O conteúdo de hoje é a continuação do apresentado na semana passada, quando iniciamos o tópico  “Programação Java Básico para Desenvolvimento Android, Parte 1”.

O fato é que para ser um bom desenvolvedor Android, você precisa entender bem sobre programação Java. Isso pode soar estranho, mas é verdade. A arquitetura de aplicativos Java é muito diferente de aplicativos para Android, mas a linguagem é a mesma. Você precisa dominar a linguagem em si e aplica-la a cada tipo de projeto. É por isso que expliquei os conceitos básicos de programação Java para desenvolvimento Android na Parte 1 desta série, onde cobrimos os tipos de dados, variáveis e métodos.

Nesse post continuarei com mais informações sobre a linguagem de programação Java, falando sobre classes, objetos, condicionais e loops.

Comentários

Em alguns dos exemplos de código abaixo eu vou fazer anotações no código usando comentários. Comentários em código Java são linhas de código que não têm qualquer efeito sobre a forma como o programa é executado. Eles são meramente informativos, destinado a nos ajudar a compreender como funciona o código ou como é organizado.

Comentário Simples

Comentários simples começam com duas barras: // . Tudo na linha após as barras torna-se comentário e é completamente ignorado pelo programa.

// Este é um comentário de uma única linha
 String codigo = "12353454"; // Somente esta parte é um comentário

Comentário Múltiplo

Às vezes queremos comentários mais longos que se estendem por mais de uma linha. Nesse caso, use um marcador de abertura para marcar o início do comentário: /* , e um marcador de encerramento para marcar o fim do comentário: */ .

/ * Este é um comentário multi-line. Embora apenas a abertura
 * E marcadores de fechamento são obrigados, muitas vezes adicionar um
 * Asterisco no início de cada linha para torná-lo
 * Mais legível, e terminar o comentário com o
 * Marcador em uma nova linha.
 * /

Classes e Objetos

Em geral, os arquivos de código em Java são organizados como classes. Um arquivo (com extensão .java) geralmente contém uma definição de classe, e ele é compilado em um arquivo de classe (com extensão .class).

Lembre-se da Parte 1 em que expliquei que a linguagem de programação Java é orientada a objetos, isso significa que ele é construído em torno do conceito de objetos. Os objetos podem ser representações de objetos físicos, como uma caneca, ou objetos mais abstratos, como uma conexão para um site.

A classe se destina a definir um objeto e como ele funciona. Deste modo, uma classe é como um modelo de um objeto. As classes definem coisas sobre objetos como propriedades e as habilidades do objeto são definidos como métodos.

Vamos dar uma olhada em uma classe que poderia ser usada para representar uma simples conexão para um site:

public class URLConnection {
    // Variáveis de classe (propriedades do o objeto)
    private String url;
    // Métodos (habilidades do objeto)
    public void setURL(String url) {
        this.url = url;
    }
    public void connect () {
       // Código para fazer uma conexão HTTP
    }
}

Neste exemplo temos uma variável de classe, url que representa a URL que esse objeto se destina a conectar. Podemos ver que no método setURL() usamos na frente da variável a palavra-chave this, isso serve para diferenciar a variável de escopo de classe com a variável que vem por parâmetro no método.

Temos dois métodos, o primeiro é chamado setUrl() e é usado para definir a variável de classe url, e o segundo é chamado connect() e seria onde vai o código para estabelecer uma conexão com a url.

Modificadores de Acesso

Para as classes, variáveis de classe, e métodos, normalmente queremos especificar quem pode acessá-los. Em alguns casos, queremos que as coisas fiquem disponíveis publicamente, o que significa que qualquer um pode ver e utilizar as variáveis e métodos.

Outras vezes, a gente quer manter as coisas privadas para proteger os dados do mundo exterior ou alterações acidentais. As palavras-chave public , private e protected são modificadores de acesso que controlam quem pode acessar a classe, variável ou método.

MODIFICADORES DE ACESSO MESMA CLASSE MESMO PACOTE SUBCLASSE OUTROS PACOTES
public SIM SIM SIM SIM
protected SIM SIM SIM NÃO
private SIM NÃO NÃO NÃO
nenhum modificador de acesso SIM SIM NÃO NÃO

Pacotes

As classes são freqüentemente agrupadas em pacotes. Um pacote é simplesmente uma coleção de classes relacionadas e são geralmente denominados em um formato que segue a notação de domínio reverso, ou seja, uma URL, como de um site, invertida: androidpro.com.br para br.com.androidpro.

