# Java/Imprimir

* Esta é a versão para impressão de Java
* Se você for imprimir esta página, escolha "Visualizar impressão" no seu navegador, ou clique em Versão para impressão, você irá ver esta página sem esse aviso, sem os elementos de navegação a esquerda ou acima, e sem as TOC's de cada página.
* Atualize esta página para ter certeza de que está imprimindo a versão mais atual.
* Para maiores informações sobre a versão para impressão, incluindo como fazer arquivos PDF realmente adequados para a impressão, veja Wikilivros:Versões para impressão.

# Introdução

Java é uma linguagem de programação de alto nível e orientada à objetos criada pela empresa Sun Microsystems no começo da década de 90. A sintaxe da linguagem é muito parecida com C e C++, mas ela possui um número maior de facilidades e funcionalidades.
Por exemplo, se o programa java for feito em uma plataforma Linux, ele pode ser usado na plataforma FreeBSD ou Windows - o programa rodará sem problema nenhum desde que a JRE (Java Runtime Environment), também conhecida como Máquina Virtual Java (Java Virtual Machine) esteja instalada na plataforma.
Linguagens como C e C++ rodam em diversas plataformas, mas os programas precisam ser recompilados, o que não acontece com o Java onde o mesmo binário pode ser portado. Além disso a linguagem pode ser usada para desenvolver programas para a maioria dos celulares, PDA's (Palm Tops) além de diversos dispositivos como cartões (Vale Refeição, Vale transporte, Cartões de acesso).

## Por que aprender Java?

Dentre as características mais relevantes:
* Java tem a filosofia 'WORA'
Uma das principais características de Java é o WORA (Write Once, Run Anywhere) ou simplesmente 'Escreva uma Vez e Execute em Qualquer Lugar'. Isso por si só traz vantagens, pois poupa tempo aprendendo bibliotecas específicas de Sistemas Operacionais. Poupa dinheiro, que seria gasto neste tempo. Poupa esforço, pois muitas vezes não há a necessidade de se conhecer alguns ou vários aspectos da plataforma subjacente.
* Java possui "Coleta de Lixo" automática.
Isso significa que ela desaloca automaticamente qualquer espaço de memória não utilizado sem que o programador se preocupe com isso.
* Java é uma linguagem de alto nível
Por ser uma linguagem de alto nível Java tem constructos e características que permitem escrever programas mais rapidamente do que em C/C++. Sendo assim há uma maior produtividade. Aliado ao fato de que Java sendo uma linguagem orientada a objetos, faz Java uma ótima escolha para desenvolvimento.
* Java está presente em uma variedade de lugares
Os aplicativos Java estão presentes em diversas áreas, desde celulares, até servidores, o que dá ao desenvolvedor uma ampla gama de possibilidades de sistemas a serem desenvolvidos.
* Java tem uma boa documentação, é gratuito e de código aberto
Como não há custo para se desenvolver em Java, pelo menos no início, há um incentivo aos novatos que não necessitam gastar com programas pagos, mas ao invés disso possuem escolhas de altíssima qualidade gratuitas e amplamente usadas.

## Desvantagens da Linguagem

Apesar disso, a linguagem também possui as seguintes desvantagens:
* Performance reduzida: por ser uma linguagem não projetada para gerar código nativo para cada arquitetura, os programas em Java costumam ter um desempenho menor que os escritos em linguagens como C++. Eles também costumam ocupar mais espaço em memória. Mas à medida que a linguagem vem sendo refinada, tal desvantagem vem diminuindo cada vez mais.
* Programas em Java geralmente demoram mais tempo para compilar.
* Programas que realizam cálculo com números em ponto flutuante tendem a possuir baixo desempenho.

## Onde Java está presente?

Java está presente em todos os lugares, desde telefones celulares até TVs e computadores. A linguagem Java é uma das mais difundidas e conta com inúmeros recursos pela Web. Ela pode ser usada para criar aplicativos desktop, como por exemplo o Azureus e o Eclipse, aplicações web como applets, que rodam no lado cliente ou páginas JSP, e outros termos relacionados à sua versão EE, no lado do servidor. Além disso há padrões de TV digital que disponibilizam algum suporte a Java. Inclusive até há robôs que suportam Java, sendo o que o destaque vai para o da missão Mars Rovers que percorreu o solo lunar. Sendo assim java está disponível para um amplo espectro de aplicações, cada qual com sua utilidade e características próprias.

## Por Onde Começar

Provavelmente você está ansioso para começar a aprender essa linguagem depois de tudo o que foi escrito até aqui, mas vamos com calma porque há ainda mais coisas a explicar e alguns conselhos a dar antes de realmente começarmos.
O primeiro é que a linguagem Java está disponível em várias versões, cada uma com seu propósito. Cada uma destas versões deve ser ressaltada uma vez que atuam em tecnologias diferentes e necessitam de diferentes pré-requisitos.
Java SE: É a tecnologia Java para desktops. É obrigatório o seu entendimento, ou pelo menos seus conceitos, pois serve de fundação para as outras versões. Atua em notebooks e PCs domésticos e está amplamente disponível, estando presente em quase 90% dos PCs do mundo.
Java ME: É a versão para dispositivos móveis, os quais geralmente têm menos memória sendo ela limitada bem como seu processamento também o sendo. Sendo assim nada mais é do que uma versão reduzida das APIs para desktop que incluem APIs específicas para construir aplicações que lidem com estas limitações.
JAVA EE: É na verdade um conjunto de especificações, as quais são implementadas em servidores de aplicação, tais como JBoss, Jetty, BEA Logic, etc. A base dela é o Java SE, porém o jeito de programar é diferente devido ao amplo conjunto de tecnologias e objetivos diferentes. Sendo assim o recomendado é aprender primeiro JavaSE, pois é a base para as outras edições. Para isso, como em qualquer linguagem, o ideal é primeiro treinar a lógica, pois o processo de desenvolvimento de programas requer o uso de lógica o tempo todo, e depois aprender Java em paralelo com o paradigma da orientação a objetos, o qual é o mais usado atualmente.
Para aprender Java, portanto, siga para os próximos passos para poder começar aprender os básicos dessa linguagem. Infelizmente não vamos poder ensinar a fundo a Orientação a objetos, já que este não é o foco principal do Wiki, e sim, ensinar Java.

# Características de linguagens orientadas a objetos

Antes de aprender Java, é preciso conhecer quais são as características da Programação Orientada a Objetos (POO) que ela possui. Este capítulo tem por intuito mostrar a filosofia da POO para programadores não habituados à ela.

## O que são Objetos

Em programação, objetos nada mais são do que um conjunto de dados sobre o qual estão definidas algumas operações. Se fôssemos criar um programa capaz de gerar na tela formas geométricas, por exemplo, poderíamos criar um objeto chamado "quadrado" que seria um conjunto de quatro números (que em POO são chamados de Atributos) que representam os seus vértices. O objeto "quadrado" poderia possuir as operações (que em POO são chamadas de Métodos) "MudaPosicao" que serviria para posicionar o quadrado em uma coordenada específica passada como argumento e MudaCor que trocaria a cor do quadrado desenhado na tela.
Os Atributos de um objeto são quaisquer variáveis que eles possuam que representam um número, caractere ou string. Se fôssemos programar um jogo, por exemplo, o personagem que o jogador controla poderia possuir atributos chamados Força, Resistência e Velocidade que seriam variáveis inteiras dentro do código. Ele também poderia possuir um atributo chamado Posição, que seria um vetor de inteiros que armazenariam a sua coordenada na tela.
Os Métodos de um objeto podem ser qualquer ação que o objeto pode executar. No jogo do exemplo acima, o personagem principal poderia possuir métodos chamados Pular, Atirar e Andar. Os Métodos nada mais são do que funções executadas sobre os Atributos de um Objeto.

## Classes

Classes nada mais são do que uma declaração de um objeto no começo do código. Nesta declaração, você especifica quais são os Atributos e Métodos(Comportamentos)de seu objeto. Por exemplo, uma vez que você crie uma classe chamada "quadrado", você pode passar a criar novos objetos pertencentes à esta classe, que poderiam ter diferentes valores para cada um de seus Atributos.
Classe é um conjunto de especificaçãos técnica de um objeto, Nesta declaração, pode-se especificar quais são os Atributos e Metodos(Comportamentos) da classe. Por exemplo, uma vez que seja criada uma classe chamada "quadrado", pode-se passar a criar novos objetos pertencentes à esta classe, que podem ter diferentes valores para cada um de seus Atributos.

## Herança

Herança é a capacidade que as classes tem de passar informações umas para as outras. Através da herança é possível criar fácil e rapidamente novos tipos de classes baseadas nas classes existentes. Por exemplo, assumindo que existe uma classe chamada "Veiculo", poderíamos gerar uma nova classe chamada "Carro", e outra classe chamada "Caminhao" que herdam (ou são filhas) de "Veiculo".
A classe "Veiculo" possui todos os Atributos que tem em comum entre um caminhão e um carro. Ambos possuem caracteristicas (Atributos) como, número de rodas, tipo de combustível, quantidade de portas, etc. Estes Atributos estão definidos na classe "Veiculo". Por sua vez, as classes "Carro" e "Caminhão", além de herdarem os atributos da classe "Veiculo", podem possuir seus próprios Atributos exclusivos. O mesmo ocorre com os Metodos.
Por exemplo, a classe "Caminhao", que poderia ter o Atributo numero de marchas reduzidas, que não faz sentido para um carro, apenas para um caminhão.
Para identificar se dois objetos tem uma relação de herança, deve-se analisar se o relacionamento é do tipo "é um tipo de". Por exemplo, Carro é um tipo de Veiculo, logo Carro herda de Veiculo; Cachorro é um tipo de Mamifero, e assim por diante.
Nota: em outras linguagens orientadas a objeto, como C++, existe herança múltipla, ou seja, uma classe pode herdar de mais de uma. Ex.: 'morcego é um tipo de mamífero' E 'morcego é um tipo de animal que voa'. Em java NÃO EXISTE herança múltipla! O que pode ser feito para simular isso é implementar uma Interface, mas isso será visto mais adiante.

## Sobrecarga de métodos

Algumas vezes uma mesma operação pode ser feita de diversas maneiras, utilizando informações diferentes. Isso pode ser feito utilizando a sobrecarga de métodos. Consiste em criar mais de um método com o mesmo nome, porém com parâmetros de entrada diferentes. Isso é muito usado quando uma função tem valores padrão. Cria-se um método que recebe 3 parâmetros de entrada, e outro que não recebe nenhum, este ultimo irá invocar o primeiro passando os 3 valores padrão.

## Sobreescrita de métodos

Quando a herança é usada, a classe 'filha' herda todos os métodos da classe 'pai', porém, as vezes isso pode trazer alguns problemas. Para dar mais flexibilidade, é possível sobreescrever um método, ou seja, criar uma nova implementação daquele método para a classe filha.

