O que é o Groovy?

O Groovy é uma linguagem de programação orientada a objetos e foi projetada para rodar na Java Virtual Machine (JVM), o que faz com que ela seja multiplataforma. Isso quer dizer que o esmo código Groovy pode ser executado no Windows, Linux, Mac ou outro, bastando que a máquina possua uma JVM para interpretá-lo, podendo assim rodar o código feito com Java. Além disso ele também tem semelhanças com a linguagem Ruby, pois também permite modificar o código da aplicação em tempo de execução. Esse recurso chama-se metaprogramação e com isso podemos, por exemplo, adicionar um método em uma determinada classe enquanto a aplicação está sendo executada.

A seguir veremos como começar a trabalhar com essa linguagem e seu console próprio.

Instalação

Antes de baixar e instalar o Groovy lembre-se que é necessário ter o Java instalado, por isso, se sua máquina não o possuir acesse o link Download e Instalação do Java encontrado na seção Links e então siga os passos de instalação descridos no site da própria Oracle, que distingue um pouco para cada S.O.

Em seguida podemos partir para a instalação do Groovy: neste artigo utilizaremos a versão 2.4 para execução dos exemplos. Para baixá-lo acesse o endereço eletrônico Download do Groovy encontrado na seção Links e faça o download do arquivo zip e em seguida descompacte o conteúdo em uma pasta que preferir.

Depois disso é necessário configurar duas variáveis de ambiente para que os comandos do Groovy possam ser encontrados a partir do terminal ou prompt de comando. São elas: GROOVY_HOME e PATH. O processo de configuração dessas variáveis difere dependendo do sistema operacional usado. As seções a seguir fornecem instruções para a configuração em ambientes Windows e Linux.

Variáveis de ambiente – Windows

A configuração de variáveis de ambiente no Windows pode ser feita com os seguintes passos:

  • Em “Meu Computador” escolha a opção propriedades do sistema;
  • Acesse a aba “Definições Avançadas do Sistema” e escolha “Variáveis de ambiente”;
  • Crie uma nova variável de ambiente chamada GROOVY_HOME. O valor desta deve ser o caminho para o diretório onde o Groovy foi descompactado, por exemplo, “C:/Arquivos de Programas/Groovy-2.4.5”;
  • Em variáveis de sistema localize a variável PATH e clique nela. Então edite seu valor adicionando ao final “;GROOVY_HOME”, como mostra a Figura 1:
Configuração da
variável de ambiente PATH no Windows
Figura 1. Configuração da variável de ambiente PATH no Windows.

Variáveis de ambiente – Linux

Em ambientes Linux essa configuração é mais simples, apenas sendo necessário adicionar duas linhas em um arquivo de inicialização. Por exemplo, no sistema operacional Ubuntu basta adicionar as linhas apresentadas na Listagem 1 no arquivo /etc/bash.bashrc.

Listagem 1. Configuração de variáveis de ambiente.


  JAVA_HOME={DIRETORIO_DE_INSTALAÇÃO_DO_JAVA}
  GROOVY_HOME={DIRETORIO_DE_INSTALAÇÃO_DO_GROVY}
   
  export JAVA_HOME
  export GROOVY_HOME
   
  export PATH=$PATH:$JAVA_HOME/bin:$GROOVY_HOME/bin:$GRAILS_HOME/bin

Para testar se a instalação ocorreu de forma bem-sucedida, tanto no Windows como no Linux, digite no prompt de comando ou terminal a instrução apresentada a seguir:

Groovy --version

Esse comando deve ter como resultado a versão do Groovy que foi instalada, como exibido a seguir:

Groovy Version: 2.4.5 JVM: 1.8.0_40 Vendor: Oracle Corporation OS: xxxx

Caso contrário, reveja os passos para instalação.

Groovy console

Agora já é possível analisar algumas ferramentas interessantes que estão disponíveis como, por exemplo, o Groovy console. Para acessá-lo basta digitar no terminal o comando Groovyconsole e uma nova janela será apresentada, como mostra a Figura 2. Para o Windows, basta ir em Programas >Groovy> GroovyConsole.

Console do
Groovy
Figura 2. Console do Groovy.

O Groovy Console é uma ferramenta semelhante ao irb (interactive ruby) da linguagem Ruby, pois ambos são considerados REPL's (READ EVEL PRINT LOOP – LEIA INTERPRETE IMPRIMA REPITA). Com ele é possível executar rapidamente o código, recebendo os resultados logo abaixo. Vejamos um exemplo a seguir, onde construímos o famoso Hello World:

println(“Hello World”)