Condicionais

Uma das coisas mais básicas de todas as linguagens de programação é o poder de verificar condições e, em seguida, fazer alguma coisa, se a condição for satisfeita. Em Java conseguimos isso usando a condicional if, que verifica a condição booleana como “true” e “false”.

if (nome.equals ("Fillipe Cordeiro")) {
 isAndroidPro = true;
}

Começamos com a palavra-chave if , e a condição de teste está cercada por parênteses. Se a condição for atendida, em seguida, o código dentro das chaves é executado. Java, como muitas outras línguas, usa chaves para começar e terminar blocos de código como este.

Se quisermos tomar alguma ação, se a condição não for atendida, então podemos usar a palavra-chave else para especificar o que o código deve ser executado, como no exemplo a seguir:

if (nome.equals ("Fillipe Cordeiro")) {
 ehAndroidPro = true;
} else {
 ehAndroidPro = false;
}

Além disso, podemos aninhar muitas condições juntas com else if , como este:

if (nome.equals ("Fillipe Cordeiro")) {
 ehAndroidPro = true;
} else if (nome.equals ("Joaozinho")) {
 ehJaveiro = true;
} else {
 naoEhProgramador = true;
}

Explicação Extra

Dependendo de sua experiência com a programação, você pode estar se perguntando por que  usar o método equals() em vez de dois sinais igual, por exemplo if (nome == “Fillipe Cordeiro”). A razão é porque em Java, utilizando dois sinais de igual para objetos String não compara os valores reais dos objetos , só se compara se as referências são iguais, o que geralmente não é o que nós estamos tentando para comparar.

Arrays

Arrays são estruturas usadas para organizar várias partes de dados ou outras variáveis. Basicamente são listas estruturadas em que cada parte de dados é referenciado pela sua posição na matriz.

Array

Veja este exemplo de uma lista de aplicativos. Podemos pensar nos nomes dos aplicativos na gaveta como itens de uma matriz. O primeiro item da matriz, Gmail, está no índice 0. O segundo, Docs, está no índice 1, e assim por diante até o último, Web, no índice 4. O comprimento dessa matriz (ou o número de itens) é 5.

Quando declaramos uma variável de matriz, é preciso especificar o tipo dos itens de dados que estará na matriz. Por exemplo, se vamos usar uma matriz para armazenar uma lista de nomes, então teremos que declará-la como um array de String.

A declaração de matrizes é semelhante à declaração de variáveis; nós simplesmente precisamos adicionar colchetes após o tipo de dados, como este:

String [] appNomes;

Podemos inicializar uma matriz em uma etapa ou várias etapas. Em um passo, nós simplesmente definimos todos os elementos do array entre chaves, como estes dois exemplos:

String [] cores = { "Vermelho", "Amarelho, "Preto"};
int [] idades = {18, 24, 33};

Se queremos carregar os dados na matriz em um momento posterior, temos que especificar o tamanho da matriz. Itens específicos na matriz são acessados e / ou atribuídas usando o índice do array.

O índice é especificado entre parênteses após o nome da matriz. Arrays em Java começam com índice zero, de modo que o primeiro item de uma matriz é na posição zero e é referenciado assim:

String [] appNomes = new String [5];
appNomes [0] = "Gmail";
appNomes [1] = "Docs";
appNomes [2] = "Apps";
appNomes [3] = "Jogos";
appNomes [4] = "Web";
String primeiroApp = appNomes [0]; // primeiroApp será "Gmail"

A quantidade de itens de um array é igual ao seu comprimento. O objeto Array tem uma propriedade chamada length que retorna este número:

int numeroDeApps = appNomes.length; // Será de 5

Loops

Loop através de coleções ou conjuntos de coisas é outro comando básico de programação. Por exemplo, vamos dizer que queremos percorrer essa lista de nomes de aplicativos da seção Arrays acima e mostrar na tela. Se fizéssemos isso, um por um, o código ficaria assim:

Log.d(“ANDROIDPRO”, appNomes [0]);
Log.d(“ANDROIDPRO”, appNomes [1]);
Log.d(“ANDROIDPRO”, appNomes [2]);
Log.d(“ANDROIDPRO”, appNomes [3]);
Log.d(“ANDROIDPRO”, appNomes [4]);

E se tivermos centenas de nomes? Ou se estamos lidando com milhões de registros de um banco de dados? E se a gente percorrer 20 linhas de código para cada registro no banco de dados? Isso é um monte de código para escrever.

A solução é fazer um loop através de um array (ou qualquer coleção que você está lidando) para executar um código para cada item da coleção. Vamos reescrever o código acima um pouco diferente.

O Loop “for”

for (int i = 0; i < appNomes.length; i ++) {
 Log.d(“ANDROIDPRO”, appNomes [i]);
}

Vamos examinar essa sintaxe, porque há um monte de coisas aqui que você nunca viu antes. A idéia básica é a seguinte: “para (algumas condições) fazer o código dentro destas chaves”:

for (inicializar declaração; compara declaração; incrementa declaração) {
 // Código a ser executado a cada passo do ciclo
}

Este tipo de loop, muitas vezes utiliza uma variável de contador (chamado “i” para “index” em nosso exemplo acima), que mantém o controle de nossa posição na coleção.

Inicializar Declaração

A primeira instrução dentro do parêntese configura a variável do contador ou qualquer mecanismo que será usado para manter o controle de nossa posição no loop. No nosso exemplo, a variável “i” é definido como 0, o primeiro índice do array appNomes.

Comparar Declaração

A próxima declaração dentro dos parênteses (separados por ponto e vírgula) nos diz quando este ciclo deve parar o processamento e fazer a saída para a próxima linha de código após a chave de fechamento.

Em nosso exemplo, queremos continuar contanto que “i” é menor do que o número de itens na matriz. Desde há 5 itens na matriz, mas o último item está no índice 4 (porque começa em 0), nós queremos parar uma vez que i supera 4. Caso contrário, vamos ter uma ArrayIndexOutOfBoundsException.

Incrementar Declaração

Essa última afirmação (mais uma vez separados por um ponto e vírgula) define como o nosso contador vai mudar depois que cada passo é executado. No nosso exemplo, estamos a utilizar um atalho especial “incremento”, que adiciona um para um valor inteiro. ++ pode ser usado para incrementar uma variável por um, e pode ser utilizado para diminuir uma variável por um.

Temos de ter cuidado na definição dessas condições. E se a gente diminuir nosso contador ao invés de incrementá-lo, nossa condição nunca é cumprida? Em tais casos, o nosso programa ou aplicativo vai ser pego no que é conhecido como um “loop infinito”.

O loop nunca vai sair e nosso programa irá usar todos os recursos indefinidamente, o que levará a um acidente, congelar, ou “aplicativo não está respondendo (ANR)” no Android.

O Loop”while”

Uma alternativa para o loop for é um loop while, que executa o código enquanto uma condição for satisfeita. A maior diferença é que nós precisamos definir como o loop percorre a coleção no código entre as chaves, em vez de ser uma declaração dentro dos parênteses, onde o ciclo é iniciado.

Note as três instruções dentro do loop for: a linha 1 é a declaração de inicialização, a linha 2 contém a instrução de comparação, e linha 4 é o incremento da declaração. A sintaxe geral é como se segue:

while (condição) {
 // Código para executar
}

Cada tipo de loop muitas vezes pode ser reescrita como outra, de modo que, basicamente, podemos escolher o que faz mais sentido para a forma como queremos o loop. Às vezes é mais fácil escrever um ou outro com base nos dados que estamos trabalhando.

O Do-while

Semelhante ao loop while, o do-while é diferente na medida em que verifica a condição na parte inferior do loop em vez do topo. Isso garante que o código dentro do loop será executados pelo menos uma vez.

Se a condição não for atendida na primeira passagem do loop, o while vai pular o código dentro das chaves, mas o do-while irá processar o código e, em seguida, seguir em frente.

int i = 0;
do {
  Log.d(“ANDROIDPRO”, appNomes [i]);
  5++;
} While (i < 5)

O Loop for-each

Às vezes, esses lopps e condições podem ser bem feios de serem escritos. Felizmente, o Java contém ainda uma outra maneira de escrever um loop quando você quiser interagir sobre uma coleção de itens. A idéia por trás de um loop for-each é que você deseja executar um código para cada item da coleção.

for (String nome: appNomes) {
   Log.d(“ANDROIDPRO”, nome);
}

O for-each substitui as três condições do laço for com uma declaração simplificada. O lado direito do dois pontos “:” é a matriz ou coleção a ser percorrida completamente, e o lado esquerdo é uma variável temporária usada para guardar o item na iteração atual do loop.

Assim, neste exemplo temos uma seqüência de cada item na matriz appNomes e o valor é armazenado em uma variável temporária chamada “nome“. Podemos ler isso como “para cada nome em appNomes, faça o código nestas chaves”.

Tratamento de Erros

Lembre-se que mencionei ArrayIndexOutOfBoundsException no tópico acima? O Java fornece uma forma para fazer o tratamento de todos os tipos de erros em nossos programas.

A idéia básica é que, se algo de ruim acontece em nosso programa ou aplicativo, o sistema de execução do Java vai levantar uma pequena bandeira que diz que algo está errado. Se estamos de olho nessas bandeiras podemos tratá-las adequadamente e evitar que nossos usuários passem por uma má experiência.

O ato de levantar esse bandeirinha é chamado de lançar uma exceção, e temos de pegá-las no código em nosso aplicativo. Vamos usar um exemplo para ilustrar:

String url = "https://www.androidpro.com.br";
try {
  URL blogUrl = new URL (url);
} catch (MalformedURLException e) {
  Log.e (“ANDROIDPRO”, "Erro ao criar um objeto de URL com " + url);
}

Ok, então o que está acontecendo nesse código? Até agora, temos visto código que executa normalmente na tela principal do programa. Se todas as exceções são lançadas nesta situação, isso é muito grave e o aplicativo irá falhar. Mas, muitas vezes, existem métodos que queremos usar lançam exceções menos graves, e não estamos autorizados a ignorá-los.

Nesses casos, é preciso colocar esse código dentro de um bloco try, como nas linhas 2-4. Neste exemplo, o construtor URL lança um MalformedURLException se uma URL inválida é passada como parâmetro de entrada. Se você  não capturar essa exceção, então o nosso código não irá compilar.

O bloco catch requer o tipo de exceção a ser capturado e é declarado como uma variável dentro dos parênteses após a palavras-chave catch. Então, como de costume, o código a ser executado em caso de exceção fica entre as chaves.

Se nós precisamos verificar se há várias exceções, como se tentou abrir uma conexão HTTP utilizando blogUrl, que lança uma IOException , então podemos encadear declarações catch um sobre o outro, como este exemplo:

try {
   // Algum código
 } catch (MalformedURLException e) {
   Log.e (“ANDROIDPRO”, "Houve um erro na criação de um objeto URL.";
 } catch (IOException e) {
   Log.e (“ANDROIDPRO”,  "Erro ao conectar ao site.");
}

Finalmente, há mais um bloco de código que pode ser colocado a essa seqüência: o bloco finally. Este é o lugar onde nós colocamos o código que queremos executar mesmo que uma exceção é lançada.

No exemplo abaixo, vamos abrir uma conexão com um arquivo para escrever e queremos ter certeza de que vamos fechá-lo, não importa o que aconteça. Caso contrário, essa conexão pode ser aberta por tempo indeterminado:

Writer writer;
try {
  writer = new OutputStreamWriter (new FileOutputStream ("out.txt"));
  writer.write ("AndroidPro estava aqui.");
} catch (IOException e) {
  Log.e (“ANDROIDPRO”, "Erro ao escrever no arquivo.");
} finally {
 if (writer! = null) {
   writer.close ();
 }
}

* Observe que o writer variável será nulo se uma exceção foi acionada ao tentar inicializar-lo. Assim, é preciso verificar se é nulo ou não, porque nós só queremos fechá-lo se ele foi inicializado.

Conclusão

Dominar os conceitos básicos abordados aqui e na Parte 1 será um longo caminho para ajudar você a ser um bom programador em geral e, especialmente, para o desenvolvimento do Android. Se você quiser ir mais longe com a aprendizagem Java, a Oracle tem alguns tutoriais sobre todos os tipos de conceitos relacionados com a programação Java.

Espero que tenham gostado desse conteúdo e estejam um passo a frente em sua jornada para se tornar um desenvolvedor.

Continuem ligados, nas próximas semanas dividirei conteúdos ainda melhores para àqueles que querem fazer parte de um dos setores mais promissores da atualidade!

Deixe suas duvida aqui nos comentários que irei responder todas. As suas duvidas podem ser as duvidas de outras pessoas.

Até a próxima!!!

Leia também


Fillipe Cordeiro
Fillipe Cordeiro

Engenheiro da computação e desenvolvedor de software a quase 10 anos, com experiência em tecnologias como Java, Python e Android. Agora, quero te ajudar a mergulhar no universo do Desenvolvimento Android.