## Polimorfismo

Poli (muitas) morphos (formas) permite ao desenvolvedor utilizar uma mesma assinatura de método para desempenhar funções similares, de acordo com o contexto. Um exemplo de polimorfismo no exemplo utilizado na herança seria um método que retorna a autonomia do veículo. No carro, este método tem que verificar a potência do motor e o combustível usado (alcool ou gasolina) no caminhão, teria que verificar o peso da carga e a potência do motor.
A vantagem do polimorfismo está no fato que um trecho de código, muitas vezes não sabe se o objeto Veiculo é um caminhão ou um carro, bastando chamar o método que retorna a autonomia, se o objeto for um carro, a virtual machine invoca o método do carro, se o objeto for um caminhão, ela invoca o método do caminhão.

## Associação

Uma associação define uma relação entre duas classes que permite com que um objeto de uma classe utilize objetos de outra classe. Exemplo: Uma classe Motorista possui uma associação com a classe Volante, visto que objetos da classe Motorista vão utilizar objetos da classe Volante . Agregação e composição são dois casos específicos de associação.

## Agregação

A agregação é um relacionamento onde a classe A se relaciona com a classe B, de forma com que objetos da classe A utilizam objetos da classe B. No entanto, a existência dos objetos da classe B não depende da existência dos objetos da classe A. Exemplo: Um objeto da classe Estudante utiliza objetos da classe SalaDeAula, porém a existência dos objetos da classe Estudante não depende da existência dos objetos da classe SalaDeAula.

## Composição

A composição é um relacionamento onde a classe A se relaciona com a classe B, de forma com que objetos da classe A utilizam objetos da classe B, e a existência dos objetos da classe B dependem da existência dos objetos da classe A. Exemplo: Um objeto da classe SalaDeEstar dependem de objetos da classe Casa.

## Vantagens da Programação orientada à Objetos

* Modularidade: Uma vez que um objeto é criado, ele pode funcionar independente do resto do programa. Ele pode ser aproveitado em outros programas ou substituído por algum outro objeto.
* Encapsulamento: Uma vez que objetos são criados, você só precisa se concentrar em usá-los, sem se preocupar com os detalhes de sua implementação.

## Desvantagens da Programação Orientada à Objetos

* Alguns tipos de programas podem ficar mais difíceis de serem criados usando POO.
* Por ser uma filosofia de programação de mais alto nível, os programas tendem a ser mais lentos.

## Ver também

* Programação orientada a objetos - conceitos

# A história de Java
## A história de Java

Java começou na verdade como um projeto na Sun que objetivava o estudo e a análise de interações entre dispositivos eletrônicos e computadores, não exatamente para o desenvolvimento de uma linguagem para aplicativos embarcados. Nesse tempo a linguagem tinha o nome-código Green e foi idealizada por James Gosling. Contudo, a Sun perdeu a disputa para uma outra empresa e o projeto Green estava marcado para ser descontinuado.
Entretanto, eis que surge algo novo, sim, uma nova palavra chamada internet. Com o advento em 1993 do web browser Mosaic e das páginas estáticas HTML a vida das pessoas sofreria uma mudança profunda, bem como a do projeto Green. Com o objetivo de tirar proveito desse mercado o projeto Green sofre algumas mudanças e adaptações, se chamando Oak e em 1995 é lançado com o nome Java. Tal nome adveio do evento que os idealizadores da linguagem descobriram que já havia uma linguagem chamada Oak e então ao tomar seus cafés tiveram a idéia de a chamar de Java em virtude de este ser o nome do local daonde o café era comprado, a qual era é pequena ilha na Indonésia.
Assim em 1995 a Sun faz a divulgação da linguagem no evento SunWorld e a disponibiliza oficialmente em 1996, ano da primeira JavaOne. Java foi lançada então, sendo uma linguagem de propósito geral, porém, num primeiro momento conhecida por seus applets que adicionavam interatividade às páginas Web, característica ainda inexistente na época, quando a existência do Flash ainda nem era pensada. De lá para cá a linguagem sofreu muitas mudanças e evoluiu se adaptando com o tempo e atingindo a enorme popularidade que tem hoje.

# Pré-requisitos para acompanhar o livro

Este livro foi desenvolvido para quem já tem conhecimento prévio sobre lógica de programação e alguma noção sobre orientação à objetos. Se esta é a sua primeira experiência com programação, não é recomendado que continue neste livro! Antes estude os livros Introdução à programação e Programação Orientada a Objetos.
Os aplicativos necessários para a execução dos códigos apresentados neste livro são:
* Um editor de texto simples como o Notepad no Windows e o gedit no Ubuntu (e demais distribuições com o Gnome como ambiente gráfico) para edição do código-fonte. Esses editores já estão incluídos nos respectivos Sistemas Operacionais. Pode-se também utilizar editores com realce de sintaxe como o Sublime Text, Atom, Notepad++ (apenas para Windows), entre outros.
* JDK 8 para compilação e execução dos programas. Os passos para instalação serão abordados a seguir.
* Algum emulador de terminal, tal como Prompt de comando no Windows e gnome-terminal no Ubuntu, para executar os comandos de compilação e execução do JDK.
Não é indicado o uso de IDEs (acrônimo de Integrated Development Environment, em tradução livre Ambiente de Desenvolvimento Integrado) para estudo deste livro. Os IDEs, tais como Eclipse, NetBeans, IntelliJ, entre outras, oferecem diversas automatizações que aumentam a produtividade do desenvolvedor ao mesmo tempo que inibe a necessidade de se entender alguns dos conceitos apresentados aqui.

## Java Development Kit

Mais conhecido como JDK é, como a tradução sugere, um kit de ferramentas para desenvolvimento em Java. Nesse kit é encontrado o compilador javac, a máquina virtual JVM responsável por executar os bytecodes compilados, a ferramenta javadoc que converte os comentários apropriados em códigos-fonte em documentação HTML, entre outros.
A lista de todas as ferramentas disponíveis no JDK 8 é encontrada em aqui.

## Instalação do JDK no Windows

* Acesse a página do Java em Oracle e selecione entre Windows x86 e Windows x64 para versões de 32 bits ou 64 bits do Windows, respectivamente.
* Baixe e execute o instalador.
* Configure as variáveis de ambiente PATH e CLASSPATH:

### No Windows 9x

Adicione as seguintes linhas no final do arquivo AUTOEXEC.BAT:
Obs.: A localização da pasta dos arquivos Java ("C:\Program Files\Java\jdk1.6.0_01\bin;") deve ser mudada de acordo do lugar onde você instalou o JDK. Reinicie o computador.

### No Windows XP

Vá ao Painel de controle - Sistema. Abra a aba da janela "Avançado" e clique no botão "Variáveis do sistema". Edite a variável PATH adicionando o caminho C:\Program Files\Java\jdk1.6.0_01\bin (ou a pasta de instalação dos executáveis Java - caso já exista outros caminhos configurados, deve-se separar esta inclusão com ponto-e-vírgula ; ). Reinicie o computador.

## Instalação do JDK no em Distribuições baseadas no Ubuntu

Há 2 opções para instalação do JDK 8: OpenJDK (código aberto) e Oracle HotSpot (código proprietário).

### OpenJDK

* Acesse a Central de programas do Ubuntu e busque por jdk.
* Na barra inferior, clique em Mostrar itens técnicos.
* Selecione openjdk-8-jdk e instale-o.
OU
Entre no terminal e digite o comando abaixo.
Verifique se a instalação ocorreu com sucesso inserindo o seguinte comando.
A saída deverá ser a seguinte. Sendo que o último número poderá variar de acordo com o último update disponível no repositório oficial do Ubuntu.

### Oracle HotSpot

Entre no terminal e adicione o repositório do WebUpd8 e instale o HotSpot com o seguinte comando.
A verificação de sucesso da instalação se dá da mesma maneira que do OpenJDK.

### Mais informações

Para mais detalhes sobre como instalar o Java no Linux, veja o tutorial encontrado no livro Linux para iniciantes, capítulo Linux para iniciantes/Instalando programas/Java.

# Criando e executando o primeiro programa

Para criar o primeiro programa é necessário um editor de texto simples, para a digitação do código-fonte, e o JDK instalado. O procedimento para instalação do JDK é explicado no capítulo anterior.

## Etapas
### Etapa 1

No editor de texto digite o código exibido abaixo.
Salve o arquivo com o nome Teste.java.

### Etapa 2

Por meio do terminal entre no diretório onde está o arquivo Teste.java e digite:

### Etapa 3

E por fim, digite:
Será exibido:

## Explicações

Não se preocupe em decorar as informações desta seção pois elas serão revistas com maior profundidade nos capítulos correspondentes.

### Etapa 1

Na 1.ª etapa foi digitado o código-fonte em Java. Código-fonte, à grosso modo, é um conjunto de instruções legíveis por humanos, definidas em uma linguagem de programação, para determinar o que o programa deverá realizar.
A primeira linha do código-fonte utiliza a palavra-chave class para definir uma classe com o nome Teste. O modificador de acesso public, que precede class, não é obrigatório no código acima pois há apenas uma classe sendo definida.
Palavras-chave são palavras que servem como instruções para a linguagem de programação. Essas palavras não devem ser utilizadas para definir identificadores (nomes) de classes e métodos.
Classe é um recipiente de código. Seu corpo, também conhecido como bloco de instruções, é definido entre as chaves de abertura { e fechamento }. No código acima o corpo da classe Teste inicia na primeira linha e termina na última linha. Não definir uma classe com os delimitadores de bloco de instruções (colchetes) causa um erro de compilação.
Na segunda linha, temos o método public static void main(String args) dentro do corpo da classe Teste.
Método, conhecido em outras linguagens de programação como função, é subconjunto de instruções que pode ser reutilizado. Assim como as classes, métodos também tem um corpo. Não definir um método com os delimitadores de bloco de instruções (colchetes) causa um erro de compilação.
Os modificadores de acesso public e static e o tipo de retorno void do método main serão abordados no capítulo sobre métodos. Por ora, basta saber que eles são obrigatórios para a compilação do código-fonte. main é o nome do método e (String args) define sua lista de parâmetros.
O método main sempre será definido dessa forma para que haja a inicialização do programa. A esses códigos que sempre devem ser repetidos chamamos de código boilerplate.
Dentro do corpo do método main há a instrução System.out.println("Alô mundo!");. O método println é executado através da referência out localizada na classe System. O método em questão recebe como argumento a String "Alô mundo!".
String é uma sequência de caracteres delimitada com um par aspas duplas ".
Argumento é um valor enviado ao método. É possível alterar o argumento no método print para qualquer outra String.
O código dentro da classe está espaçado em 4 colunas e dentro do método main em 8. A esse espaçamento damos o nome de indentação. A indentação não é obrigatória para o funcionamento do programa, mas é uma boa prática, pois aprimora a legibilidade do código. As instruções inseridas dentro de um bloco de instruções são espaçadas em relação ao próprio bloco. No caso de haver um bloco dentro de um bloco então as instruções dentro do bloco mais interno serão espaçados em 2 níveis. Neste livro é utilizado espaçamento de 4 colunas para cada nível, porém pode-se utilizar qualquer quantidade. É comum que ao invés de espaçamento sejam utilizadas tabulações para definir a indentação.
O nome do arquivo deve ser o mesmo da classe acompanhado da extensão .java. Java é case-sensitive o que significa que diferencia letras maiúsculas de minúsculas. Logo, alterar a caixa de algum caracter de Teste.java resulta em erro.