Após digitar o código clique no ícone executar (run) ou utilize o atalho Ctrl + R e perceba que a saída é mostrada no quadro inferior do console, conforme mostra a Figura 3.

Hello Word
Figura 3. Hello Word

Como o Groovy também pode executar código Java, o exemplo anterior poderia ter sido escrito nessa linguagem que também rodaria.

Tipagem dinâmica e estática

A definição dos tipos de variáveis no Groovy pode acontecer dinamicamente ou de modo estático, ou seja, definir o tipo das variáveis no Groovy é opcional. Veja na Listagem 2 um código feito no Groovy Console que define algumas variáveis utilizando esses dois conceitos. Após a definição de cada uma, o método .class é chamado para recuperar o tipo da variável criada.

Listagem 2. Definição de variáveis utilizando tipagem dinâmica e estática.


  int i = 10
  println(i.class)
   
  long l = 100000000000000000000
  println(l.class)
   
  d = 10.0
  println(d.class)
   
  s = "olá, estamos estudando Groovy!"
  println(s.class)

Note que a saída deste código, apresentada a seguir, não tem definido os tipos explicitamente para as variáveis “d” e “s”, pois o Groovy inferiu os seus tipos:


  => class java.lang.Integer
  => class java.lang.Long
  => class java.math.BigDecimal
  => class java.lang.String

Perceba também que não há tipos primitivos no Groovy, já que as classes Wrappers do próprio Java são usadas para definir os tipos de variáveis, como aconteceu com as variáveis “i” e “l”.

Definição de métodos em Groovy

Os métodos em Groovy também são mais simples de definir do que no Java, pois não é necessário explicitar o tipo de retorno, nem mesmo usar a instrução return para retornar um valor para o chamador. Assim, quando essa instrução não é usada o último valor avaliado será retornado. Veja na Listagem 3 a definição de alguns métodos.

Listagem 3. Definição de métodos em Groovy.


  def int aoQuadrado(int numero){
      return numero * numero
  }
   
  println("2² = " + aoQuadrado(2))
   
  def somar(operador1, operador2){
      operador1 + operador2
  }
   
  println("2 + 10 = " + somar(2, 10))

Perceba a diferença entre os dois métodos: o método “aoQuadrado” definiu na sua assinatura o tipo de retorno (int)e também fez uso da instrução return para retornar à multiplicação da variável numero. Mas isso é opcional, já que o método “somar” não define o tipo de retorno nem mesmo usa a cláusula return para devolver o valor. Ele funcionou perfeitamente apresentando o resultado esperado:


  => 2+10 = 12
  => 2² = 4

Strings no Groovy

Strings são indispensáveis em qualquer linguagem de programação, pois sempre é necessário lidar com caracteres, frases de aviso, resultados de execução ou textos vindos de uma requisição. No Groovy existem três tipos de Strings disponíveis:

  1. delimitada por aspas simples;
  2. delimitada por aspas duplas;
  3. delimitada por três aspas duplas.

Veja na Listagem 4 o uso de cada umas delas.

Listagem 4. Exemplo do uso de Strings em Groovy.


  simples = 'olá, sou uma string simples delimitada por aspas simples'
   
  a = 1
  b = 2
  c = 3
   
duplas = 'Hello, sou uma string delimitada por aspas duplas, aceito interpolação(concatenação) de variáveis. ${a}, ${b}, ${c}'
   
  stringComQuebraDeLinhas = """Oi, 
    sou uma string delimitada por três aspas duplas seguidas.
    Também posso interpolar valores mas,
    a minha principal vantagem é que posso ser quebrada em várias linhas"""

A primeira string que está entre aspas simples é a que usa menos recursos: ela é mais amplamente usada no desenvolvimento de aplicações onde o desempenho é algo crítico, já que esse tipo de string utiliza menos memória.

A segunda string apresenta a funcionalidade de interpolação ou concatenação: ela permite incluir valores de outras variáveis usando o operador ${}.

Já a terceira string, além de permitir a interpolação de valores, pode ser quebrada em várias linhas sem ter que usar o operador “+” para concatenar as demais linhas. Esse terceiro tipo de string deixa o código mais legível, como mostra a Listagem 5, onde temos a definição da variável stringComQuebraDeLinhas utilizando o Java.

Listagem 5. Definição de string com quebra de linha no Java.


  StringComQuebraDeLinhas = “Oi,”
     + “sou uma string delimitada por três aspas duplas seguidas.”
     + “Também posso interpolar valores mas,”
     + “a minha principal vantagem é que posso ser quebrada em várias linhas”

Uma vantagem do Groovy usar classes do próprio Java é que todos os métodos das suas classes estão, naturalmente, disponíveis. Veja na Listagem 6 um código executando alguns métodos conhecidos da classe java.lang.String do Java.

