Ensinando Java a Programadores PHP

Atenção! Essa postagem foi escrita há mais de 2 anos. Na informática tudo evolui muito rápido e algumas informações podem estar desatualizadas. Embora o conteúdo possa continuar relevante, lembre-se de levar em conta a data de publicação enquanto estiver lendo. Caso tenha sugestões para atualizá-la, não deixe de comentar!

PHP e Java

Então você quer aprender Java mas só tem experiência de programação com o PHP? Esse texto é pra você!

Não é segredo pra ninguém que atualmente os profissionais precisam conhecer mais de uma tecnologia. Precisamos estar abertos a novidades e, te prometo, que aprender uma nova linguagem não tira pedaço. Pelo contrário, saber mais de uma linguagem, além de deixar o seu cérebro mais afiado, ainda te dá um currículo mais pesado e maior probabilidade de conseguir um bom emprego.

Como uma das linguagens mais utilizadas para programação Android é o Java, muitos estão tentando assimilá-la ultimamente. Neste artigo tentarei cobrir tudo que alguém que sabe apenas PHP precisaria saber para detonar no Java. Dê uma boa lida no material que segue e responderei algumas questões ao longo do caminho.

Java é uma linguagem fortemente tipada

Talvez você não esteja acostumado com o conceito de “declarar” variáveis. No Java você precisa declará-las antes de utilizar.

[java]DatabaseRecord foo;
foo = new DatabaseRecord();[/java]

Na linha 1 declaramos a variável apenas especificando seu tipo (assim podemos nos assegurar de que a variável foo conterá apenas um objeto do tipo DatabaseRecord). Na linha seguinte, criamos um novo objeto DatabaseRecord e o atribuímos a banco. Você também pode fazer isso tudo em uma linha apenas:

[java]DatabaseRecord foo = new DatabaseRecord();[/java]

Aqui quando foo é declarada, qualquer valor que for atribuído a esta variável deve ser do tipo DatabaseRecord. E daqui em diante, você só poderá atribuir valores do tipo DatabaseRecord para a variável foo, enquanto no Mundo do PHP você poderia colocar uma string em uma variável na qual havia um objeto apenas alguns segundos atrás.

Então, o código PHP a seguir é válido:

[php]$foo = new Bar();
$foo = "Bla bla bla";[/php]

Mas o equivalente não é válido em Java:

[java]DatabaseRecord foo = new DatabaseRecord();
foo = "Bla bla bla";[/java]

Até métodos precisam ter o tipo do retorno especificado:

Em PHP:

[php]class myClass {
public function getName() {
return "Rafa Jaques";
}
}[/php]

Em Java:

[java]class myClass {
public String getName() {
return "Rafa Jaques";
}
}[/java]

É importante perceber que você não deve especificar que é uma função. Para funções que não retornam nenhum valor ou retornam apenas com “return;”, utilize void no lugar de String.

Propriedades do objeto são chamadas de fields

No PHP os objetos possuem propriedades:

[php]class myClass {
public $foo = ‘bar’;
protected $_bar = ‘baz’;
}[/php]

Em Java existem fields (campos). A sintaxe é similar e você precisa especificar um tipo para cada field.

[java]class myClass {
public String mFoo = ‘bar’;
protected String mBar = ‘baz’;
}[/java]

Uma convenção que eu vi nos códigos de exemplo pra Android foi preceder cada um desses fields com a letra ‘m’ (de ‘Member Field’). Eu achei bem útil para identificar quais variáveis são fields do atual objeto, especialmente se você levar em conta o próximo ponto.

Você não utiliza this muito frequentemente

Quando estiver acessando propriedades no Java, você não utiliza $this.

No PHP você faria:

[php]class myClass {
protected $_bar = ‘baz’;

public function getBar() {
return $this->_bar;
}
}[/php]

No java não é obrigatório usar o this para esses casos.

[java]class myClass {
protected String mBar = ‘baz’;

public String getBar() {
return mBar;
}
}[/java]

A única vez que você realmente precisa do this é quando ocorre uma colisão de nomes e acaba não ficando muito claro qual variável você está referenciando. Vejamos um exemplo:

Em Java:

[java]class myClass {
protected String mBar = ‘baz’;

public String getBar(String mBar) {
return this.mBar; // especifique o "this" para acessar o field mBar
// em vez do mBar que foi passado como parâmetro
// para o método
}
}[/java]

Annotations (ex.: @override)

Quando você começar a sobrecarregar métodos, perceberá um @override antecedendo os métodos que são sobrescritos (geralmente a IDE coloca isso lá).

Essas anotações servem para fazer Reflection (falarei mais sobre isso a seguir). Como é um assunto bastante extenso, não vou explicar em detalhes o que é aqui, mas deixo um link para que você possa aprofundar seus estudos sobre annotations e reflection.

Você pode criar as annotations que quiser por qualquer motivo que der na telha e depois acessar annotations de um método específico usando reflection.

Aqui está um exemplo da utilização de annotations:

[java]class MyActivity extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
}[/java]

Reflection – “O que é Object.class?”

Cada classe que você declara essencialmente estende a classe Objeto. Essa classe lhe dará um punhado de métodos e fields padrão. Um deles é o membro estático acessado via NomeDaClasse.class cujo o objetivo é retornar o objeto Classe.

Esse objeto classe descreve seu objeto e possui vários métodos para explorá-lo. Por exemplo: você pode utilizá-lo para verificar quais annotations um método possui, ou pode também passar informações para que outro método saiba qual classe criar.

Você deve ver algo parecido com isso:

[java]String someObject = "Uma string";
Intent i = new Intent(someObject, MyActivity.class)[/java]

Esse código cria um novo objeto Intent, passando um objeto string e depois passando um objeto Classe do field estático MyActivity.class. Por exemplo: internamente o objeto Intent pode utilizar o objeto Classe para criar um novo objeto MyActivity pois o objeto dessa classe possui um método newInstance().

Parênteses angulares genéricos em Java

Se por acaso você ver algo do tipo, poderá ficar um pouco confuso:

[java]List<Integer> = new LinkedList<Integer>();[/java]

São conhecidos como generics e permitem a você indicar ao objeto List que tipo de objeto ele estará armazenando.

Se quiser ler mais sobre generics, recomendo dar uma lida neste link, pois possui um tutorial bem detalhado.

Arrays não são mais a solução

Em Java você não irá achar arrays tão úteis quanto no PHP no qual você pode declarar um array sem especificar tamanho, tipo ou qualquer outra coisa.

Quando criar arrays em Java você precisará especificar o tamanho e só poderá atribuir valores de um mesmo tipo de objeto (tudo string ou tudo integer, por exemplo).

Então em PHP teríamos:

[php]$stringArray = array(‘Um’, ‘Dois’, ‘Três’);[/php]

Em Java:

[java]String[3] stringArray;
stringArray[0] = "Um";
stringArray[1] = "Dois";
stringArray[2] = "Três";[/java]

Perceba que declara-se um array colocando parênteses quadrados (colchetes) contendo o tamanho do array. Então você poderá acessar esses, e apenas esses, três elementos.

Se quiser uma lista de objetos de tamanho não especificado, provavelmente você quer uma lista encadeada: LinkedList. A utilização é como segue:

[java]LinkedList myList = new LinkedList();
myList.add(new MyObject());
myList.add(new MyObject());
myList.add(new MyObject());[/java]

Esse snippet adiciona três objetos MyObject à lista. O jeito mais simples de percorrer uma lista encadeada é utilizando a sintaxe do foreach, que é semelhante à do PHP. Utilizar um loop com myList.size() também funciona.

Para interagir utilizando o foreach, você precisa trabalhar sobre algo que implemente a interface Collection. Tanto List quanto LinkedList implementam essa interface, então o código ficaria mais ou menos assim:

[java]LinkedList myList = new LinkedList();
myList.add(new MyObject());
myList.add(new MyObject());
myList.add(new MyObject());

for (MyObject myobj : myList) {
myobj.doSomething();
}[/java]