## Referências

* ↑ Os modificadores de acesso de classe serão vistos no capítulo Declaração de Classes.
* ↑ Regras adicionais no capítulo Identificadores.
* ↑ Também pode ser utilizado String... args.Mais sobre varargs no capítulo Métodos.
* ↑ Também a construtores e anotações.
* ↑ Apenas no caso da classe ser precedida do modificador public. Mais informações no capítulo Declarações de Classes.

### Etapa 2

No terminal é utilizado o comando javac Teste.java para compilar as instruções do código-fonte Teste.java em instruções de bytecode do arquivo Teste.class.
javac é o compilador incluído no JDK. Com ele é possível compilar os códigos-fontes .java em arquivos bytecode de extensão .class. No exemplo, o javac após compilar Teste.java produziu o bytecode Teste.class.
bytecode é um arquivo que contém instruções interpretáveis pela JVM (máquina virtual Java). Um bytecode pode ser executado em qualquer Sistema Operacional que contenha uma JVM, o que significa que se um código-fonte é compilado pelo javac em um Windows, teoricamente esse bytecode resultante poderá ser executado pelo comando java em um Ubuntu.

### Etapa 3

O bytecode é executado pela JVM ao comando java Teste ser disparado.
O comando java inicia a JVM, que por sua vez irá carregar o bytecode apontado no comando, no caso Teste, irá procurar pelo método main, e caso encontrado, a JVM irá executá-lo.
Ao utilizar o comando java deve-se digitar o bytecode sem a extensão .class. Caso a extensão seja utilizada, o seguinte erro será reportado por java.

## Conveções utilizadas neste livro

* Os códigos-fonte e as saídas de texto (mensagens resultantes no terminal) serão dispostos em caixas cinzas como abaixo.
* As saídas de texto tanto podem conter resultados de métodos como print quando o programa é compilado e executado com sucesso (como ocorreu acima) quanto podem apresentar erros de compilação, rastreamento de pilha de exceções e erro na chamada de comandos da JDK tal como java.
Erro apontado na compilação.
Rastreamento de pilha de exceção (do original em inglês: exception stack trace).
Erro na sintaxe de comando.
* Exceto quando descrito o contrário, todos os códigos ao longo dos próximos capítulos foram escritos dentro do corpo do método main.
* Os números iniciando cada linha do código-fonte servem apenas para ser referenciados no texto, não devendo ser digitados.
* Os conceitos apresentados serão destacados em amarelo.
* Comentários contêm informações importantes sobre o código apresentado.
* No texto, referências às palavras-chaves serão apresentadas em caixas cinzas em linha como em class. Os identificadores (nomes) de métodos, classes e similares estarão em negrito como em "método main".

## Exercícios
# Como funciona o primeiro programa

A classe OlaMundo é criada(linha 1) com o método main(linha 2) que tem dois parâmetros, o Array String que terá os argumentos colocados no terminal e os args que terá o número de argumentos que foi passado.
A linha 3 pode ser explicada da seguinte forma, temos a classe System com a váriavel de instância out (que no caso é um objeto) referenciada e está variável de instância tem um método chamado println (Um método nada mais é do que uma função).

# Tipos de dados primários
## Tipos de dados primários

    Toda variável deve ter um tipo de dado, pois, o tipo determina que valores a variável poderá conter e que operações poderão ser realizadas com ela.
    Os tipos primários ou primitivos são os tipos de informações mais usuais e básicas. As variáveis deste tipo contêm valores simples, apropriados ao tipo da variável, e seus dados podem ser classificados basicamente em três categorias: lógicos, numéricos (inteiros e reais) e de caracteres.

### Tipos de dados lógicos
#### boolean

    É o tipo de dado que contém literal lógico. Serve para armazenar um único bit de informação. Este bit pode ser representado pelas palavras false (falso) ou true (verdadeiro). Representa estados binários, tais como: verdadeiro/falso, certo/errado, ligado/desligado, aberto/fechado, sim/não etc.
    Exemplos de declarações:
Observação: um erro muito comum para quem programa em C/C++ é fazer testes lógicos usando variáveis inteiras ou reais. Em Java, a instrução if só deve receber argumentos lógicos.

### Tipos de dados numéricos
#### Tipos de dados numéricos inteiros
##### byte

    É o tipo de dado capaz de armazenar 8 bits de informação, ou seja, um número inteiro entre -128 e 127. Sua utilização é recomendada em caso de economia de memória, já que alguns tipos de dados maiores possuem processamento mais rápido.
    Exemplos de declarações:

##### short

    É o tipo de dado que é capaz de armazenar números inteiros de 16 bits, ou seja, um número inteiro entre -32.768 e 32.767.
    Exemplos de declarações:

##### int

    É o tipo de dado capaz de armazenar 32 bits, ou seja, de representar um número inteiro qualquer entre -2.147.483.648 e 2.147.483.647. É o tipo mais indicado na maioria dos casos por possuir uma grande faixa de valores. Variáveis deste tipo também costumam ser manipuladas mais rapidamente já que correspondem à largura de dados (de palavra) mais usual na maioria dos processadores atuais.
    Exemplos de declarações:

##### long

    É o tipo de dado capaz de armazenar 64 bits de informação, ou seja, que pode representar um número inteiro qualquer entre -9.223.372.036.854.775.808L e 9.223.372.036.854.775.807L. Recomenda-se seu uso apenas quando for preciso assumir valores maiores ou menores do que aqueles possíveis de serem assumidos pelo int.
    Exemplos de declarações:

#### Tipos de dados numéricos reais
##### float

    É o tipo de dado capaz de armazenar números reais de precisão simples, ou seja, 32 bits de informação representando um número real.
    Exemplos de declarações:

##### double

    É o tipo de dado capaz de armazenar números reais de precisão dupla, ou seja, 64 bits de informação em forma de número real. É usado para representar valores nos quais é preciso uma precisão maior que a de float.
    Exemplos de declarações:

### Tipos de dados de caracteres
#### char

    É o tipo de dado capaz de armazenar 16 bits representando caracteres no formato UTF-16 (formato UTF composto de dois caracteres de 8 bits). Representado numericamente, o tipo char pode ter valores de 0 a 65535 (inclusive) - de '\u0000' a '\uffff'. Nas versões mais recentes da linguagem Java, propõe-se substituir o tipo char pelo tipo byte.
    Exemplos de declarações:

# Literais
## Literais

    Literais são as representações de dados dentro do código fonte. Na linguagem Java, literais representam os dados dos tipos primitivos, dos tipos String e dos tipos nulo, por exemplo.
    Assim, podemos subdividir os literais em:
   * Literais Booleanos ou Lógicos: correspondem ao valores true (verdadeiro) e false (falso).
   * Literais inteiros: representam os números inteiros e podem ser de base octal, decimal, ou hexadecimal. Assim:
   ** Literais Inteiros Decimais: são números em base decimal que representam um valor inteiro. Eles podem ser tanto byte, como short, int ou long. Para escrever um literal inteiro na base decimal, basta digitar o seu valor com um desses dígitos: 0 1 2 3 4 5 6 7 8 9.
   ** Literais Inteiros Octais: são números em base octal que representam um valor inteiro. Para representar este tipo de literal, basta escrever os seus dígitos colocando 0 (dígito zero) antes. Os dígitos para este tipo são: 0 1 2 3 4 5 6 7.
   ** Literais Inteiros Hexadecimais: são números em base hexadecimal que representam um valor inteiro. Para representar este tipo de literal basta escrever os seus dígitos normalmente precedidos pelos caracteres 0x (zero xis) ou 0X. Os dígitos permitidos são: 0 1 2 3 4 5 6 7 8 9 A a B b C c D d E e F f.
   * Literais Fracionários (de Ponto Flutuante): correspondem aos números racionais (fracionários). Para representá-los, basta escrever um número inteiro seguido por um ponto e por sua parte decimal - o ponto faz o lugar da vírgula. Outra opção seria escrever o número em notação científica, escrevendo primeiro o valor da mantissa, seguido do caractere "e" e do valor do expoente (de base 10).
   * Literais Caracteres: correspondem a um caractere. Para representá-los, basta escrever o caractere cercado por apóstrofos. Também podem armazenar caracteres de controle de formatação (quebra de linha, etc.) e também caracteres no formato unicode.
   * Literais de cadeias de caracteres - Strings: correspondem às cadeias de caracteres. Para representá-los, escreva o(s) caracter(es) cercado(s) por aspas.
   * Literal nulo: representa a ausência de tipo e de dado (valor). Para representar utiliza-se a palavra null.
    Os literais atribuem valores às variáveis ou partes do código. Ou seja, eles são usados para fazer com que variáveis passem a ter um valor ou se executem cálculos. Exemplos:
Nos exemplos acima, pudemos ver exemplos da atribuição de valores iniciais às diversas variáveis no momento da declaração assim como, a partir da declaração de pesoTotal (sem valor inicial), do cálculo de pesoTotal igual a x vezes o peso dividido por 4. A variável ligado recebe o valor "verdadeiro", velocidade recebe o número 128, x recebe 12 em octal que é o mesmo que 10 em decimal, peso recebe 12A em hexadecimal que é o mesmo que 298 em decimal, preco recebe 1,24 e letra recebe f. Já a variável texto recebe Isto é um exemplo de cadeia de caracteres.

### Regras para representar literais fracionários (de ponto flutuante)
#### Regras básicas

   * Os literais do tipo float são representados colocando-se a letra F ou f após o número. Por exemplo:
       Observação: é importante a utilização do F (ou f) após o número para representar o tipo float já que sua omissão implicará que o literal passe a ser automaticamente interpretado como sendo do tipo double. Por exemplo:
   * Os literais do tipo double são representados colocando-se a letra D ou d após o número.
   * A separação entre a parte inteira e fracionário do número é feita através do ponto - ao invés da vírgula. Por exemplo:
   * Caso a parte inteira seja 0 ("zero"), ela poderá ser omitida desde que se coloque o ponto (representando a vírgula) e a parte fracionária. Por exemplo:

#### Outras variações de representação

    Os literais fracionários também podem ser representados com o uso de uma exponenciação em base 10, ou seja, através do número seguido da letra e ou E seguido do expoente de base 10 a ser multiplicado e do f ou F. Exemplo:
       1e3f representa o número $1\times 10^{3}$, ou seja, 1000
       -1e3F representa o número $-1\times 10^{3}$, ou seja, -1000
       1e-2F representa o número $1\times 10^{-2}$, ou seja, 0,01
       -1e-3F representa o número ${-1}\times 10^{-3}$, ou seja, -0,001
    Exista também a representação de literais fracionários em hexadecimal.
    a fazer

### Representação de caracteres de controle de texto

    Caracteres de controle de texto podem ser representados da seguinte forma:
| Código | Código | Significado |
| Escape | Unicode | Significado |
| \b | \u0008 | caractere de retrocesso (backspace - BS) |
| \t | \u0009 | tabulação horizontal tab (horizontal tab - HT) |
| \n | \u000a | quebra de linha (linefeed - LF) |
| \f | \u000c | quebra de página (form feed - FF) |
| \r | \u000d | retorno de carro (carriage return - CR) |
| \" | \u0022 | aspas (double quote - " ) |
| \' | \u0027 | apóstrofo (single quote - ' ) |
| \\ | \u005c | barra invertida (backslash - \ ) |

### Representação de caracteres no formato Unicode-16

    Unicode é padrão que define um conjunto de caracteres universais. O padrão Unicode-16 define caracteres com o uso de 2 bytes (16 bits). Na linguagem Java, define-se esses caracteres com \u seguido de 4 dígitos hexadecimais (dígitos 0 1 2 3 4 5 6 7 8 9 A a B b C c D d E e F f). Assim, a representação poderá variar de \u0000 até \uFFFF. Exemplos:
| Caractere Unicode-16 | Caractere gerado |
| \u7Fff | 翿 |
| \u7Ffc | 翼 |
| \u0062 | b |
| \u0078 | x |
    Exemplo de declaração de uma variável do tipo char usando o literal Unicode-16:

# Variáveis

    Variáveis são nomes atribuídos à endereços na memória de um computador onde se guardam dados. A declaração de uma variável consiste em dar um nome para a posição de memória a ser usada e especificar qual tipo de dado a guardar na memória.
    Para declarar uma variável, utiliza-se a seguinte sintaxe:
    Observação: o modificador é opcional no caso da variável ser a completar
    Por exemplo:
    Pode-se declarar mais de uma variável do mesmo tipo separando-as por vírgulas, como na seguinte sintaxe:
    Por exemplo:
    Iniciar uma variável é atribuir um valor, um dado, à variàvel. As variáveis também podem ser declaradas e iniciadas ao mesmo tempo. Por exemplo:

# Modificadores

* Java/Modificadores

# Identificadores

* Java/Identificadores

# Identificadores

    Identificador é o nome que utilizamos para representar as variáveis, classes, objetos, etc. Por exemplo, na Matemática utilizamos um nome para as incógnitas (x, y, z, etc.) que é o identificador daquela incógnita.
    Utilizamos, em Java, as seguintes regras para criação do identificador:
   * não pode ser uma palavra-reservada (palavra-chave);
   * não pode ser true nem false - literais que representam os tipos lógicos (booleanos);
   * não pode ser null - literal que representa o tipo nulo;
   * não pode conter espaços em brancos ou outros caracteres de formatação;
   * deve ser a combinação de uma ou mais letras e dígitos UNICODE-16. Por exemplo, no alfabeto latino, teríamos:
   ** letras de A a Z (de \u0041 a \u005a);
   ** letras de a a z (de \u0061 a \u007a);
   ** sublinha _ (\u005f);
   ** cifrão $ (\u0024);
   ** dígitos de 0 a 9 (de \u0030 a \u0039).
       Observação 01: caracteres compostos (acentuados) não são interpretados igualmente aos não compostos (não acentuados). Por exemplo, História e Historia não são o mesmo identificador.
       Observação 02: letras maiúsculas e minúsculas diferenciam os identificadores, ou seja, a é um identificador diferente de A, História é diferente de história, etc.

### Alguns exemplos de identificadores

       X
       abóbora
       άγγελος
       carro1
       carro_1

## Palavras-chave

    Em programação, palavras-chave, ou palavras reservadas, são as palavras que não podem ser usadas como identificadores, ou seja, não podem ser usadas como nome de variáveis, nome de classes, etc. Estas palavras são assim definidas ou porque já têm uso na sintaxe da linguagem ou porque serão usadas em alguns momento, seja para manter compatibilidade com versões anteriores ou mesmo com outras linguagens. No caso do Java temos as seguintes palavras-chave:
| abstract | continue | for | new | switch |
| assert(3) | default | goto(1) | package | synchronized |
| boolean | do | if | private | this |
| break | double | implements | protected | throw |
| byte | else | import | public | throws |
| case | enum(4) | instanceof | return | transient |
| catch | extends | int | short | try |
| char | final | interface | static | void |
| class | finally | long | strictfp(2) | volatile |
| const(1) | float | native | super | while |
| null |

# Conversão de tipos
## De String para tipo básico

Implícitas
    Entre inteiros: tipos menores para tipos maiores;
Explícitas
    Type Casting
Entre inteiros: tipos maiores para tipos menores;
Cuidado para que o valor que está sendo atribuído não extrapole o tamanho máximo possível do tipo que está recebendo.

# Constantes

    As constantes em Java são declaradas através do modificador final. Um modificador de acesso também pode ser adicionado opcionalmente com o fim de determinar o escopo da constante. A sintaxe para declaração de uma constante é a seguinte:
    Onde:
   * modificador = modificador de acesso (opcional);
   * tipo = tipo de dado primário;
   * identificador = nome (identificador) da constante;
   * literal = literal que atribui informação à constante.
    Exemplo:
    O exemplo acima cria uma constante pública (pelo modificador de acesso public) com o tipo de dado inteiro int com o valor 10.

# Blocos e comentários de programação
## Blocos de programação

    Blocos de programação são aglomerados de instruções e declarações que têm escopo conjunto. Ou seja, as variáveis definidas como locais dentro de um bloco somente serão presentes dentro deste bloco assim como as instruções ali presentes. Os blocos de programação são delimitados por chaves e podem ser aninhados - colocados um dentro dos outros. Por exemplo:
    Outro exemplo:

## Comentários

    Comentários, como o próprio nome instiga, são notas que podem ser incluídas no código fonte para descrever o que se quiser. Assim, não modificam o programa executado e servem somente para ajudar o programador a melhor organizar os seus códigos. Os comentários em Java seguem a mesma sintaxe da linguagem C++.
    Comentários de uma ou mais linhas podem ser iniciados por /* e terminados por */ . Por exemplo:
    Comentários que terminam no final da linha são indicados com // . Pode ser usados desde o ínicio da linha ou colocados depois do código funcional, desde que não haja um caractere de quebra de linha no comentário. Por exemplo:

### Comentários para facilitar a documentação automática

    Pode-se utilizar comentários de várias linhas em que a primeira linha se inicia com /** e a última termina com */. Ou seja, na seguinte sintaxe:
    Observação: a documentação é gerada através do aplicativo javadoc.

# Operadores
## Operadores

Operadores são símbolos que representam atribuições, cálculos e ordem dos dados. As operações seguem uma ordem de prioridades, ou seja, alguns cálculos (ou outros) são processados antes de outros. Por exemplo, na Álgebra podemos mostrar a seguinte ordem:
| Ordem | Operadores | Operação |
| 1 | / * | Divisão e multiplicação |
| 2 | + - | Soma e subtração |
Assim, as operações de divisão e multiplicação, por serem de ordem 1, serão executadas antes das operações de soma e subtração (ordem 2). Também, as operações de divisão e multiplicação são de mesma ordem (1) e não importa, entre si, a ordem da operação (2 dividido por 4 vezes 9 é igual a 2 vezes 9 dividido por 4).

### Tipo

Os operadores são divididos em 3 tipos em relação à quantidade de operandos no qual operam: unário, binário e ternário.

### Precedência

Precedência indica a ordem na qual um operador opera em relação à avaliação de uma expressão.
A tabela seguinte elenca os operadores por precedência, do maior para o menor.
| Tipo de Operador | Lista de Operadores |
| Sufixais | expr++ expr-- |
| Prefixais | ++expr --expr +expr -expr ~ ! |
| Multiplicativos | * / % |
| Aditivos | + - |
| Shift Binário | << >> >>> |
| Comparativos | < > <= >= instanceof |
| igualdade | == != |
| Bit-aBit E | & |
| Bit-aBit XOU OR | ^ |
| Bit-aBit OU OR | | |
| Lógico E | && |
| Lógico OU | || |
| Ternário | ? : |
| Atribuição | = += -= *= /= %= &= ^= |= <<= >>= >>>= |

#### Precedência 13: operadores sufixais

São operadores unários posicionados após o identificador da variável para incrementar ++ ou decrementar -- uma variável de tipo numérico em 1. Não podem ser utilizados em variáveis do tipo string, boolean ou de referência. Também não podem ser utilizados em valores de expressão e em literais. Diferente dos operadores de pré incremento/decremento, esses operadores sufixais retornam o valor original da variável para a expressão e depois realizam a operação sobre a variável.

#### Precedência 12: operadores prefixais

São operadores unários que alteram o valor de uma variável e seus sinais são posicionados antes do identificador da variável. Como exemplo, pode-se citar o Incremento ++, Decremento --, Sinal Positivo +, Sinal Negativo -, Inversão e Incremento ~ e Negação !. O incremento e decremento, já vimos o que faz. Eles estão sendo citados aqui novamente porque seus sinais podem vir antes de variáveis também e numa operação complexa (com outros operadores binários) alteram a precedência da operação. O Sinal Positivo + retorna a variável que vem depois dele com o mesmo sinal, o Sinal Negativo - inverte o sinal de variáveis transformando números positivos em negativo e vice-versa. Ele não pode ser usado em variáveis dos tipos boolean e char. O Incremento e Inversão ~ aumenta o número em uma unidade e inverte o seu sinal. Só pode ser usado em inteiros. Já a operação de negação ! transforma "verdadeiro" em "falso" e vice-versa, só podendo ser usado em variáveis do tipo boolean. Também só funcionam em variáveis, não em literais. Exemplos de uso:
Observação: uma diferença importante entre os operadores '++' e '--' prefixais e sufixais é o tempo de avaliação da expressão comparado com a alteração da variável. A saber:
Neste exemplo, temos que, ao final x vale 7 (duas vezes incrementado), y vale 5 (o valor inicial de x) e z vale 7 (o valor final de x). Deve-se evitar usar mais de um operador prefixal e sufixal na mesma linha, porque isto torna o código incompreensível, por exemplo: x = (y++ + ++z - --x) + ++y.