Listagem 6. Uso de alguns métodos da classe java.lang.String

simples = 'olá, sou uma  string simples delimitada por aspas simples'
  println(simples.indexOf('aspas'))
  println(simples.length())
  println(simples.substring(13))

O método indexOf retorna o índice ou a posição que determinada string ou caracteres se encontra na string. O método length retorna a quantidade de caracteres contidas em uma string. Já o substring retorna uma parte ou “pedaço” de uma string baseada nos parâmetros passados. Veja o resultado da execução desse bloco de código:


  => 43  
  => 56  
  => string simples delimitada por aspas simples
  

Estruturas de controle

if / else

A estrutura if / else é usada para decidir o fluxo de execução de determinado código. Se uma condição for satisfeita (se uma condição retornar o valor true) então a parte do código relacionada com a instrução if é executada, caso contrário (se uma condição retornar o valor false), o bloco de código associado ao else é chamado. Veja na Listagem 7 um exemplo que usa o operador “>” (maior que) para verificar se a variável idade é maior ou não que 18.

Listagem 7. Exemplo da estrutura if / else.


  int idade = 19
   
  if(idade > 18){
      println("você já é adulto");
  }else{
      println("você não é adulto");
  }

Para desenvolvedores Java o exemplo mostrado anteriormente é bastante familiar, isso por que as estruturas condicionais do Groovy são bastante semelhantes às do Java, a não ser por um ponto: as variáveis nulas ou vazias, ou ainda que não referenciam nenhum objeto são avaliadas como falsas (false). Veja na Listagem 8 um exemplo de como isso acontece.

Listagem 8. Exemplo de estrutura if/ else avaliando um valor nulo.


  variavel = null
   
  if(variavel){
      println("essa variável foi avaliada como verdadeira. O seu valor é = ${variavel}");
  }else{
      println("essa variável foi avaliada como falsa. O seu valor é = ${variavel}");
  }

Operador ternário

O Groovy também dispõe de um operador condicional ternário, que funciona como um if / else em uma linha só. A sintaxe desse operador é exibida a seguir:

(condição) ? (código a ser executado caso verdadeiro) : (código a ser executado caso falso)

Veja na Listagem 9 como ficaria o código da Listagem 7 usando o operador ternário.

Listagem 9. Exemplo de uso do operador ternário.


  int idade = 19
  idade > 18 ? println("você já é adulto"):println("você não é adulto")

Switch

A estrutura switch pode ser usada em substituição a estrutura if / else quando há muitas condições. Essa estrutura também é bem semelhante a switch do Java, com algumas pequenas diferenças: uma delas é que no Groovy pode-se aplicar o switch para qualquer objeto, enquanto que no Java apenas tipos como enum, string e numéricos a serem usados. Veja na Listagem 10 a sintaxe dessa instrução.

Listagem 10. Sintaxe para a estrutura switch.


  switch(variavel_a_ser_avaliada){
   
    case [valor_1]:
      [bloco_de_codigo]
      break
    
    case [valor_2]:
      [bloco_de_codigo]
      break
    case [valor_3]:
      [bloco_de_codigo]
      break
    default:
     [bloco_de_codigo]
   
  }

O bloco switch recebe uma variável e compara o valor desta com os valores informados nos blocos case. Note na Listagem 11 um exemplo de uso dessa estrutura.

Listagem 11. Exemplo de uso da instrução switch.


  valor = 5
   
  switch(valor){
     case 1:
         println("sou igual a um")
         break
     case 2:
         println("sou igual a dois")
         break
     case 3: 
         println("sou igual a três")
         break
     case 4: 
         println("sou igual a quatro")
         break
     case 5:
         println("sou igual a cinco")
         break
     default:
         println("não sou nenhum desses valores")
  }

Caso nenhum dos blocos case retorne verdadeiro, o bloco de código atrelado a instrução default será executada, como mostra o exemplo da Listagem 12.

Listagem 12. Exemplo de funcionamento da instrução default.


  valor = 10
   
  switch(valor){
     case 1:
         println("sou igual a um")
         break
     case 2:
         println("sou igual a dois")
         break
     case 3: 
         println("sou igual a três")
         break
     case 4: 
         println("sou igual a quatro")
         break
     case 5:
         println("sou igual a cinco")
         break
     default:
         println("não sou nenhum desses valores")
  }

Também existe um ponto importante a ser esclarecido sobre a instrução break: caso ela não seja usada, isso poderá causar alguns efeitos estranhos ou indesejados. Veja por exemplo o que acontece no código exibido na Listagem 13, que não usa a instrução break em sua estrutura.