Mais ou menos algo como para cada (MyObject)myObj em myList, faça isso. O equivalente em PHP seria:

[php]$myList = array();
$myList[] = new MyObject();
$myList[] = new MyObject();
$myList[] = new MyObject();

foreach ($myList as $myObj) {
$myObj->doSomething();
}[/php]

Pessoalmente eu acho que a maneira do Java faz mais sentido. No PHP parece que estamos fazendo de trás pra frente.

Arrays Associativos

Até o presente momento quando você não possuir alternativa e precisar utilizar arrays associativos, terá de apelar para hashtables.

Dê uma olhada neste link para aprender mais sobre HashTableHashMap HashCode.

Perceba também que você precisará dar cast nos objetos no caminho – os Hashtables não utilizam o mecanismo de generics para assegurar um tipo específico de dado.

Implementando interfaces com objetos anônimos

Algo que eu achei realmente muito legal (e se você já usou interfaces antes tenho certeza de que também irá gostar) é a capacidade de implementar interfaces com objetos anônimos. Em PHP, se você possui uma interface, necessita de uma declaração sólida da sua interface antes de implementá-la em uma classe.

Em Java você pode implementar uma interface na hora. Você especifica a interface que você está implementando, seguida pelo bloco de código contendo a implementação:

[java]OnClickListener myClickListener = new OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
startGame(i);
}
};[/java]

Simples, não? Parece bastante útil quando você precisa desenvolver pequenos manipuladores como esses.

Classes e Interfaces Aninhadas

No exemplo anterior eu acabei omitindo algo: o OnClickListener, na verdade, é uma interface estática aninhada. O código correto seria:

[java]DialogInterface.OnClickListener myClickListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
startGame(i);
}
};[/java]

Vou tenta explicar em miúdos. Você pode dar uma olhada no site oficial do Java (texto em inglês) e também no site da Caelum um tutorial sobre classes aninhadas.

O primeiro exemplo fala de uma classe interna comum (não uma estática como OnClickListener). Você pode ter uma declaração de classe dentro de outra classe e apenas a classe exterior poderá criar uma nova instância dessa classe interna. A seguir vemos um exemplo de classe aninhada e como ela se parece:

[java]class MyClass {
class MyInnerClass {
}

public void foo() {
MyClass.MyInnerClass innerObject = new MyClass.MyInnerClass();
}
}[/java]

Então aqui você faz uma declaração de classe interna (MyInnerClass) que apenas pode existir dentro da sua classe externa (MyClass).

Algumas vezes a classe deve estar dentro de uma outra classe mas ainda ser acessível para o mundo – está dentro de outra classe apenas por causa dos namespaces, como o exemplo do OnClickListener acima (a diferença é que ali está mais pra interface do que pra uma classe, então você deve apenas substituir class por interface).

Neste caso você deveria utilizar a palavra-chave static:

[java]class MyClass {
static class MyInnerClass {
}

public void foo() {
MyClass.MyInnerClass innerObject = new MyClass.MyInnerClass();
}
}

class MyOtherClass {
public void foo() {
MyClass.MyInnerClass inner = new MyClass.MyInnerClass();
}
}[/java]

Perceba que nesse caso a classe interna pode residir totalmente dentro de outra classe. Não precia estar dentro de MyClass.

Considerações Finais

Muitas dessas peculiaridades do Java, que podem ser consideradas implementações mais puras da orientação a objetos, podem ser integradas ao novo PHP 6. Caso você queira dar uma olhada no que vem por aí dentro do PHP, sugiro que leiam meu outro artigo: O que há de novo no PHP 5.4? Conheça as mudanças mais significativas.

Espero que essas experiências possam ajudá-los a melhorar suas aptidões em novas linguagens e, assim, não ficar parado no tempo. É importante nunca parar de estudar e aperfeiçoar-se cada vez mais.

Aproveitem os comentários para exporem suas dúvidas e contribuírem com a discussão.

Um abraço a todos e fiquem com Deus!

Texto adaptado do original: http://www.searbe.co.uk/moving-from-php-to-java