#### Precedência 11: operadores multiplicativos

São operadores que realizam uma operação igual ou semelhante à multiplicação. Exemplos de operações do tipo são a Multiplicação (*), a Divisão (/) e o Resto (%). O primeiro pode realizar a multiplicação entre dois valores que não sejam do tipo boolean e nem do tipo char. O segundo pode dividir o primeiro número pelo segundo. Também não pode ser usado em valores booleans ou char. O terceiro retorna o resto da divisão do primeiro pelo segundo. Exemplos de uso:

#### Precedência 10: operadores aditivos

São operadores que realizam alguma operação igual ou equivalente à adição. Assim como os Operadores Multiplicativos, os Aditivos podem ser usados tanto em variáveis como em literais (quando fazem a concatenação de strings). Mas também não podem ser usados em variáveis char e boolean. Eles também não alteram as variáveis passadas para eles. No lugar disso, eles retornam um número que deve ser direcionado par uma variável por meio da operação de atribuição (veja abaixo). Exemplos de uso:

#### Precedência 9: operadores de shift

São operadores que deslocam os bits de um número de modo a alternar o seu valor. Exemplos de operadores deste tipo são o Shift para a Direita (>>), o Shift para a Direita Sem-Sinal(>>>) e o Shift para a Esquerda (<<). O primeiro valor a ser recebido pelo operador é o número sobre o qual será realizado um Shift e o segundo número é a quantidade de posições de bits a serem deslocados. Exemplos de uso:

#### Precedência 8: operadores comparativos

São operadores que comparam dois números e retornam em seguido o valor booleano "verdadeiro" ou "falso". Como exemplo, pode-se citar o Menor que(<), Maior que (>), Menor ou Igual que(<=), Maior ou Igual que (>=) e Exemplo de (instanceof). O significado dos quatro primeiros operadores é evidente. Já a operação Exemplo de, retorna "verdadeiro" se o primeiro operando for um Objeto pertencente à classe passada como segundo operando e "falso" caso contrário. Exemplos de uso:

#### Precedência 7: operadores de igualdade

São semelhantes aos Operadores Comparativos. Eles também recebem números como operandos e retornam um valor boolean. A diferença é que estes operadores apenas verificam se as variáveis são iguais ou não. Como exemplos de operadores assim, pode-se citar o Igual a (==) e Diferente de (!=). Estes operadores podem ser usados em qualquer tipo de variável, desde que elas sejam do mesmo tipo. Exemplos de uso:
Ao utilizar operadores de igualdade com objetos, a comparação é feita entre suas referências. Dessa forma, dois objetos cognitivamente iguais, podem ser avaliados como diferentes. Exemplo:

#### Precedência 6, 5 e 4: operadores Bit-a-Bit

Os Operadores Bit-a-Bit são todos aqueles que realizam suas operações sobre os bits de um número, e não sobre o seu valor. Existem ao todo três destes operadores e cada um deles tem um valor de precedência diferente. O que tem precedência mais alta é o AND bit-a-bit (&). Ele analisa dois bits e retorna 1 se ambos forem iguais à 1 e 0 caso contrário. Depois vem o OR exclusivo bit-a-bit (^) que retorna 1 se os bits forem diferentes e 0 caso contrário. Por último, vem o operador OR inclusivo (|), que retorna 0 caso ambos os bits valerem 0 e retorna 1 caso contrário. Estes operadores podem ser usados em qualquer tipo de dados, desde que possuam o mesmo tamanho em bits. Exemplos de uso:

#### Precedência 3 e 2: operadores AND e OR

Os operadores AND e OR só podem ser usados em variáveis e literais do tipo boolean. O operador AND (&&) retorna "verdadeiro" quando seus dois operandos também valem "verdadeiro" e retorna "falso" caso contrário. O operador OR (||) retorna "falso" quando seus dois operandos são falsos e retorna "verdadeiro" caso contrário. Exemplos de uso:

#### Precedência 1: operadores ternários

O operador ternário ? : recebe ao todo três operandos. O primeiro operando deve possuir necessariamente um valor do tipo boolean. Os outros dois operandos podem ser de qualquer tipo. Caso o valor do primeiro operando seja "verdadeiro", o operador retorna um valor igual ao do segundo operando. Caso o seu valor seja "falso", ele retorna um valor idêntico ao terceiro operando. Exemplos de uso:

#### Precedência 0: atribuições

Os operadores de atribuição são os mais numerosos e os que tem uma prioridade menor de serem interpretados. Um exemplo deste operador (=)foi bastante usado neste capítulo. Ele armazena o valor que aparecer à direita na variável presente à esquerda. Caso deseje-se que a variável da esquerda receba o valor dela mesma após passar por alguma operação com um segundo valor, basta colocar o símbolo da operação antes do sinal "=" e colocar o segundo valor à direita. Exemplos de uso:
Quando em uma mesma linha forem encontrados vários operadores diferentes, serão executados primeiro aqueles que tiverem maior precedência. Se existirem operadores com o mesmo valor de precedência, será realizado primeiro aquele cujo símbolo aparecer primeiro. É possível alterar a ordem natural com que são feitas as operações através do uso de parênteses. As operações entre parênteses sempre são realizadas antes.

## Separadores

    Os separadores são sinais que separam, ou sejam, indicam/modificam a ordem das operações (ou atribuições, ou interpretações etc.) que podem ou não ser diferentes da comum. Em Álgebra, temos alguns separadores como os seguintes:
       Ordem Separadores Descrição 1,Vírgula 2( )Parênteses 3[ ]Colchetes 4{ }Chaves

### Separadores em Java

       Ordem Separadores Descrição 1 ;Ponto-e-vírgula 1.Ponto 1,Vírgula 1( )Parênteses 2[ ]Colchetes 2{ }Chaves

#### Ponto-e-vírgula, ponto e vírgula

    O ponto-e-vírgula serve para separar sentenças ou instruções. A quebra de linha não separa instruções. Por exemplo:
    É o mesmo que:
    E
    É o mesmo que:
    O ponto serve para separar a parte inteira da fracionária em um número, tal como na notação inglesa. Ou seja, enquanto escrevemos 2,5 para representar dois e meio, em Java escrevemos:
    A vírgula serve para separar itens, elementos, membros, como o que ocorre na atribuição de valores aos vetores, por exemplo:

#### Parênteses, colchetes e chaves

    Na maioria das linguagens de programação de computadores, os separadores colchetes e chaves são utilizados para outros propósitos diferentes dos em Álgebra. Para uso semelhante, em programação se utiliza o aninhamento (inclusão dentro de outros) de parênteses. Por exemplo:
    Em Álgebra:
       {13x(4+12)/[12+(13+76/2)x(1+2)]+5}
    Equivale a, em Java:
       (13*(4+12)/(12+(13+76/2)*(1+2))+5)
    Em Java, as chaves são utilizadas para separar blocos de programação e os colchetes são utilizados para indicar/separar os índices de vetores (e, também, na declaração dos mesmos vetores).

#### Outros separadores/delimitadores

    Através de uma visão mais ampla, podemos encontrar muitos outros símbolos que podem atuar como separadores em Java.
    Quando atuam em dupla, podem ser chamados de delimitadores, tais como:
   * aspas " " - são usadas para delimitar uma cadeia de caracteres;
   * apóstrofos ' ' - são usados para delimitar um literal do tipo caracter (char).
    Alguns outros tipos de separadores:
   * e ou E - usados na notação científica de números fracionários;

# Exercícios básicos

class Olamundo // declara a classe Olamundo que corresponde ao nome do programa {

# Comandos de seleção

Como pode-se notar, o conhecimento adquirido até aqui não permite a criação de programas interativos. Eles sempre executam da mesma forma, independente do que o usuário faz ou dos valores que são recebidos. Mas agora iremos aprender a usar alguns comandos que permitem que dependendo das circunstâncias, os programas executem instruções diferentes.

## A instrução if

A instrução de seleção única if, também conhecida por if-then, possibilita a execução condicional de um bloco de instruções.
Depois da palavra-chave if é necessária uma expressão booleana entre parênteses. Caso a expressão booleana resulte no valor true em tempo de execução então o bloco seguinte será executado, caso resulte em false aquele será ignorado. O bloco de instruções pode conter 0 ou mais instruções. As chaves que delimitam o bloco são opcionais caso se tenha apenas uma instrução a ser executada.

## A instrução if...else

Também conhecida como instrução if-then-else, a instrução de seleção dupla if...else tem função complementar à de if: executa instruções no caso da expressão booleana de if resultar em false.
A palavra chave else deve estar logo após da(s) instrução(ões) de if. Após a palavra chave else deve ser colocado o bloco de instruções a serem executadas no caso da expressão booleana de if resultar em false. Assim como if, as chaves delimitadoras de bloco são opcionais caso haja apenas uma instrução a executar.

## Instruções if...else aninhadas

As instruções if ou if...else podem ser aninhadas dentro de outras instruções if ou if...else para casos em que antes de determinadas instruções serem executadas sejam necessárias combinações de resultados de expressões booleanas.
As instruções if e if...else aninhadas não apresentam nenhum comportamento diferente do esperado caso não estivessem aninhadas. Estão sendo abordadas apenas com o intuito de exemplificar a possibilidade de aumento das ramificações de decisões.
É possível verificar no exemplo acima que a primeira instrução if mesmo contendo mais de uma linha de instruções consegue identificar que o if...else forma uma única ramificação e assim executar a expressão booleana normalmente. Isso se deve ao fato que toda else está vinculada a uma if. Já na else com o escopo mais externo, verifica-se chaves delimitadoras de bloco. Essas chaves são necessárias por conta de uma segunda instrução, nomeadamente System.out.println, que é executada independentemente do resultado da expressão booleana da if...else.
No exemplo acima há um recurso estilístico para indentar o código com a finalidade de aprimorar a legibilidade. As palavras chave if foram anexadas às palavras chave else já que as else têm somente uma instrução cada e por isso não necessitam de chaves para delimitar bloco de instruções. O código abaixo tem exatamente a mesma funcionalidade apesar das quebras de linha.

## A instrução switch