Listagem 13. Exemplo de estrutura switch sem instrução break.


  valor = 1
  switch(valor){
     case 1:
         println("sou igual a um")
     case 2:
         println("sou igual a dois")
     case 3: 
         println("sou igual a três")
     case 4: 
         println("sou igual a quatro")
     case 5:
         println("sou igual a cinco")
     default:
         println("não sou nenhum desses valores")
  }

Note agora na saída apresentada a seguir que todos os blocos case, inclusive o bloco default, foram executados:


  => sou igual a um
  => sou igual a dois
  => sou igual a três
  => sou igual a quatro
  => sou igual a cinco
  => não sou nenhum desses valores

Isso acontece porque após entrar em qualquer bloco case o fluxo só irar parar após uma instrução break ser encontrada.

Estruturas de repetição

While

As estruturas de repetição são usadas para repetir a execução de tarefas por um determinado período, ou seja, até que uma condição seja satisfeita. Uma dessas estruturas disponíveis no Groovy é o while, que executa determinado bloco de código enquanto uma condição for satisfeita, ou retornar true. Note na Listagem 14 como a sua sintaxe é simples.

Listagem 14. Sintaxe da estrutura while.


  while(condicao){
      [bloco_de_codigo_a_ser_executado]
  }

Veja agora na Listagem 15 o uso dessa estrutura para imprimir os algarismos pares encontrados de 1 a 20.

Listagem 15. Exemplo de uso da instrução while.


  int i = 1
   
  while(i <= 20){
   
      if(i % 2 == 0){
          print "${i} "
      }
   
      i = i + 1;
   
  }

Perceba que as estruturas da instrução while ficam separadas: a inicialização da variável, a condição e o incremento. Isso talvez dificulte a leitura do código, então o for pode ser usado neste caso, deixando essas estruturas mais legíveis.

For

A instrução for representa uma maneira diferente de construir loops, deixando tudo in-line (na mesma linha), o que o torna mais limpo ou legível que o while. A sintaxe para o for está apresentada a seguir:


  for([inicialização_de_variável], [condição_para_execução], [incremento_do_contadot]){
              [bloco_de_código_a_ser_executado]
  }

Perceba que a inicialização do contador, a condição e o incremento ficam na mesma linha.

Note agora na Listagem 16 o uso dessa estrutura para imprimir os algarismos ímpares encontrados no intervalo de 1 a 20.

Listagem 16. Exemplo de uso da instrução for.


for(int i= 1; i <= 20; i++){
   
  if(!(i % 2 == 0)){
    print("${i}, ");
  }
   
}

O for também pode ser usado facilmente para percorrer objetos que representem intervalos como os ranges. Ranges são intervalos definidos de objetos numéricos, e podem ser definidos de duas formas:

intervalo1 = 1..<10
  intervalo2 = 1..10

O operador “<” pode ser usado para indicar que o último número não deve ser incluído. O range ou intervalo que foi armazenado na variável intervalo1 vai de 1 até 9, enquanto o armazenado na variável intervalo2 varia de 1 até 10.

Veja na Listagem 17 como percorrer usando a instrução for sobre esses ranges.

Listagem 17. Percorrendo em um range utilizando o for.


  intervalo1 = 1..15
  for(int i = 0; i < intervalo1.size(); i++){
      print "${intervalo1[i]}, "
  }

Há ainda uma maneira mais fácil para percorrer ranges ou estruturas semelhantes utilizando o for: veja na Listagem 18 uma forma de se fazer isso tendo o mesmo efeito da maneira convencional.

Listagem 18. Percorrendo em um range com um for simplificado.


  intervalo1 = 1..15
  for(i in intervalo1){
      print "${i}, "
  }

Note que neste caso não foi necessário definir uma condição de parada de execução, nem mesmo uma seção para incremento da variável. Isso foi encapsulado pela estrutura for. Ela apenas passou a pegar cada elemento no range e armazenar na variável i, que foi impressa até que não houvessem mais valores para na variável intervalo1 a serem mostrados.

Essa foi uma breve introdução aos recursos da linguagem Groovy. Por essa pequena explanação com certeza já nota-se algumas vantagens em se utilizar o Groovy: uma delas é o fato de que todo código Groovy é executado pela JVM, amplamente difundida atualmente. Outra vantagem considerável é que código Java pode acessar o código Groovy e vice-versa, podendo incluir algumas instruções Java nas classes Groovy. Ainda outro ponto importante é a tipagem forte e dinâmica da linguagem e a sua simplicidade.

Espero que tenham gostado e até a próxima.

Referências:
Apache Groovy