A instrução switch por vezes chamada de switch...case possibilita a execução condicional de instruções de acordo com a correspondência entre a expressão avaliada e a constante em case.
Dentro do parâmetro da switch pode ser utilizada expressão que resulte em: byte, short, char, int, String e enum. As chaves que delimitam o bloco são necessárias ainda que só haja uma ramificação do fluxo do código. A palavra chave case indica as ramificações de código. Deve ser seguida de uma expressão constante que corresponda ao tipo da expressão inserida no parâmetro da switch, e essa expressão constante, por sua vez, deve ser seguida de : que é o carácter que delimita o início do bloco de instruções relativo à case. Após : podem ser inseridas 0 ou mais instruções, incluindo a palavra chave break que será abordada mais adiante. Ao iniciar outra instrução case ou inserir a chave de fechamento do bloco de switch o bloco anterior é encerrado.
Em tempo de execução, a variável dia será comparada com as expressões constantes, definidas em tempo de compilação, de cada case. O case contendo o valor 5 tem valor igual ao da variável dia, então desse ponto em diante todas as instruções serão executadas até que chegue o término do bloco de switch.

### A instrução break

Caso seja necessário que apenas sejam executadas instruções vinculadas a determinadas case então deve-se utilizar a instrução break. Após a instrução break o fluxo do programa sai do bloco de switch.
Com a instrução break inserida no bloco da case com valor sexta, o código será executado da case com valor 5 até essa break referida.

### A instrução default

A instrução default pode ser utilizada para o caso da expressão no parâmetro de switch não corresponder a nenhum dos valores das instruções case. default pode aparecer em qualquer ordem e segue o mesmo funcionamento que case no que tange a bloco de instruções e uso de break.

## Exercícios

Dado o código acima, responda:
1. O que será impresso na tela? A afirmação está correta? :
* Será exibido a é menor que 2. porém a informação está incorreta. A instrução else está vinculada a if imediatamente anterior, e no parâmetro dessa if a expressão booleana resultará false. Logo, a informação correta seria a é maior ou igual a 4..
2. Como corrigir o código? :
* int a = 5;
* if (a > 2) {
* if (a < 4)
* System.out.println("a é igual a 3.");
* } else
* System.out.println("a é menor ou igual a 2.");
Dado o código acima, responda:
3. Remova o código desnecessário, defina blocos de instruções para todas as instruções if...else e indente. :
* A última expressão booleana (b < c) não é necessária pois caso um número b não seja maior ou igual a um número c, obviamente ele será menor.
* double b = 10.5;
* double c = 2.0;
* if (b == c) {
* System.out.println("b é igual a c");
* } else {
* if (b > c) {
* System.out.println("b é maior que c");
* } else {
* System.out.println("b é menor que c");

# Comandos de iteração

Neste capítulo veremos como fazer para que o seu programa execute uma sequência de instruções um determinado número de vezes ou até que determinada condição seja satisfeita.

## O comando for

O comando for deve ser usado sempre que se deseja que um código seja executado um determinado número de vezes. A sintaxe do comando for é:
Quando o comando "for" é executado, a primeira coisa a ser feita é a inicialização prevista. Em seguida, verifica-se se CONDIÇÃO é "falso". Em caso afirmativo, o loop não será executado. Caso contrário, todos os comandos existentes no bloco abaixo do comando são executados e a operação prevista em EXPRESSÃO é executada. Mais uma vez, a CONDIÇÃO é analisada. Caso ela seja falsa, o loop é interrompido. Caso contrário, ela continua. Exemplos de uso:

## O comando while e do-while

O comando while deve ser usado sempre que não sabemos quantas vezes um loop será executado. A sintaxe do comando é:
Quando o comando "while" é executado, verifica-se o valor retornado por CONDIÇÃO. Se for "verdadeiro", a sequência de comandos presente no bloco logo abaixo do comando é executada. Ao fim, o valor de CONDIÇÃO é verificado novamente. O loop só para quando o valor retornado por CONDIÇÃO for "falso".
Além do comando "while", também pode ser usado o comando "do-while" que segue a seguinte sintaxe:
Ele funciona exatamente igual ao comando "while". A diferença é que a CONDIÇÃO só é analisada depois que os comandos são executados. Isso significa que o comando "do-while" sempre executa o conjunto de comandos ao menos uma vez. Mesmo que a condição seja inicialmente falsa. Exemplos de uso:
Exemplo 1:
Exemplo 2:

## Comandos de controle de fluxo

Existem alguns comandos que foram feitos para facilitar o uso de loops em programas. Eles permitem que você controle melhor o fluxo de execução de um programa. São eles:

### O comando break

O comando break é um comando bastante importante no desenvolvimento da maior parte dos programas de computador, ele é usado para sair imediatamente de um laço (loop, em inglês), independente do valor de CONDIÇÃO. Ele pode ser executado dentro de um while, for, do ... while ou switch (estes comandos serão discutidos mais adiante neste livro), fazendo um saída imediata dessa instrução. Passando para o execução do próximo comando.
A sintaxe do comando é bastante simples:
Exemplos de uso: No exemplo abaixo temos um código escrito em Java, onde em um loop for é interrompido quando a variável inteira contador se torna igual a 5.

### O comando continue

O comando continue serve para encerrar a execução de comandos e verificar o valor de CONDIÇÃO. Caso o valor seja "verdadeiro", a iteração continua. Caso contrário, ela se encerra. Exemplos de uso:
Neste capítulo veremos como fazer para que o seu programa execute uma sequência de instruções um determinado número de vezes ou até que determinada condição seja satisfeita.

## O comando for

O comando for deve ser usado sempre que se deseja que um código seja executado um determinado número de vezes. A sintaxe do comando for é:
Quando o comando "for" é executado, a primeira coisa a ser feita é a inicialização prevista. Em seguida, verifica-se se CONDIÇÃO é "falso". Em caso afirmativo, o loop não será executado. Caso contrário, todos os comandos existentes no bloco abaixo do comando são executados e a operação prevista em EXPRESSÃO é executada. Mais uma vez, a CONDIÇÃO é analisada. Caso ela seja falsa, o loop é interrompido. Caso contrário, ela continua. Exemplos de uso:

## O comando while e do-while

O comando while deve ser usado sempre que não sabemos quantas vezes um loop será executado. A sintaxe do comando é:
Quando o comando "while" é executado, verifica-se o valor retornado por CONDIÇÃO. Se for "verdadeiro", a sequência de comandos presente no bloco logo abaixo do comando é executada. Ao fim, o valor de CONDIÇÃO é verificado novamente. O loop só para quando o valor retornado por CONDIÇÃO for "falso".
Além do comando "while", também pode ser usado o comando "do-while" que segue a seguinte sintaxe:
Ele funciona exatamente igual ao comando "while". A diferença é que a CONDIÇÃO só é analisada depois que os comandos são executados. Isso significa que o comando "do-while" sempre executa o conjunto de comandos ao menos uma vez. Mesmo que a condição seja inicialmente falsa. Exemplos de uso:
Exemplo 1:
Exemplo 2:

## Comandos de controle de fluxo

Existem alguns comandos que foram feitos para facilitar o uso de loops em programas. Eles permitem que você controle melhor o fluxo de execução de um programa. São eles:

### O comando break

O comando break é um comando bastante importante no desenvolvimento da maior parte dos programas de computador, ele é usado para sair imediatamente de um laço (loop, em inglês), independente do valor de CONDIÇÃO. Ele pode ser executado dentro de um while, for, do ... while ou switch (estes comandos serão discutidos mais adiante neste livro), fazendo um saída imediata dessa instrução. Passando para o execução do próximo comando.
A sintaxe do comando é bastante simples:
Exemplos de uso: No exemplo abaixo temos um código escrito em Java, onde em um loop for é interrompido quando a variável inteira contador se torna igual a 5.

### O comando continue

O comando continue serve para encerrar a execução de comandos e verificar o valor de CONDIÇÃO. Caso o valor seja "verdadeiro", a iteração continua. Caso contrário, ela se encerra. Exemplos de uso:

# for
## Exemplo de comando de repetição usando o FOR

A sintaxe deste comando é a seguinte:
Veja um exemplo:
O Resultado obtido será:

## ForEach

ForEach funciona com Array ou toda class que implementa a interface Iterable:

### Exemplo de ForEach:
# Vetores
## Definição de vetor

    Um vetor é uma estrutura de dados formada por um conjunto de dados ou outros elementos de um mesmo tipo ou uma mesma estrutura. O vetor pode ter uma dimensão ou mais. Também chamado de matriz quando de duas dimensões, funciona de modo análogo às matrizes matemáticas. O acesso aos dados é feito através de "coordenadas" (índices).
    A programação faz um grande uso de vetores. Cada item de um vetor é chamado de elemento. Cada um dos elementos possui uma posição dentro do vetor, à qual referenciamos através do índice do elemento. Cada um dos "domínios" (conjunto de posições, endereços de armazenamentos) do vetor, nos chamamos de dimensão. Já o tipo de dado (ou de elemento) corresponde ao "contradomínio" do vetor, ou seja, o conjunto de literais ou de outro tipo de elemento que o vetor pode armazenar.
    Veja um vetor de uma dimensão e dez elementos:
    Ele possui 10 elementos que são acessados (referenciados) pelos índices:
    Os índices de cada elemento são escritos entre colchetes [ ].
    Veja um vetor de duas dimensões e vinte e cinco elementos (5 x 5):
    Ele possui 25 elementos que são acessados (referenciados) pelos índices:
    Cada elemento é representado por dois índices (um para cada dimensão), entre colchetes e adjacentes [ ][ ].
    Veja um vetor de três dimensões e cento e vinte e cinco elementos (5 x 5 x 5):
    Ele possui 125 elementos que são acessados (referenciados) pelos índices:

## Declaração de um vetor

Para declarar um vetor, utiliza-se a seguinte sintaxe:
    ou
    Onde:
       tipo = tipo de dado ou de elemento;
       identificador = nome do vetor.
    Um vetor de duas dimensões é criado do seguinte modo:
    ou
    Um vetor de três dimensões é criado do seguinte modo:
    ou
    E assim, por diante - um vetor de quatro dimensões é criado do seguinte modo:
    ou

## Dados em um vetor

    Os elementos dos vetores podem ser atribuídos da seguinte forma (separados por vírgulas e entre chaves. Por exemplo, em um vetor unidimensional poderíamos indicar os dados de seus elementos assim:
onde cada um dos valores X é um valor do elemento de índice correspondente no vetor. A numeração dos índices começa a partir do 0 e pode ser somente número natural, ou seja, inteiro maior ou igual a zero.
    Vetores podem ser declarados e iniciados conforme o seguinte exemplo - cada dimensão é delimitada por chaves e cada elemento é separado do outro através de vírgulas:
    Outro modo de uso é declarando, iniciando com o tamanho (quantidade de elementos) do vetor e depois atribuindo os valores, como o equivalente a seguir:
    Ou então, atribuindo os elementos individualmente:
    Observação: lembre-se que o ponto é utilizado para separar a parte inteira da parte fracionário de um número (notação inglesa) enquanto que a vírgula separa elementos.
    Vetores de caracteres também são chamados de strings (cadeias de caracteres) e podem ser representados como um conjunto de caracteres cercado por aspas. Podemos declarar e atribuir tipos não básicos. No exemplo a seguir, frase é um vetor de objetos da classe String. Cada elemento de frase é também um vetor de caracteres. Por exemplo, "Bom dia" é o primeiro elemento do vetor frase e também, por si só, é um vetor de caracteres {'B','o','m',' ','d','i','a'}.

### Acessando os elementos do vetor

    Para representar ou acessar um único elemento de um vetor, usa-se a sintaxe:
    onde:
       identificador = nome do vetor;
       i$_n$ = é a literal que representa o elemento de índice n.
    Assim, no exemplo acima, frase[0] é igual a "Bom dia".
Observação: como a numeração dos índices começa em 0, frase poderá ter somente, no exemplo acima, os índices 0, 1 ou 2.
    Cada dimensão do vetor é representada por um conjunto de colchetes. Assim, um vetor x de:
   * uma dimensão é acessado:
   * duas dimensões é acessado:
   * três dimensões é acessado:
   * quatro dimensões é acessado:
       e assim por diante.

## Comparando um vetor de duas dimensões com uma matriz algébrica

    Por exemplo, podemos representar a seguinte matriz:
$B={\begin{bmatrix}8&0&9&2\\2&4&3&1\end{bmatrix}}$
    assim, em Java:
    ou assim:
    ou assim:

## Declarando, iniciando e atribuindo valores a um vetor de duas ou mais dimensões

    Para se atribuir valores às várias dimensões de vetor, separamos cada dimensão num bloco (por chaves) e seus elementos separados por vírgulas.
    Exemplo de vetor de duas dimensões (2 elementos x 3 elementos):
    O exemplo acima corresponde à seguinte matriz:
$V={\begin{bmatrix}1,5&2,7&3,5\\1,2&3,0&4,5\end{bmatrix}}$
    Então, no caso de duas dimensões, geralmente se formata o código em Java assim (para lembrar a representação "biordenada" da matriz):
    Cada dimensão está agrupada por chaves. Cada um dos elementos da dimensão são separados por vírgulas. Os números fracionários são representados com ponto ao invés de vírgula (entre a parte inteira e a fracionária).
    Exemplo de um vetor de 3 dimensões (4 elementos x 3 elementos x 2 elementos), lembre-se que cada dimensão está agrupada entre chaves
    Equivale à sobreposição (num espaço tridimensional) dessas duas matrizes (formando a terceira dimensão):
    ${\begin{bmatrix}1&2&33\\1&22&53\\1&12&23\\1&2&3\end{bmatrix}}$ e ${\begin{bmatrix}65&47&5\\32&7&65\\5&7&5\\2&7&66\end{bmatrix}}$

# Arrays

A classe Arrays é uma classe utilitária que suporta operações em vetores. Seu nome qualificado é java.util.Arrays.

# Exemplo 2: Um Exemplo do Uso de Vetores

* LINHA 1: Uma nova classe chamada ImprimeVetores é criada
* LINHA 2: O Método main é iniciado. Isso indica que a função ImprimeVetores é a principal.
* LINHA 3: Um vetor de inteiros que representa (3, 2, 5) é criado e inicializado.
* LINHA 4: É impressa uma string que forma o trecho "O vetor possui os seguintes valores ". Esta string é concatenada com o inteiro que é o primeiro número do vetor, que é concatenado com a string ", " e assim por diante. No final, o que será impresso será: "O vetor possui os valores 3, 2 e 5.". Logo em seguida, o programa se encerra.
Perceba que com o conhecimento visto até agora, os programas que estamos fazendo não são nem um pouco interativos e rodam sempre do mesmo jeito. Também não está sendo possível mostrar muitos detalhes da Programação Orientada à Objetos. Nos próximos capítulos veremos como fazer isso.

# Exercícios sobre arrays

public class ImprimeVetores{

# Introdução às classes

O conhecimento sobre classes é um conhecimento global,sendo que toda linguagem orientada a objetos utiliza desse conceito para projetar seus objetos. Uma classe nada mais é do que um projeto de um objeto. Ao definirmos classes estamos modelando uma entidade que pode ser criada várias vezes com a mesma definição. Sendo que ao necessitarmos utilizar essa entidade temos que criar um objeto através do nosso modelo que é a classe. Fazendo uma analogia, uma receita de bolo seria a classe o resultado dessa receita, o bolo, seria o objeto.

# Declaração de classes

Para declarar uma classe em java, utilizamos a palavra reservada class. Por exemplo:
Digamos que criamos a classe YouTube. Se quero declarar essa classe como de acesso geral utilizaria a seguinte sintaxe:

# Objetos

Elementos de software que representam entidades físicas ou abstratas, simples ou complexas, dentro de um sistema. Possuem identidade, responsabilidades específicas, estado e um conjunto de mensagens que estão aptos a responder.
* Estáticos: Dependem de um agente externo ao objeto para solicitar que o objeto altere o seu estado.
* Dinâmicos: O objeto é capaz de espontaneamente alterar o seu próprio estado.

# Herança

Em java a herança é realizada de maneira simples ao utilizar a palavra chave extends:
Exemplo:
Quando uma classe é criada como sub-classe de outra classe, a palavra-chave super é usada para que a sub-classe possa acessar métodos public ou protected (mas não private) da superclasse. super também é usado para invocar o constructor da superclasse, durante o constructor da subclasse.
Sintaxe:
ou
Outro exemplo:

# Modificadores
## Modificadores de acesso

Os modificadores de acesso são palavras-chave que modificam a forma como podem ser acessadas as classes, métodos e/ou variáveis.

### Modificador de acesso private

O modificador de acesso "private" quando aplicado a um atributo ou a um método indica que os mesmos só podem ser acessados de dentro da classe que os criou (encapsulamento). Uma classe que herde de uma superclasse com atributos declarados como "private" só poderá ter acesso a eles através dos métodos públicos da própria superclasse, caso contrário, não haverá acesso a estes atributos.
Exemplo

### Modificador de acesso protected

    A instrução protected indica que o método ou a variável assim declarada possa ser acessada somente dentro do pacote em que está contida através de uma subclasse.

### Modificador de acesso public

    A instrução public indica que a classe, método ou variável assim declarada possa ser acessada em qualquer lugar e a qualquer momento da execução do programa.

### Friendly

Sem modificador de acesso, o membro da classe é considerado friendly. Não há uma palavra-chave para esse modificador.

## Outros modificadores

Os modificadores a seguir podem ser usados em conjunto com os modificadores de acesso provendo, assim, outros comportamentos:

### Modificador de acesso static

    A palavra reservada static serve:
   * na declaração de uma variável dentro de uma classe, para se criar uma variável que será compartilhada por todas as instâncias de objetos de uma classe como um variável comum. Ou seja, a variável criada será a mesma em todas instâncias e quando seu conteúdo é modificado em uma das instâncias então ele será modificado em todas instâncias;
   * na declaração de um método que deve ser acessado diretamente na classe e não nas suas instâncias.

### Modificador abstract

    A instrução abstract serve para:
   * declarar métodos abstratos, ou seja, métodos que deverão ser desenvolvidos/implementados nas subclasses. Quando a classe que contiver métodos abstratos for herdada, os referidos métodos deverão ser implementados, caso contrário, a classe que extendeu deverá ser declarada como abstrata.
   * declarar classes abstratas que se desenvolvem numa(s) subclasse(s). Classes abstratas são aquelas que não estão totalmente implementadas/descritas. Uma classe abstrata não pode ser instanciada e é amplamente usada nas interfaces.
   * Uma classe é considerada abstrata se contiver pelo menos um método abstrato. Um método abstrato tem a seguinte característica: void getName( );
   * Caso o método tenha as chaves características, o mesmo não mais será considerado abstrato, embora não tenha código dentro das chaves.

### Modificador final

    A instrução final indica que a classe, método ou variável assim declarada têm uma única atribuição que se mantém constante, ou seja, não pode ser alterada no decorrer do processamento.
    Além de não admitir a criação de classes filhas.
    Este modificador declara o que chamamos, em programação, de constante.

# Fluxos de entrada e saída

A entrada e saída de dados em Java é feita através de streams.
Uma stream é uma sequência ordenada de bytes ou caracteres de tamanho indefinido. Streams podem ser abertas e fechadas pelo programa; algumas vezes, estas operações são feitas de forma automática (normalmente em caso de erro).
Um programa que usa uma stream deve incluir a biblioteca java.io, ou seja, deve incluir logo no início:
ou instruções equivalentes.
Assim como em C/C++, uma stream não é usada diretamente através do nome do arquivo; é preciso abri-la como um File para depois usar as operações em streams.
Por exemplo, o programa abaixo pega o arquivo "teste1.txt" e copia seu conteúdo (bit-a-bit) para o arquivo "teste2.txt":
Explicações:
apenas associam os streams inputFile e outputFile aos nomes "teste1.txt" e "teste2.txt". Neste ponto, não foi dito que "teste1.txt" é entrada, nem que "teste2.txt" é saída (obvimente, os nomes inputFile e outputFile são apenas conveniência para o leitor do programa).
Neste ponto são criados os dois streams. in é o stream de entrada, e out é o stream de saída. Como, na declaração do main, previmos uma exceção no I/O, caso o arquivo de entrada "teste1.txt" não exista, será gerada uma mensagem de erro.
c é um inteiro. read, enquanto houver elementos para serem lidos, retorna números naturais, e retorna -1 no final. write escreve este número. Este loop (extremamente ineficiente para arquivos grandes!) faz a cópia, caracter a caracter, do arquivo de entrada para o arquivo de saída.
fecha os streams.

# Coleções

O Collections Framework também conhecido em línguas lusófonas como Coleções é uma arquitetura que provê implementações de estruturas de dados na API do Java. Suas classes, interfaces e enums estão localizadas no pacote java.util.

# Collections

A classe Collections é uma classe utilitária que suporta operações em coleções. Assim como todas as outras coleções está localizada no pacote java.util.

# Iterator

A interface java.util.Iterator tem a finalidade de prover capacidade de iteração às classes, principalmente as de coleções, que implementam java.util.Iterable.

# ArrayList

A classe ArrayList é uma implementação da interface List que utiliza um vetor para armazenar elementos. Uma vez que vetores tem tamanho fixo em Java, a classe ArrayList se encarrega de criar um novo vetor (internamente) com um tamanho maior e copiar seus elementos correntes para esse novo vetor sempre que for necessário.
O vetor interno da classe ArrayList é recriado quando há remoções de elemento, adições de elemento no fim da lista além da capacidade dimensionada e adições de elementos que não no final da lista.
Como a operação de recriação do vetor é custosa, busque dimensionar previamente o tamanho da lista, para tal, utilize o construtor sobrecarregado ArrayList(int) enviando como argumento a capacidade inicial da lista. A capacidade inicial padrão de um objeto ArrayList é de 10 elementos.

## Métodos não constantes na interface List

Saída
Foi utilizado o construtor sobrecarregado ArrayList<>(int) para definir a capacidade inicial do vetor interno. Não confunda a capacidade inicial do vetor com o tamanho da Lista. O tamanho é devolvido pelo método size e corresponde à quantidade de elementos armazenados já a capacidade é o tamanho do vetor interno o qual não temos acesso.
O método ensureCapacity(int) recriou o vetor interno com o capacidade para 15 elementos.
O método trimToSize(int) recriou novamente o vetor interno, porém agora com a capacidade igual ao tamanho da lista, no caso 3.
O método clone, sobrescrito de Object e indicado pela implementação da interface Clonable, atribuiu uma instância de ArrayList à variável listaClone com os mesmos elementos, que são as referências às 3 instâncias do objeto NavegadorWeb que incluímos na variável listaOriginal. Como o método clone devolve um tipo Object, foi necessário o uso do cast com o tipo (ArrayList<Navegador>). Conforme evidenciado na chamada do método setNome("Edge") o método clone apenas copia a lista e não cada um de seus elementos e com a chamada ao método remove(1) percebemos que as instâncias de ArrayList nas variáveis listaOriginal e listaClone são diferentes e portanto desvinculadas.
Como você pode ter concluído, o uso dos métodos ensureCapacity(int) e trimToSize(int) não é recomendável pois eles recriam o vetor interno do objeto ArrayList situação em que a performance é prejudicada.

# Exercício

* Depure o código acima e observe em que chamadas de métodos o atributo elementData é alterado.
* Os métodos add e remove alteram a capacidade da instância de ArrayList das variáveis listaOriginal e listaClone?

# A classe Thread

Resumidamente, uma Thread em Java é composta de três partes:
* CPU ( processamento compartilhado para executar rotinas )
* Código ( linhas de código de uma rotina que serão executadas )
* Dados ( área de dados que fazem parte da execução da rotina )
Ou seja, o objeto Thread do Java proveniente da classe java.lang.Thread, representa uma instância da CPU da máquina virtual Java, e que tem associada um trecho de código que será executado, e uma área de memória.
Podemos criar uma Thread em Java de duas maneiras:
* Estendendo o comportamento da classe Thread
* Implementando a interface Runnable

### Criando uma Thread a partir da classe java.lang.Thread

O código abaixo mostra como criar uma classe que [funciona] como uma Thread:
O código abaixo mostra como usar a classe MinhaThread:
Executando o classe TesteMinhaThread, veremos que as Threads incrementam o contador separadamente, baseado no objeto MinhaThead.

### Criando uma Thread a partir da interface java.lang.Runnable

O código abaixo mostra como criar uma classe que funciona como uma Thread:
O código abaixo mostra como usar a classe MeuRunnable:
Executando o classe TesteMeuRunnable, veremos que as Threads incrementam o contador separadamente, baseado no objeto MeuRunnable.

### Considerações de Design

* Usar a implementação do Runnable, dá maior flexibilidade de Design, pois permite que a classe que implementou a interface java.lang.Runnable estenda o comportamento de outra classe.
* Estender diretamente a classe Thread, facilita o acesso aos métodos da classe java.lang.Thread, mas dificulta a modelagem da POO pois impede que a sub-classe de Thread estenda outra classe.

### Desafio

Criar uma pequena aplicação gráfica usando a Java SWING API de simulador simples para um prédio que tenha 3 elevadores e que funcionam independentemente.

## Ligações externas

* Linguagem Java - Wikipedia
* Sun Java Tutorial - Threads
* Sun Java Tutorial - SWING

# GUI

As principais interfaces gráficas para Java são AWT e Swing.

## AWT

Abstract Window Toolkit foi a interface gráfica original da linguagem.

## Swing

    Ver módulo principal: Java/Swing
A interface Swing foi desenvolvida depois da AWT, e é considerada mais fácil de ser usada e com mais recursos.

# Swing

Swing é uma API Java para interfaces gráficas. Ela é compatível com a API AWT, mas trabalha de uma maneira totalmente diferente. A API Swing procura renderizar\desenhar por contra própria todos os componentes, ao invés de delegar essa tarefa ao sistema operacional, como a maioria das outras APIs de interface gráfica trabalham.
Por ser uma API de mais alto nível, ou seja, mais abstração, menor aproximação das APIs do sistema operacional, ela tem bem menos performace que outras APIs gráficas e consome mais memória RAM em geral. Porém, ela é bem mais completa, e os programas que usam Swing têm uma aparência muito parecida, independente do Sistema Operacional utilizado.
Este capítulo segue a estrutura do livro Programação em GUI

## Índice

* Primeiro programa
* Widgets
* Eventos e Action listeners

## Ver também

* Tutorial em português

# Autores

Os usuários citados abaixo contribuiram para o desenvolvimento deste trabalho. Estes dados foram obtidos em 16/12/2013.
Abacaxi, Albmont, Alexandref93, Alexandreqo, Alguém, Daniel Souza, Dante Cardoso Pinto de Almeida, David Stress, Devarde, Edufsousa, Ezarate, Felipe Gustavo Firmo, Fesaopilger, Guiwp, Helder.wiki, Helder.wiki.bot, Hojerio, JackPotte, Jonas AGX, Jorge Morais, Julianocanuto, LipeFontoura, Luís Felipe Braga, Lukas²³, Marco Antonio Bidóia, Marcos Antônio Nunes de Moura, Master, Maxtremus, MGFE Júnior, Mike.lifeguard, Nunesnd, PatiBot, PatríciaR, Profvalente, Raylton P. Sousa, Ruy Pugliesi, SallesNeto BR, Scorpion, Seduardo, Sfragata, Thiagoharry, Voz da Verdade, Wbrito, Webcentro, Wutsje.

# Palavra-chave

    Em programação, palavras-chave, ou palavras reservadas, são as palavras que não podem ser usadas como identificadores, ou seja, não podem ser usadas como nome de variáveis, nome de classes, etc. Estas palavras são assim definidas ou porque já têm uso na sintaxe da linguagem ou porque serão usadas em alguns momento, seja para manter compatibilidade com versões anteriores ou mesmo com outras linguagens. No caso do Java temos as seguintes palavras-chave:
| abstract | continue | for | new | switch |
| assert(3) | default | goto(1) | package | synchronized |
| boolean | do | if | private | this |
| break | double | implements | protected | throw |
| byte | else | import | public | throws |
| case | enum(4) | instanceof | return | transient |
| catch | extends | int | short | try |
| char | final | interface | static | void |
| class | finally | long | strictfp(2) | volatile |
| const(1) | float | native | super | while |
| null |

# Ferramentas da Linguagem Java

As ferramentas são os programas fornecidos no JSDK:
* appletviewer
* apt
* extcheck
* htmlconverter
* keytool
* jar
* jarsigner
* java
* javac
* javadoc
* javah
* javap
* javaw
* javaws
* jconsole
* jdb
* jinfo
* jmap
* jps
* jsadebugd
* jstack
* jstat
* jstatd
* kinit
* klist
* ktab
* idlj
* native2ascii
* orbd
* pack200
* policytool
* rmic
* rmiregistry
* rmid
* serialver
* servertool
* tnameserv
* unpack200

# RMI
## Introdução

A tecnologia Java RMI (Remote Method Invocation) consiste em uma biblioteca capaz de permitir que um programa rodando em uma dada máquina efetue chamadas à objetos instanciados em outra máquina. Apesar de ser desenvolvida focando principalmente a chamada de procedimentos à objetos localizados em máquinas distintas ela também pode ser utilizada para efetuar a comunicação entre dois processos rodando na mesma máquina (desde que ambos utilizem a JVM), muito embora tecnologias como XPCOM e outras possam disponibilizar performance e integração melhores.

## Tenologias semelhantes

Existem duas outras tecnologias que se assemelham muito com a RMI: CORBA e .NET Remoting (que no .NET 3.0 foi incorporada pela WCF). A tecnologia .NET Remoting é pode ser vista como a resposta Microsoft à tecnologia RMI, e possui quase as mesmas características. Já a tecnologia CORBA é divulgada à mais tempo e possui a vantagem de possuir bibliotecas em diversas linguagens, assim um objeto CORBA pode ser utilizado em vários programas escritos em linguagens diferentes (a tecnologia RMI foi feita exclusivamente para a plataforma Java).

## Um exemplo rápido

Para demonstrar a facilidade da linguagem, vou criar um exemplo bem simples que irá utilizar a tecnologia RMI. Um pequeno aplicativo para postar mensagens em um fórum e listar as mesmas.
Primeiro devemos criar uma interface que será utilizada para exibir aos usuários dos serviço as operações.
Depois devemos criar uma classe que irá implementar a interface e disponibilizar a funcionalidade.
Feito isso vamos implementar a classe que irá disponibilizar o serviço ao usuário.
Na classe acima observe a linha:
Ela é responsável por associar um nome ao seu objeto. É através deste nome que os computadores e processos remotos irão encontrar e utilizar o seu objeto. Este nome é único para um dado host, ou seja, mesmo se duas aplicações criarem objetos distintos (até mesmo de classes distintas) o mesmo nome não poderá ser utilizado.
Por último vamos implementar a classe que irá utilizar o serviço disponibilizado.
A linha:
Efetua uma consulta no host informado (neste caso o localhost) e solicita o objeto associado ao nome: forumService.
O resto do código fala por si só, e graças ao RMI as chamadas são idênticas á chamadas locais. Melhorando um pouco o design da aplicação é possível criar um objeto local ou então um remoto dependendo da ocasião.
Para facilitar o teste, a classe abaixo foi criada apenas para permitir rodar o serviço através da linha de comando: "java -jar arquivoJar.jar"
pronto! Para executar basta compilar as classes, iniciar o aplicativo rmiregistry que é o responsável por encontrar e disparar as chamadas aos objetos corretos e iniciar o servidor em um terminal ou prompt.
Após isso feito abra outro terminal ou prompt e inicie a aplicação cliente.
Observação importante: neste caso o teste é apenas local mas quando utiliza-se um ambiente com diversas máquinas é muito importante iniciar a aplicação servidor com a opção: -Djava.rmi.server.hostname=<nome_ou_ip_do_host>. Caso não seja feito o objeto pode ser exportado com o host errado e a aplicação cliente pode tentar disparar o procedimento em um endereço diferente do solicitado.
Existem diversas outras características da tecnologia RMI que não foram abordadas, como por exemplo a capacidade de baixar o código de uma determinada classe de modo transparente. Assim mesmo que o contexto local não reconheça uma classe esta será transferida do servidor e poderá ser utilizada pela aplicação.

## Fontes e referências

* Informações sobre RMI - Sun
* Java RMI - André Luiz Alves Moraes