Você está na página 1de 50

APOSTILA JAVA

Capítulo 1
Java
Java é uma linguagem de programação orientada a objetos desenvolvida na
década de 90 por uma equipe de programadores chefiada por James Gosling, na
empresa Sun Microsystems. Diferentemente das linguagens convencionais, que são
compiladas para código nativo, a linguagem Java é compilada para um "bytecode"
que é executado por uma máquina virtual. A linguagem de programação Java é a
linguagem convencional da Plataforma Java, mas não sua única linguagem.

Histórico
Em 1991, na Sun Microsystems, foi iniciado o GreenProject, o berço do Java,
uma linguagem de programação orientada a objetos. Os mentores do projeto eram
Patrick Naughton, Mike Sheridan, e James Gosling. O objetivo do projeto não era a
criação de uma nova linguagem de programação, mas antecipar e planejar a
“próxima onda” do mundo digital. Eles acreditavam que, em algum tempo, haveria
uma convergência dos computadores com os equipamentos e eletrodomésticos
comumente usados pelas pessoas no seu dia-a-dia.

Para provar a viabilidade desta idéia, 13pessoas trabalharam arduamente


durante 18 meses. No verão de 1992 eles emergiram de um escritório de Sand Hill
Roadno Menlo Park com uma demonstração funcional da idéia inicial. O protótipo
se chamava *7 (leia-se“StarSeven”), um controle remoto com uma interfacegráfica
touch screen. Para o *7, foi criado um mascote, hoje amplamente conhecido no
mundo Java, o Duke. O trabalho do Duke no *7 era ser um guia virtual ajudando e
ensinando o usuário a utilizar o equipamento. O *7 tinha a habilidade de controlar
diversos dispositivos e aplicações. James Gosling especificou uma nova linguagem
de programação para o *7. Gosling decidiu batizá-la de “Oak”, que quer dizer
carvalho, uma árvore que ele podia observar quando olhava pela sua janela.

O próximo passo era encontrar um mercado para o *7. A equipe achava que
uma boa idéia seria controlar televisões e vídeo por demanda com o equipamento.
Eles construíram um demo chamado Movie Wood, mas infelizmente era muito
cedo para que o vídeo por demanda bem como as empresas de TV a cabo
pudessem viabilizar o negócio. A idéia que o *7 tentava vender, hoje já é realidade
em programas interativos e também na televisão digital. Permitir ao telespectador
interagir com a emissora e com a programação em uma grande rede cabos, era algo
muito visionário e estava muito longe do que as empresas de TV a cabo tinham
capacidade de entender e comprar. A idéia certa, na época errada.

Entretanto, o estouro da Internet aconteceu e rapidamente uma grande


rede interativa estava se estabelecendo. Era este tipo de rede interativa que a
equipe do *7 estava tentando vender para as empresas de TV a cabo. E, da noite
para o dia, não era mais necessário construir a infraestrutura para a rede, ela
simplesmente estava lá. Gosling foi incumbido de adaptar o Oak para a Internet e
em janeiro 1995 foi lançada uma nova versão do Oak que foi rebatizada para Java.
A tecnologia Java tinha sido projetada para se mover por meio das redes de
dispositivos heterogêneos, redes como a Internet. Agora aplicações poderiam ser
executadas dentro dos browsers nos Applets Java e tudo seria disponibilizado pela
Internet instantaneamente. Foi o estático HTML dos browsers que promoveu a
rápida disseminação da dinâmica tecnologia Java. A velocidade dos acontecimentos
seguintes foi assustadora, o número de usuários cresceu rapidamente, grandes
fornecedores de tecnologia, como a IBM anunciaram suporte para a tecnologia
Java.

Desde seu lançamento, em maio de 1995, a plataforma Java foi adotada mais
rapidamente do que qualquer outra linguagem de programação na história da
computação .Em 2003 Java atingiu a marca de 4 milhões de desenvolvedores em
todo mundo. Java continuou crescendo e hoje é uma referência no mercado de
desenvolvimento de software. Java tornou-se popular pelo seu uso na Internet e
hoje possui seu ambiente de execução presente em web browsers, mainframes,
SOs, celulares, palmtop se cartões inteligentes, entre outros.

Padronização
Em 1997 a Sun Microsystems tentou submeter a linguagem a padronização
pelos orgãos ISO/IEC e ECMA, mas acabou desistindo. Java ainda é um standard de
fato, que é controlada através da JCP Java Community Process. Em 13 de Novembro
de 2006, a Sun lançou a maior parte do Java como Software Livre sob os termos da
GNU General Public License(GPL). Em 8 de Maio de 2007 a Sun finalizou o
processo, tornando praticamente todo o código Java como software de código
aberto, menos uma pequena porção que a Sun não possui copyright.

Principais Características da Linguagem Java


A linguagem Java foi projetada tendo em vista os seguintes objetivos:

• Orientação a objeto - Baseado no modelo de Smalltalk e Simula67;


• Portabilidade - Independência de plataforma - "write once run anywhere";
• Recursos de Rede - Possui extensa biblioteca de rotinas que facilitam a
cooperação com protocolos TCP/IP, como HTTP e FTP;
• Segurança - Pode executar programas via rede com restrições de execução;

Além disso, podem-se destacar outras vantagens apresentadas pela linguagem:

• Sintaxe similar a Linguagem C/C++.


• Facilidades de Internacionalização - Suporta nativamente caracteres
Unicode;
• Simplicidade na especificação, tanto da linguagem como do "ambiente" de
execução (JVM);
• É distribuída com um vasto conjunto de bibliotecas (ou APIs);
• Possui facilidades para criação de programas distribuídos e multitarefa
(múltiplas linhas de execução num mesmo programa);
• Desalocação de memória automática por processo de coletor de lixo
(garbage collector);
• Carga Dinâmica de Código - Programas em Java são formados por uma
coleção de classes armazenadas independentemente e que podem ser
carregadas no momento de utilização.

Máquina Virtual Java


Programas Java não são traduzidos para a linguagem de máquina, como
outras linguagens estaticamente compiladas e sim para uma representação
intermediária, chamada de bytecodes.

Os bytecodes são interpretados pela máquina virtual Java (JVM - Java


Virtual Machine). Muitas pessoas acreditam que por causa desse processo, o código
interpretado Java tem baixo desempenho. Durante muito tempo esta foi uma
afirmação verdadeira. Porém, novos avanços têm tornado o compilador dinâmico
(a JVM), em muitos casos, mais eficiente que o compilador estático.

Java hoje já possui um desempenho próximo do C++. Isto é possível graças a


otimizações como a compilação especulativa, que aproveita o tempo ocioso do
processador para precompilar bytecode para código nativo. Outros mecanismos
ainda mais elaborados como o HotSpot da Sun, que guarda informações
disponíveis somente em tempo de execução (ex.: número de usuários,
processamento usado, memória disponível),para otimizar o funcionamento da
JVM, possibilitando que a JVMvá "aprendendo" e melhorando seu desempenho.
Isto é uma realidade tão presente que hoje é fácil encontrar programas
corporativos e de missão crítica usando tecnologia Java. No Brasil, por exemplo, a
maioria dos Bancos utiliza a tecnologia Java para construir seus home banks, que
são acessados por milhares de usuários diariamente. Grandes sítios como o eBay
utilizam Java para garantir alto desempenho. E a cada ano Java tem se tornado
mais rápido, na medida que se evolui o compilador dinâmico.

Essa implementação no entanto tem algumas intrínsecas. A pré-compilação


exige tempo, o que faz com que programas Java demorem um tempo
significativamente maior para começarem a funcionar. Soma-se a isso o tempo de
carregamento da máquina virtual. Isso não é um grande problema para programas
que rodam em servidores e que deveriam ser inicializados apenas uma vez. No
entanto isso pode ser bastante indesejável para computadores pessoais onde o
usuário deseja que o programa rode logo depois de abri-lo. A próxima versão da
máquina virtual produzida pela Sun promete novos recursos que irão minimizar
este fato.1

O Java ainda possui uma outra desvantagem considerável em programas


que usam bastante processamento numérico. O padrão Java tem uma especificação
rígida de como devem funcionar os tipos numéricos. Essa especificação não condiz
com a implementação de pontos flutuantes na maioria dos processadores o que faz
com que o Java seja significativamente mais lento para estas aplicações quando
comparado a outras linguagens.

Os bytecodes produzidos pelos compiladores Java podem ser usados num


processo de engenharia reversa para a recuperação do programa-fonte original.
Esta é uma característica que atinge em menor grau todas as linguagens
compiladas. No entanto já existem hoje tecnologias que "embaralham" e até
mesmo criptografam os bytecodes praticamente impedindo a engenharia reversa.

Extensões

Extensões em Java:
• J2SE (Standard Edition)
• J2EE (Enterprise Edition)
• J2ME (Micro-Edition for PDAs and cellular phones)
• JCE (Java Cryptography Extension)
• JMF (Java Media Framework)
• JNDI (Java Naming and Directory Interface)
• JSML (Java Speech API Markup Language)
• JDBC (Java Database Connectivity)
• JMS (Java Message Service)
• JAAS (Java Authentication and Authorization Service)
• JDO (Java Data Objects)
• JAIN (Java API for Integrated Networks)
• JDMK (Java Dynamic Management Kit)
• Jini (a network architecture for the construction of distributed systems)
• Jiro
• JXTA (open source-based peer-to-peer infrastructure)
• Java Card
• JavaSpaces
• JMI (Java Metadata Interface)
• JMX (Java Management Extensions)
• JSP (JavaServer Pages)
• JSF (JavaServer Faces)
• JNI (Java Native Interface)
• J3D (A high level API for 3D graphics programming)
• JOGL (A low level API for 3D graphics programming, using OpenGL)
• OSGi (Dynamic Service Management and Remote Maintenance)
• SuperWaba (JavaVMs for handhelds)
• MARF (Modular Audio Recognition Framework)
• JavaFX

Frameworks
É possível utilizar frameworks parafacilitar o desenvolvimento de aplicações.
Dentreos mais utilizados pode-se destacar:
• Hibernate ferramenta para ORM;
• Spring ferramenta que auxilia principalmente implementação de injeção de
dependências e inversão de controle;
• Log4j ferramenta para facilitar a criação de logs na aplicação;
• Junit ferramenta para auxiliar na criação de testes unitários;
• Struts controlador MVC (Model 2) web.

Ambientes de desenvolvimento
É possível desenvolver aplicações sem Java através de vários ambientes de
desenvolvimento integrado (IDE's). Dentre as opções mais utilizadas pode-se
destacar:

• Eclipse — um projeto aberto iniciado pela IBM;


• NetBeans — um ambiente criado pela empresa Sun Microsystems;
• JBuilder — um ambiente desenvolvido pela empresa Borland;
• JDeveloper — uma IDE desenvolvida pela empresa Oracle;
• JCreator — um ambiente desenvolvido pela Xinox.
• BlueJ — um ambiente desenvolvido por uma faculdade australiana(muito
bom para iniciantes).
• Greenfoot — bem parecido com o BlueJ
• JGRASP — bom para intermediários, feito pela equipe do projeto GRASP.
• IntelliJ IDEA — uma IDE desenvolvida pela JetBrains (considerada por
muitos a melhor IDE do mercado).

Certificações
Existem 8 tipos de certificações da Sun Microsystems para Java:

• Sun Certified Enterprise Architect (SCEA)


• Sun Certified Mobile Application Developer (SCMAD)
• Sun Certified Developer For Java Web Services (SCDJWS)
• Sun Certified Business Component Developer (SCBCD)
• Sun Certified Web Component Developer (SCWCD)
• Sun Certified Java Developer (SCJD)
• Sun Certified Java Programmer (SCJP)
• Sun Certified Java Associate (SCJA)
• Cada certificação testa algum tipo de habilidade dentro da plataforma e
linguagem Java. Todos os testes são realizados pela empresa Prometric e
são reconhecidos internacionalmente.

Comunidade
A comunidade de desenvolvedores Java reúne-se em grupo denominados
JUGs (Java User Groups). No Brasil o movimento de grupos de usuários expandiu-
se bastante e tem formado alguns dos maiores grupos de usuários Java do mundo,
como, por exemplo, o Portal Java e o GUJ.
Licença
A Sun disponibiliza a maioria das distribuições Java gratuitamente e obtém
receita com programas mais especializados como o Java Enterprise System. Em 13
de novembro de 2006, Sun liberou partes de Java como software livre, sob a
licença GNU General Public License(GPL). A liberação completa dos programas
fonte sob a GPL é esperada para o primeiro trimestre de 2007.
Capítulo 2
O que é necessário para programar em JAVA
Para programar em Java, não é necessário ter programado antes. Porém,
ficaria mais fácil se tiver conhecimento em linguagem Orientada a Objeto, porque
Java é totalmente estruturada em objetos (Classes, métodos, abstração, etc).

Para começar a programar será necessário fazer o download do JDK (Java


Development Kit - Kit de desenvolvimento Java) que é gratuito e pode ser obtido
direto do site da Sun Microsystem. Além disso, também, um compilador de Java.
Existem vários tipos, uns mais leves e simples e outros mais pesados e complexos
de usar. Se não souber qual usar, veja nossa lista de compiladores Java.
Então, mãos à obra, instale um compilador e comece seu projeto. Vá para o
primeiro programa em Java.

Primeiro Programa em Java


Veremos aqui o nosso primeiro código em linguagem Java.
A única coisa que esse programa faz é imprimir (mostrar) na tela uma
mensagem dizendo: Bem vindo ao mundo Java!.

1.//Primeiro programa em Java


2.public class MeuPrimeiroPrograma {
3. public static void main(String[] args) {
4. System.out.println("Bem vindo ao mundo Java!");
5. }
6.}

Primeiramente, iremos entender algumas estruturas básicas da linguagem.

Usamos // para indicar que foi iniciado um comentário. Um comentário


serve apenas para documentar o código. Isso quer dizer que, ao ser executado este
programa, as linhas marcadas como comentário serão ignoradas.
Este tipo de comentário é de linha única, ou seja, começa nas barras e termina no
final da linha. Se quisermos criar comentário de várias linhas podemos utilizar /*
*/, no qual /* inicia o comentário e */ termina. Por exemplo:

//Este é um comentário de uma linha


/*Este é
um comentário
de várias
linhas*/

public class MeuPrimeiroPrograma


public class MeuPrimeiroPrograma é a criação da classe. Como Java é
totalmente orientado a objeto, sua programação é feita dentro de classes e mais
classes. O assunto de classes será abordado mais afrente. O importante a princípio
é entender que o programa para funcionar deve ter pelo menos uma classe com o
método principal (main).

public static void main


public static void main é o método principal do código. Quando executamos
um programa é esse método que é chamado. Em outras palavras, sem ele não há
programa.

(String[ ] args)
(String[] args) é o argumento passado ao método main. Qualquer programa
pode ser iniciado ou não com argumentos que modificam sua execução, trataremos
futuramente de argumentos com programas.

{}
As chaves são usadas para marcar o bloco de dados. No caso deste
algorítmo, ele marca o código que será executado na classe MeuPrimeiroPrograma
e também todo o código que será executado quando o método main for chamado.

System.out.println
System.out.println é a saída padrão de Java. É este método que indica o que
deve aparecer na tela.

("Bem vindo ao mundo Java!")


("Bem vindo ao mundo Java!") é o argumento do método System.out.println.
Neste caso é o que deve ser apresentado na tela.

Toda linha de comando em Java termina com um ponto-e-vírgula (;).

Bem, isso é o necessário para começarmos a programar em Java.


Logicamente, muitos conceitos foram deixados de lado nesta pequena prévia, mas
veremos mais aprofundadamente nas próximas páginas.

Regras e convenções de nomenclatura


Quando programamos em Java, devemos levar em consideração as
convenções de nomenclatura para deixar nosso código o mais legível e
documentável possível, pois um dos objetivos da programação orientada a objetos
é o reaproveitamento do código.

É muito provável que quem não tenha experiência com programação sinta
dificuldade de identificar todos os termos utilizados neste artigo, mas garantimos
que tudo que será visto aqui será detalhado mais adiante, embora que este artigo
se torna trivial a medida que programamos. Portanto, quem já conhece
programação em algum outro tipo de linguagem (como Delphi ou C++)
aconselhamos que prossiga para a próxima página. Porém, se nunca programou
antes, com certeza, este artigo será didático o suficiente para que entenda essas
regras.

Muitos compiladores como Eclipse e NetBeans dão um grande auxilio na


hora de criarmos nosso projeto nos informando sobre as convenções de
nomenclatura no momento que estamos criando os pacotes, classes, etc...

Nome de Classes
Por convenção, toda classe deve começar com uma letra maiúscula e, de
preferência, não pode conter letras não ASCII (caracteres de língua de origem
latina, como caracteres acentuados). Portanto, não é possível declarar uma classe
com qualquer caracter especial (@, #, $, %, &, *, _, etc...) ou número.

Caso o nome de uma classe seja composto por mais de uma palavra, a
primeira letra de cada palavra deve ser em maiúscula.

O nome da classe deve ser exatamente o mesmo nome de seu arquivo fonte
( .java ).

O nome da classe deve fazer referência total ao seu objeto (atributos e


métodos contidos dentro da classe). Por exemplo: se tivermos uma classe com os
atributos canal, volume e sintonia; e os métodos mudarCanal (), aumentarVolume
() e diminuirVolume (); então, possivelmente chamaríamos esta classe de TV ou
Televisao. Contudo, em uma classe que contivesse o atributo corDasPenas e o
método voar () jamais chamaríamos de Pessoa (por que pessoas não tem penas e
nem voam).

Exemplos de nomes de classes: Pessoa, ImpostoDeRenda, Conta,


AgenciaDeEmprego, ...

Nome de Pacotes
Os pacotes devem começar com uma letra minúscula e podem usar letras
não ASCII. Jamais poderemos iniciar o nome de um pacote com caracteres
especiais (@, #, $, %, &, *, _, etc...) ou número.

Caso o nome de um pacote seja composto por mais de uma palavra, a


primeira letra de cada palavra deve ser em maiúscula.
O nome do pacote deve ser o mesmo nome da pasta a qual ele se refere. Por
exemplo, se os arquivos fonte estão na pasta criptografia, então o nome do pacote
deve ser criptografia.

O nome do pacote deve fazer referência total às funções exercidas pelas


classes dentro do pacote, pois pacotes servem basicamente para organizar os
arquivos de código fonte de nosso projeto.

Exemplos de nomes de pacotes: criptografia, usuários,


conexõesDeBancoDeDados , ...

Nome de atributos ou variáveis


Os atributos (variáveis) podem começar com qualquer letra e os caracteres
$ ou _, porém não podem começar com números.

Caso o nome de um atributo (variável) seja composto por mais de uma


palavra, a primeira letra de cada palavra deve ser em maiúscula.

Exemplos de nomes de atributos ou variáveis: x, y, resultado, valorDeX,


valorDeY, ligado, ...

Nome de atributos finais ou constantes


Os atributos finais (constantes) devem ser escritos em letras maiúsculas.

Usamos underline (_) para separar nomes compostos de atributos finais


(constantes).

Exemplos de nomes de atributos finais ou constantes: TAMANHO,


PARAR_DE_EXECUTAR, ...

O que são atributos e variáveis


Para quem já programou antes em alguma linguagem de programação não
orientada a objetos, deve achar estranho o termo atributo porque, na verdade, está
mais acostumado com o termo variável.

Mas, qual a diferença entre atributos e variáveis? Nenhuma.

Atributos e variáveis são a mesma coisa em questão de funcionalidade.


Ambos são endereços de memória que tem um espaço ou tamanho definido de
acordo com o tipo de dado que será guardado, por exemplo: caractere, número,
número decimal, etc. Em Java, costumamos utilizar o termo atributo, que é nada
além do que uma variável que está dentro de uma classe. Como tudo que fazemos
em Java está contido dentro de uma classe, então usamos o termo atributo ao invés
de variável.
Tipos de dados e declaração de atributos
Todo programa de computador deve ser capaz de lidar com dados para
conseguir fazer seus processos como, por exemplo, somar, multiplicar, dividir, etc...
Usar atributos é a melhor forma de manipular os dados.
Os tipos de dados são o que definem a quantidade de memória do
computador que será utilizado para guardar tal dado. Cada tipo de dado tem um
tamanho diferente e por consequência seu alcance também. O que queremos dizer
é que se declararmos um atributo para guardar um número inteiro, jamais
poderemos guardar um número decimal, porque um número decimal ocupa mais
espaço de memória que um inteiro.
Para declararmos qualquer tipo de atributo, usamos a seguinte ordem: primeiro o
tipo de dado e depois o nome do atributo. Se não souber como nomear um
atributo, veja as regras e convenções de nomenclatura.
Vamos iniciar com os tipos de dados inteiros que são os mais simples. Em
Java, os números inteiros são divididos em quatro tipos: byte, short, int e long.
Esses quatro guardam o mesmo tipo de dado, mas ocupam espaços de
memória diferente, o que afeta em seu alcance.
O tipo byte é o de menor alcance entre os inteiros. Como o próprio nome
sugere, ele consome apenas um byte (8 bits) e pode guardar valores entre -128 e
127.
O tipo short guarda inteiros de 2 bytes (16 bits) e pode guardar números
entre -32.768 a 32.767.
O tipo int é o tipo de dado mais comum. Ele consome 4 bytes (32 bits) e
guarda valores entre -2.147.483.648 e 2.147.483.647.
Long é o tipo de dado com maior alcance entre os inteiros.
Consequentemente, também é o que ocupa mais espaço (8 bytes ou 64 bits). Tem
um grande alcance que fica entre -9,22E+18 (exatos -9.223.372.036.854.775.808)
e 9,22E+18 (exatos 9.223.372.036.854.775.807).
Existem os tipos de dados próprios para caracteres que é o char.
O tipo char ocupa 2 bytes, o que torna Java ideal para programar em língüas
latinas, asiáticas ou qualquer outra que utilize caracteres diferentes do padrão
ASCII.
O padrão ASCII utiliza apenas um byte que fornece 256 letras diferentes,
mas o padrão utilizado em Java (ISO) nos dá a possibilidade de até 65.536
caracteres diferentes.
Para números decimais utilizamos dois tipos de dados, dependendo da
necessidade de seu alcance e precisão (números após a vírgula).
O tipo de dado mais comum para número decimal é o float. Em um tipo de
dado float, podemos guardar números grandes que vão desde 1,4E-45 até
3,4028235E+38
Para número decimais com grande precisão ou valores extraordinários
(geralmente utilizados em matemática aplicada e complexa como cálculos físicos,
químicos, astrológicos, meteorológicos, etc) utilizamos o tipo de dado double.
Double é o tipo de dado mais complexo que há em Java e o maior valor
possível de se armazenar é 1,797.693.134.862.315.7E+308. Muito mais do que
qualquer programador precisa.
Para ilustra melhor essa explicação, abaixo está um pequeno algoritmo com
alguns atributos e seus valores mínimos e máximos.
01.public class TiposDeDados {
02. public static void main(String[] args) {
03. System.out.println("Tipos de dados em Java: \n" +
04. "\nMenor Byte: " + Byte.MIN_VALUE +
05. "\nMaior Byte: " + Byte.MAX_VALUE +
06. "\nMenor Short Int: " + Short.MIN_VALUE +
07. "\nMaior Short Int: " + Short.MAX_VALUE +
08. "\nMenor Int: " + Integer.MIN_VALUE +
09. "\nMaior Int: " + Integer.MAX_VALUE +
10. "\nMenor Long: " + Long.MIN_VALUE +
11. "\nMaior Long:" + Long.MAX_VALUE +
12. "\nMenor Float: " + Float.MIN_VALUE +
13. "\nMaior Float: " + Float.MAX_VALUE +
14. "\nMenor Double: " + Double.MIN_VALUE +
15. "\nMaior Double: " + Double.MAX_VALUE);
16. }
17.}

Atribuição de Valores a Variáveis ou Atributos


Como vimos, há vários tipos de dados em Java, cada um com um consumo
de memória determinado que afeta diretamente o seu alcance.

Veremos agora como atribuir valores a esses endereços de memória


(atributo ou variável).

Para atribuirmos valor a uma variável ou atributo usamos o operador =.


Neste caso, o sinal de igual não significa igualdade, mas que um valor será
atribuído.

A regra básica é que sempre o que estiver à esquerda do "=" receberá o


valor que estiver à direita.

Por exemplo: se expressarmos var1 = 10 queremos dizer que a variável


var1 receberá o número 10. Pronto! Agora, temos o número 10 gravado na
memória.

Podemos também atribuir valores contidos em outras variáveis. Por


exemplo:

var1 = 20;
var2 = var1;

A variável var1 recebe o número 20, depois a variável var2 recebe o valor
de var1 (que é 20). Pronto! Agora, temos duas variáveis guardando o mesmo
número (20).

Inicialização de variáveis ou atributos


Muitas vezes, precisamos inicializar as variáveis ou atributos para que
possuam um valor desde o início do programa.

Como há muitos tipos de dados em Java, seus criadores desenvolveram


formas de escrita para que diferenciam os vários tipos de dados.

Primeiramente, começaremos com os mais simples: os inteiros.

Os número inteiros comuns e do tipo byte são os mais simples de se


inicializar, pois basta atribuirmos seu valor diretamente. Logicamente,
precavendo-se dos limites de alcance do tipo inteiro vistos na página de tipos de
dados. Por exemplo:

int var1 = 10;


int var2 = 500;
int var3 = 65000;
byte var1 = -100;
byte var2 = 50;

Os números inteiros longos têm duas formas de serem inicializados.


Podemos escrevê-lo diretamente se, e somente se, seu valor for menor que o
alcance de um inteiro comum. Mas se o valor atribuído for maior que o valor
permitido por um inteiro comum, então, no final deve ser acrescentado uma letra L
(maiúscula ou minúscula, não há diferença aqui). Exemplo:

long var1 = -65000;


long var2 = 3590;
long var3 = 15000000000L;
long var4 = -6740000000L;

A inicialização do tipo double e float é um pouco diferente. É possível


apenas digitar um número como sendo inteiro que o compilador entenderá
facilmente, porém, se quisermos utilizar as casas decimais, devemos utilizar um
ponto para separar a parte inteira da decimal. Outro fato ao utilizar casas decimais
é que o tipo float deve ser diferenciado do tipo double. Conseguimos fazer isso
facilmente digitando uma letra F ao final do número (não importa se a letra é
maiúscula ou minúscula). Exemplo:

double var1 = 12045741359;


float var1 = 745621;
double var2 = 10.658745965;
float var2 = 0.5f;

Char deve ser inicializado com uma letra entre aspas simples. O importante
é entender que em uma variável do tipo char só pode ser colocada uma letra, não
uma frase. Além do mais, neste caso há diferença entre maiúsculas e minúsculas.

Exemplo:
char var1 = 'a';
char var2 = 'A';

Se quisermos criar uma frase devemos guarda-la em uma string. Apesar de


String não ser um tipo de dado em Java, mas sim uma classe, este é com certeza o
elemento mais utilizado. Uma cadeia de caracteres (string) pode ser inicializada de
três formas: 1) Como uma string inexistente, ou seja, sem valor algum. Para isso
utilizamos a palavra reservada null; 2) Como uma frase vazia; 3) Como uma string
completa.

Com exceção da inexistente, toda string deve estar dentro de aspas duplas (
" " ). Se por acaso, precisarmos digitar uma aspas dentro de uma string, estas aspas
devem vir precedidas de uma barra invertida (\). Exemplo:

String var1 = null;


String var2 = "";
String var3 = "Cadeia de caracteres";
String var4 = "entre aspas: \"String em Java\".";

O tipo booleano possui apenas dois valores: verdadeiro e falso. True para
verdadeiro e False para falso. Exemplo:

boolean var1 = true;


boolean var2 = false;

Neste tipo de dado não há possibilidade de ter outro valor.


Capítulo 3
Método de Saída Padrão
Um método de saída é utilizado para mostrar alguma coisa ao usuário. No
caso de Java, existe um método padrão que utiliza uma saída padrão (monitor de
vídeo) para criar a comunicação com o usuário - estamos falando de println.

O método println faz parte da classe System que controla a maioria das
funcionalidades do computador, e se tratando de uma saída, mais especificamente
de out.

Basicamente, o método println imprime na tela uma string (cadeia de


caracteres - frase) que é passada ao método como argumento entre parênteses.

A saída padrão é exibida sempre no console e não em uma janela.

O importante é saber que o método PRINTLN sempre pulará uma linha


quando seu argumento chega ao final.

Então, procedemos da seguinte maneira: 1) A classe ao qual pertence


(System); 2) o membro que indica a saída (out); 3) o método (println); 4) O
argumento contendo a string que deve ser apresentada na tela.

O método, resumidamente, ficaria assim: System.out.println ("string")

1.public class ExemploDeSaidaPadrao {


2. public static void main(String[] args) {
3. System.out.println("Saída Padrão em Java");
4. System.out.println("Linha 1");
5. System.out.println("Linha 2");
6. System.out.println("Linha 3");
7. }
8.}

Uma outra forma de saída padrão é o print. A única diferença entre println e
print é que ao final de seu argumento ele não irá pular nenhuma linha. Dessa forma
podemos criar uma linha contínua com vários print em linhas diferentes.

1.public class ExemploDeSaidaComPrint {


2. public static void main(String[] args) {
3. System.out.print("Saída Padrão ");
4. System.out.print("usando ");
5. System.out.print("o método ");
6. System.out.print("print");
7. }
8.}

Controle de Texto
Outra possibilidade interessante nos métodos de saída são os controles de
texto. Os controles de texto são dados por caracteres chaves que são indicados com
uma barra invertida antes dele. Veja a lista abaixo:

\n - pula uma linha


\t - cria uma tabulação (o mesmo que apertar a tecla TAB)
\b - retorna o cursor um caracter
\r - retorna o cursor ao início da linha

1.public class ExemploDeControleDeTexto{


2. public static void main(String[] args) {
3. System.out.print("Site:\t"); // cria uma tabulação
4. System.out.print("tiexpert\n"); //pula uma linha
5. System.out.print("O ponto de encontro do estudante de TI\r");
6. // põe o cursor no início da linha
7. }
8.}

Apresentando valores de variáveis ou atributos


Podemos facilmente demonstrar o valor de uma variável ou atributo
bastando apenas dar como argumento a variável. O próprio método println ou
print se encarrega de converter o valor em uma string, ou seja, ele transforma o
valor número em um texto que o representa. Veja o exemplo:

01.public class ApresentandoVariaveis{


02. public static void main(String[] args) {
03. int inteiro = 200;
04. float decimal = 0.5f;
05. char letra = 'J';
06. System.out.println (inteiro);
07. System.out.println (decimal);
08. System.out.println (letra);
09. }
10.}

Também é possível exibir o resultado de uma operação matemática


(processo) executado dentro da própria saída padrão.

1.public class ApresentandoResultados{


2. public static void main(String[] args) {
3. int inteiro = 200;
4. float decimal = 0.5f;
5. System.out.println (inteiro + decimal);
6. }
7.}

Obs.: Tenha cuidado ao apresentar resultados de números junto com texto,


pois nesse caso haverá a concatenação de string, ou seja, a junção de duas ou mais
cadeias de caracteres.

Concatenação
Concatenação é o ato de unir duas ou mais cadeias de caracteres (strings).

Por muito tempo, operações envolvendo strings eram os pesadelos de


qualquer programador, pois havia a necessidade de tratar o elemento pelo seu
dado bruto, ou seja, caracter por caracter. Então, juntar por exemplo, duas frases
era um trabalho árduo.

Com o surgimentoda orientação a objeto e o advento do Java, as operações


envolvendo strings foram muito simplificadas. A melhoria mais significativa nesse
assunto, sem sombra de dúvidas, foi utilizar a concatenação de strings.

A concatenação de strings é dada pelo operador +, mas não o confunda com


o operador de adição que utiliza o mesmo símbolo.

Dessa forma, com apenas este símbolo, podemos unir duas cadeias de
caracteres diferentes em apenas uma.

Veja este exemplo, que apesar de bobo, ilustra exatamente o que acontece
na concatenação:

João + zinho = Joãozinho; Passa + tempo = Passatempo; beija + - + flor = beija-flor.

Acredite, simples desse jeito.

Colocando isso em um código ficaria:

1.public class ConcatenacaoSimples {


2. public static void main(String[] args) {
3. String palavra1 = "tele";
4. String palavra2 = "fone";
5. System.out.println(palavra1 + palavra2);
6. }
7.}

O melhor da concatenação é que não precisa ser uma palavra que faça
sentido porque o computador não verifica se faz sentido, ele simplesmente junta a
cadeia de caracteres. Portanto, poderíamos muito bem fazer isso:
01.public class ConcatenacaoComposta {
02. public static void main(String[] args) {
03. String part1 = "De";
04. String part2 = "se";
05. String part3 = "nc";
06. String part4 = "or";
07. String part5 = "aj";
08. String part6 = "ad";
09. String part7 = "o";
10. System.out.println(part1+part2+part3+part4+part5+part6+part7);
11. }
12.}

A concatenação de strings ajuda muito no momento que usamos o método


de saída padrão println, porque ao invés de utilizarmos várias vezes o mesmo
método, podemos apenas concatenar a string anterior com a string posterior, ou
seja, juntar a string de cima com a string da linha de baixo. Veja o exemplo:

1.public class ConcatenacaoComPrintln {


2. public static void main(String[] args) {
3. System.out.println("Bem vindo ao mundo Java!\n\n" +
4. "Este é um exemplo prático de concatenação de string.\n" +
5. "Aqui, a string da linha de cima é " +
6. "sempre concatenada com a string da linha de baixo" );
7. }
8.}

Cuidados ao concatenar
Apesar da concatenação ser algo bem simples de ser feito, devemos ter
alguns cuidados. Pois como podemos perceber, ele também é o símbolo utilizado
para fazer operações de adição. O que queremos dizer é que, se por exemplo,
quisermos marcar um número de telefone em uma única string e tivermos na
verdade dois números inteiros distintos, o resultado será desastroso. Veja:

Telefone: 998 + 1234, resultaria em Telefone: 2232. Acabamos de perder o


número de telefone. Então, o mais sensato é se lembrar que concatenação só
ocorre entre uma string e outro dado (não necessariamente precisa ser uma string
também).

Então, para conseguirmos juntar os dois números acima, pelo menos um


deles deve ser uma string.

Telefone: "998" + 1234, ou Telefone: 998 + "1234".

Esse pensamento se torna mais complicado a medida que temos que


concatenar uma operação no meio da string. Exemplo:
"CCXXVI em algarismos romanos são " + 200 + 20 + 6. Aqui, ao invés de
representar a soma de 200 + 20 + 6, que seria 226, é representada a total
concatenação de todos os elementos. O que resultaria em "CCXXVI em algarismos
romanos são 200206".

Mas este problema é fácil de resolver, basta indicarmos com os parênteses


que a operação matemática deve ser executada primeiro. Representando ficaria:

"CCXXVI em algarismos romanos são " + (200 + 20 + 6). O que consequentemente,


representaria "CCXXVI em algarismos romanos são 226".
Capítulo 4
Estruturas de controle
Estrutura seletiva - IF e ELSE
Uma ação muito importante que o processador de qualquer computador
executa, e que o torna diferente de qualquer outra máquina, é a tomada de decisão
definindo o que é verdadeiro e o que é falso.

Se quisermos fazer um bom programa, esse programa deve ser capaz de


definir caminhos diferentes de acordo com decisões que o próprio programa toma.
Para isso, precisamos de uma estrutura seletiva da qual o único valor possível é o
bit 1 ou 0, resumindo: retornar o valor VERDADEIRO ou FALSO.

Em Java, como em muitas linguagens de programação, quem faz isso é o IF


(SE traduzindo).

O ELSE é o que chamamos de caso contrário, ou seja, se for falso execute o


que está no ELSE.

Exemplificando: Se (IF) for tal coisa, faça isso! Caso contrário (ELSE), faça
aquilo!

Usando IF
Para usar o IF basta digitar entre parênteses o que deve ser comparado.

IMPORTANTE: IF é uma palavra reservada que não aceita ponto-e-vírgula


(;) no final.

Se for verdadeiro, o programa executará a primeira linha logo abaixo do if.

Mas, e se quisermos executar várias linhas se if for verdadeiro?

Se o if tiver que executar várias linhas, todas as linhas que devem ser
enquadradas dentro do bloco de dados - as chaves ({}).

Usando ELSE
O ELSE só existe se tiver um IF. O else só será executado se o IF for falso.

Else executará só a primeira linha abaixo dele. Se o else tiver que executar
várias linhas, vale a mesma regra de if. Todas as linhas a ser executadas deverão
estar contidas dentro do bloco de dados ({}).
Para que IF chegue a uma decisão de falso e verdadeiro são necessários
operadores lógicos. Dos quais destacam-se 6:

> - maior que


< - menor que
>= - maior ou igual a
<= - menor ou igula a
== - igual a
!= - diferente de

Importante
O operador lógico ! (negação) server para inverter o valor, ou seja, se algo
for falso, irá se tornar verdadeiro e vice-e-versa.

Uma construção sem comparação entre duas variáveis é sempre entendida


como sendo verdadeira. Ex.: if (var1) -> entenda como: se var1 for verdadeiro.

Uma construção sem comparação entre duas variáveis será entendida como
false se usarmos o operador de negação antes da variável. Ex.: if (!var1) -> entenda
como: se var1 for falso.

01.public class UsandoIf {


02. public static void main(String args[]) {
03. boolean var1 = true;
04. // Se var1 for verdadeiro
05. if (var1) {
06. System.out.println("var1: Verdadeiro");
07. } else {
08. System.out.println("var1: Falso");
09. }
10. // Se var1 for falso
11. if (!var1) {
12. System.out.println("!var1: Verdadeiro");
13. } else {
14. System.out.println("!var1: Falso");
15. }
16. }
17.}

WHILE
While é uma estrutura de repetição.

While executa uma comparação com a variável. Se a comparação for


verdadeira, ele executa o bloco de instruções ( { } ) ou apenas a próxima linha de
código logo abaixo.
Procedemos da seguinte maneira:

WHILE (comparação)

O problema com estruturas de repetição, principalmente com while, é o que


chamamos de looping infinito. Damos esse nome ao fato de que o programa fica
repetindo a mesma sequência de códigos esperando por um resultado que nunca
irá acontecer.

Portanto, é imprescindível que uma determinada variável seja modificada


de acordo com cada loop. Veja o exemplo

01.public class ExemploWhile {


02. public static void main(String args[]) {
03. int contador = 0;
04. while (contador < 50) {
05. System.out.println("Repetição nr: " + contador);
06. contador++;
07. }
08. }
09.}

Como podemos ver, existe a variável contador que é iniciada valendo 0, a


cada loop executado (repetição) é somado 1 ao contador. Perceba que o while irá
manter a repetição enquanto a variável contador for menor que 50.

Outro ponto importante é que a variável contador é inicializada antes de


chegar ao while, porque o while irá comparar a sentença e só depois permitirá a
execução do bloco. Se quisermos fazer todo o bloco primeiro e só depois fazer a
comparação, devemos utilizar o comando DO WHILE

DO WHILE
DO WHILE é uma estrutura de repetição, tal como o próprio while. A
principal diferença entre os dois é que DO WHILE irá fazer a comparação apenas
no final do bloco de código, sendo representado da seguinte forma:

DO { código } WHILE (comparação);

Neste caso, devemos ter as mesmas precauções quanto while, no que diz
respeito a looping infinito. Mas não é necessário inicializar a variável antes do
bloco de código como acontece com while, pois a comparação só será feita após
todo o código ter sido executado.

FOR
FOR é uma estrutura de repetição que exerce a mesma função que WHILE e
DO WHILE.
A principal diferença entre eles é a sintaxe e também a forma de trabalhar.

O FOR necessita de três parâmetros: a inicialização da variável, a condição


que irá manter o looping (repetição) e o modificador da variável inicializada que
pode ser incrementada ou decrementada, ou seja, pode aumentar seu valor ou
diminuir. Um ponto importante é que todos os parâmetros devem ser separados
por ponto-e-vírgula ( ; ).

Dessa forma, temos resumidamente a seguinte construção: FOR


(inicialização ; condição ; incremento ou decremento).

Por exemplo, vamos criar um código que nos dá o resultado do fatorial de 5.


Como sabemos para calcular o fatorial de algum número basta multiplicarmos ele
pelo número anterior regressivamente até 1, ou seja, seria algo como 5 × 4 × 3 × 2
× 1. Dessa forma, sabemos exatamente em quanto devemos começar nossa conta
(5), sabemos por quanto tempo o looping irá continuar executando (enquanto a
variável for maior que 1) e sabemos quanto devemos modificar essa variável (para
cada repetição irá subtrair - decrementar - 1).

Em um código ficaria:

public class Fatorial {


public static void main (String args[]){
int fator, resultado=1;
for (fator=5; fator>1; fator--)
resultado*=fator;
System.out.println(resultado);
}
}

Observemos apenas um detalhe, como toda variável é automaticamente


inicializada como nulo (NULL), então, necessitamos inicializar a variável resultado
em 1, porque seria impossível multiplicar a variável resultado pela variável fator
(ex.: NULL × 5 = ?).

Switch, Case e Default


Uma estrutura muito utilizada em programação é o switch. A estrutura
switch verifica uma variável e age de acordo com seus cases. Os cases são as
possibilidades de resultados que são obtidos por switch.

Basicamente, o switch serve para controlar várias ações diferentes de


acordo com o case definido dentro dele.

A estrutura do Switch é:

SWITCH (variável) {
CASE valor :
Código a ser executado caso o valor de case seja o mesmo da variável de switch
}

Então, detalhadamente, switch recebe uma variável e abre um bloco de


dados ( { } ), dentro desse bloco de dados há os cases. Cada case recebe um valor
único, ou seja, que não pode ser repetido no mesmo bloco de dados. Então,
marcamos cada case com dois pontos ( : ). Após os dois pontos colocamos todo
código que deverá ser executado que pode conter quantas linhas nós quisermos.

Dica importante: É um bom costume sempre terminar um código após o


case com um comando break. Assim, nós evitamos que o resto do código seja
executado por acidente. E vale também ressaltar que case não gera resultados
booleanos, portanto, não há a possibilidade de fazer comparações (Ex. Isso está
totalmente errado-> case var1 > var2:).

Default
Como switch pode receber várias possibilidades, pode ocorrer de algum
caso estar fora do alcance ou não definido. Nesse momento, default faz seu papel.
Default pega qualquer resultado que não esteja definido no case. Ou seja, ele é o
bloco de código padrão que deve ser executado quando nenhum case for satisfeito.
Podemos colocá-lo onde quisermos dentro de switch, mas, geralmente, o
colocamos no final.

Para exemplificar, vamos ver o código abaixo.

01.public class ExemploSwitch {


02. public static void main(String args[]) {
03. int diaDaSemana = 1;
04. switch (diaDaSemana) {
05. case 1:
06. System.out.println("Domingo");
07. break;
08. case 2:
09. System.out.println("Segunda-feira");
10. break;
11. case 3:
12. System.out.println("Terça-feira");
13. break;
14. case 4:
15. System.out.println("Quarta-feira");
16. break;
17. case 5:
18. System.out.println("Quinta-feira");
19. break;
20. case 6:
21. System.out.println("Sexta-feira");
22. break;
23. case 7:
24. System.out.println("Sábado");
25. break;
26. default:
27. System.out.println("Este não é um dia válido!");
28. }
29. }
30.}

Como podemos perceber, existe uma variável inteira chamada


diaDaSemana. Essa variável é passada ao switch e dentro desse switch há 7 cases
que correspondem aos dias da semana. Como o valor inicial é 1, então, o bloco logo
abaixo de case 1 é executado, ou seja, ele imprimirá Domingo no monitor. Para
evitar que o código dos outros cases sejam executados, logo após o método println
há um comando BREAK;

Se quiser, baixe este código e modifique o valor inicial de diaDaSemana para


verificar os possíveis resultados e como este algoritmo funciona.

Break e Continue
Break e Continue são dois comandos de controle de estruturas largamente
utilizados em loops (repetições) como for e while.

Break
O comando break serve para determinar uma quebra de estrutura, ou seja,
ele faz com que, por exemplo, um loop (repetição) pare. No comando switch, por
exemplo, ele determina que não pode ser executado o case seguinte, e assim por
diante.

No exemplo abaixo, temos uma repetição que se inicia em 1 e deve terminar


em mil (1.000), mas dentro desta estrutura há uma condição: se a variável for igual
a 10 saia da estrutura de repetição. Vejamos:

01.public class ExemploBreak {


02. public static void main (String args []){
03. for (int contador=1; contador<=1000; contador++){
04. System.out.println("Esta é a repetição nr: "+contador);
05. if (contador==10)
06. break;
07. }
08. }
09.}

Como podemos observar, mesmo a estrutura de repetição for


determinando que a repetição deve ir até 1000, ao executarmos esse código,
apenas conseguimos chegar até a repetição número 10. Isso ocorre porque quando
if for verdadeiro ele executa o break. Dessa forma, conseguimos sair do loop sem
ele ter terminado.

Continue
Continue também é muito utilizado em estruturas e repetição e sua função
é ignorar o código, e não sair como acontece com o break.

Exemplificando, faremos um código contendo uma estrutura de repetição


que irá contar de 1 a 100, mas sempre que o número não for múltiplo de 5 o código
para apresentar o número na tela será ignorado e a repetição continuará com o
número seguinte.

01.public class ExemploContinue {


02. public static void main (String args []){
03. for (int contador=1; contador<=100; contador++){
04. if (contador%5!=0)
05. continue;
06. /* Se o contador não for múltiplo de 5
07. * Todo o código abaixo será ignorado
08. * e o loop continua com o próximo nr */
09. System.out.println("Contador: "+contador);
10. }
11. }
12.}

Ou seja, desta forma, apenas os múltiplos de 5 entre 1 e 100 aparecem na


tela.
Capítulo F
Arrays
Arrays, também muito conhecidos como vetores, são variáveis que servem
para guardar vários valores do mesmo tipo de forma uniforme na memória. Por
exemplo, se tivemos que criar 20 variáveis do mesmo tipo que querem dizer a
mesma coisa, nós não criaríamos -> int var1, var2, var3, var4, var5, ... ao invés
disso, criaríamos apenas uma variável de array para guardar todos os 20 números
de uma vez.

Como um array pode guardar vários valores temos que definir quantos
valores ele deve guardar para que seja reservado o espaço necessário em memória.

Primeiramente, vamos aprender como declarar um array. Para declarar um


array devemos especificar a classe ou o tipo de dado que será armazenado nele.
Após isso, damos um nome a esse array. E, para finalizar, indicamos que ele é um
array, simplesmente abrindo e fechando colchetes ( [ ] ). Portanto, se quiséssemos
um array de números inteiros chamado meu array, declararíamos da seguinte
forma:

int meuArray [];

Agora que já declaramos o array, devemos dar um tamanho a ele, para que
seja reservado espaço suficiente em memória. Para fazermos isso, utilizaremos um
instanciador chamado new.

New é muito importante, pois ele irá criar de fato o array.

Para indicarmos o tamanho usamos o instanciador new, depois o tipo de


dado do array e entre colchetes o tamanho do array. Tomando o exemplo acima,
vamos indicar que meuArray terá o tamanho 4. Então, a linha de cima ficaria:

int meuArray[] = new int [4];

Na memória é representado da seguinte forma:

Uma única variável com 4 espaços nos quais podem ser guardados números
inteiros.
Acessando uma posição no Array
Agora, para acessarmos um local específico dessa memória devemos indicar
entre colchetes a posição desejada no array que chamamos de index. O importante
mesmo é saber que não importa o tamanho do array, o index (número que indica a
posição) sempre começa em 0. Ou seja, um array de tamanho 20 vai da posição 0 a
19, um array de tamanho 180 vai da posição 0 a 179. Portanto, um array de
tamanho 4 vai da posição 0 a 3.

Agora, se quisermos atribuir os valores 540 na posição 1 e 8456 na posição


3, faríamos: meuArray [1]=540; meuArray [3]=8456.

Não podemos nunca nos esquecer que o limite do array é sempre seu
tamanho menos 1. Usando o exemplo: array de tamanho 4, posição máxima é 3
(pois 4-1=3). Então, se atribuirmos um valor a posição 4 ocorrerá um erro.
Resumidamente, jamais poderíamos fazer meuArray [4]=200.

Inicialização direta de Array


Podemos inicializar um array diretamente, sem a necessidade de instanciá-
lo com new. Para isso, após a declaração do array, basta colocar seus valores em
chaves, separando cada valor por vírgula. Por exemplo, se quiséssemos inicializar o
meuArray com os valores 450, 200, 1000, 700, faríamos:
int meuArray [] = { 450, 200, 1000, 700 };

Matrizes
Matrizes são arrays multidimensionais, ou seja, eles não são totalmente
lineares, e sim, geométricos.

Enquanto um array tem apenas uma linha com vários valores, uma matriz
pode, por exemplo, tem várias linhas com vários valores, que comumente
chamamos de linhas e colunas.

Para criarmos um array multidimensional (ou matriz), procedemos da


mesma forma que um array normal, porém com mais um dimensionador (os
colchetes). Então, se quisermos criar um array (matriz) bidimensional com 3 linha
e 5 colunas, faríamos:

int minhaMatriz [][] = new int [3][5];

Na memória é representado como:

Isso também pode ser feito para adquirirmos o formato de matriz que
quisermos. Ou seja, se fosse uma matriz tridimensional, bastaria ter três
dimensionadores, se fosse 4D, então, 4 dimensionadores, se fosse 5D (apesar de
geometricamente difícil de imaginar) seriam 5 dimensionadores. E assim por
diante...

Entendendo Static
Sempre que programamos devemos levar em conta como nosso próprio
programa irá acessar os dados que ele mesmo produz. Isso é o simples
entendimento e visualização da diferença entre o que é local e o que é global.

Local é qualquer tipo de dado que só pode ser acessado em seu próprio
contexto. Por exemplo, uma variável dentro da função principal (main) só pode ser
acessada pela função main.

Global é qualquer tipo de dado que pode ser acessado diretamente de


qualquer contexto dentro da classe inteira. Por exemplo, podemos declarar uma
variável como sendo da classe e criarmos também outras três funções que podem
acessar essa mesma variável diretamente, pois ela é global e não pertence a
nenhuma das três funções especificamente.
Portanto, sempre usamos a palavra reservada static para indicar que algo
(função, método, variável, etc.) é global e pode ser acessado diretamente por todos
os elementos de uma classe.

Para exemplificar de uma maneira bem simples e direta, no código abaixo


há três variáveis: duas declaradas no corpo da classe e uma declarada na função
main.

01.public class GlobalELocal {


02. static int x;
03. float y;
04.
05. public static void main(String args[]) {
06. char z;
07. x = 1;
08. z = 'a';
09. }
10.}

Traduzindo o código acima, a regra é a seguinte:

• Quando o código é executado, a função main é chamada;


• Dentro da função main podemos atribuir um valor para x, porque x é um
inteiro marcado como global (static) e pode ser acessado de qualquer lugar.
• y não pode ser modificado dentro da função main, pois ele só pertence a
classe GlobalELocal.
• z só pode ser modificado dentro da função main, e não pode ser modificado
na classe GlobalELocal.
Capítulo 6
Funções
Funções são rotinas ou sub-rotinas automatizadas. Sempre que
pretendemos usar a mesma codificação para algo específico, criamos uma função.
Dessa forma, sempre que quisermos utilizar aquela codificação, ao invés de nós a
digitarmos inteira novamente, simplesmente chamamos a função. Funções são
extremamente úteis e adaptáveis, e o conceito de funções é importante para mais a
frente entendermos o funcionamento e criação dos métodos.

Criando funções sem argumentos


Para criar uma função, temos que ter sempre em mente que toda função é
global, ou seja, é estática (static).

As funções mais básicas são aquelas que apenas executam uma rotina,
portanto, não recebem nenhum argumento. No código, digitaríamos dentro da
classe, mas fora da função main o seguinte:

public static void nomeDaFunção () { código da função }

Static porque pode ser acessado globalmente; void porque não retorna
nenhum valor; mesmo não tendo argumentos, é necessário ter parênteses.

Vamos ver o exemplo:

01.public class ExemploFuncao {


02. //criando a função
03. public static void mostrarMensagem() {
04. System.out.println("Minha Mensagem");
05. }
06.
07. public static void main(String[] args) {
08. //chamando a função dentro do programa
09. mostrarMensagem();
10. }
11.}

O código acima funciona da seguinte maneira:

Primeiro é criada a função mostrarMensagem(), que em seu corpo tem


apenas um println com uma mensagem. Depois iniciamos nosso programa com o
main. Dentro do main chamamos a função. Para isso, basta colocar o nome da
função. Quando a função é chamada, o código dentro do corpo da função é
executado. Concluindo, o programa acima apenas mostra na tela a mensagem
Minha Mensagem.
Funções com argumentos
Funções com argumentos funcionam e são criadas da mesma forma que
uma função sem argumento, porém com uma diferença.

A diferença está que haverá informações necessárias para que a função


processe, e essas informações serão descritas dentro dos parênteses.

Uma função pode ter um ou vários argumentos desde que separados por
vírgula (,). Cada argumento deve ter seu tipo de dado declarado. Então, todos os
exemplos abaixo são funções válidas:

public static void funcao1 (String arg1){}


public static void funcao2 (int arg1, int arg2){}
public static void funcao3 (String arg1, char arg2, int arg3, float arg4, Object arg5)
{}

Para demonstrar este tipo de função criaremos uma função que mostra na
tela o resultado fatorial de um número. Além disso, colocaremos esta função
dentro de um loop que irá de 1 a 10 para ele mostrar cada um desses fatoriais.

01.public class FatorialComFuncao {


02. public static void fatorar(int numero) {
03. int fator = 1;
04. for (int i = numero; i > 1; i--) {
05. fator *= i;
06. }
07. System.out.println(numero + "! = " + fator);
08.}
09.
10. public static void main(String args[]) {
11. for (int x=1; x<=10; x++)
12. fatorar (x);
13. }
14.}

Simplificando, x que está sendo passado pelo main para fatorar() será o
valor int numero da função fatorar.

Funções que retornam valores


Aqui veremos a grande vantagem de se criar uma função. Funções podem
retornar valores de um processo executado dentro delas e esse valor pode ser
guardado dentro de uma variável no programa. Isso com certeza deixa nosso
código mais simples, pois podemos destacar processos repetitivos e guardar em
uma variável apenas o resultado daquele processo.
Para criar uma função que retorna valores temos que nos ater ao fato
retorno. Como todas as outras funções não retornavam valores, então, seu retorno
era vazio - void. Agora, temos que declarar que tipo de retorno virá da função.

O retorno é dado pelo comando return, que finaliza a função e mostra o


retorno. A variável ou valor que utilizarmos para return será o tipo de retorno da
função.

Vamos imaginar que três funções, sendo que a primeira irá retornar um inteiro, a
segunda um double e a terceira uma string. Então, as criaríamos da seguinte
maneira:

public static int funcaoDeInteiro (){}


public static double funcaoDeDouble (){}
public static String funcaoDeString (){}

No exemplo abaixo, nós criaremos uma função que irá retornar um valor
booleano (verdadeiro ou falso). Usando este retorno, determinaremos o que fazer
dentro de uma estrutura seletiva (if).

01.public class Primo {


02. public static boolean ehPrimo(long nr) {
03. if (nr < 2)
04. return false;
05. for (long i = 2; i <= (nr / 2); i++) {
06. if (nr % i == 0)
07. return false;
08. }
09. return true;
10. }
11.
12. public static void main(String[] args) {
13. long x = 5;
14. if (ehPrimo(x)) // se for primo
15. System.out.println(x + " é primo");
16. else // se não for primo
17. System.out.println(x + " não é primo");
18. }
19.}
Capítulo 7
Criação de Classe
Começaremos agora a ver a alma da programação Java que é a orientação a
objeto.

Sempre que programamos em Java, devemos pensar em como montar as


definições de nosso objeto. Ou seja, quais atributos uma classe deve conter,
simplificando, quais características tem tal objeto.

É como pensar em alguma coisa. Por exemplo, se pensarmos em relógio, a


primeira coisa que nós vem a cabeça é hora, minuto, segundo e assim por diante.
Nós também podemos ajustar as horas, ajustar o alarme, etc.

A princípio, vamos nos ater aos detalhes técnicos da programação de uma


classe.

Para criar uma classe usamos a palavra chave class, e após a definição do
nome de nossa classe, nós definimos seus atributos. Para exemplificar, criaremos
uma classe que terá as características mais simples de uma televisão.

1.class TV{
2. int tamanho;
3. int canal;
4. boolean ligada;
5.}

Pronto, esses são os atributos de uma classe, ou seja, nós definimos que
existe um objeto chamado TV e que ele tem três características: uma dessas
características é o tamanho, outra é um valor inteiro identificado por canal e mais
outra característica que determina se ele está ligado ou não.

Como podemos perceber, isso é mais um conceito (paradigma) de como


devemos pensar. Uma classe (ou objeto) pode ser muito implementado, tornando-
se um objeto com várias características que pode ser facilmente manipulado e
incorporado por outros objetos. Isso é o que chamamos de reutilização de código,
que envolve vários aspectos importantes da orientação a objeto como herança,
interface, enumeradores, sobrecarga de métodos entre outros que nós
estudaremos nas próximas páginas.

Método Construtor
Vimos anteriormente que é simples criar uma classe. Mas, para realmente
conseguirmos utilizar a classe, ela deve conter pelo menos um método construtor.
O método construtor é desenvolvido da mesma forma que uma função, a
única diferença é que ele tem o mesmo nome da classe.

Isso se deve ao fato de que um objeto deve ser construído cada vez que
chamamos a classe. E a responsabilidade de fazer isso é do construtor. Isso parte
do princípio que podemos ter dois objetos com a mesma característica, mas que
não são os mesmos objetos.

Ou seja, nós podemos ter uma TV de 29" ligada no canal 15 e nosso amigo
tem uma outra TV que também é de 29" e está ligada no canal 15. Perceba que
ambas as TVs têm as mesmas características, mas continuam sendo duas TVs
diferentes.

Sempre que criamos uma classe, Java automaticamente vincula um método


construtor padrão interno com o mesmo nome da classe, mas sem inicializar
nenhum atributo.

Para demonstrar um método construtor, criaremos um construtor padrão


sem argumentos no qual já contém os valores dos atributos definidos por nós
mesmos.

Então, vamos imaginar que sempre que uma TV é construída, o seu padrão é
tamanho 21", desligada e no canal 0. Então, podemos definí-lo como:

01.class TV {
02. int tamanho;
03. int canal;
04. boolean ligada;
05.
06. TV(){
07. tamanho=21;
08. canal=0;
09. ligada=false;
10. }
11.}

Pronto! Com isso, nós já somos capazes de instanciar nossa classe.

Instanciar Objetos
Objetos são estruturas de dados definidas e agrupas dentro de uma classe.
Sempre que utilizamos um objeto ou classe devemos reservar espaço em memória
para que aquele objeto seja manipulado sem maiores problemas.

Além do mais, também podemos utilizar a mesma classe (com todos os seus
métodos e atributos) para manipular outros objetos que serão tratados de forma
diferente (mesmo se tiverem as mesmas características do objeto anterior), pois
serão dois endereços de memória diferentes.
A vantagem de Java é nos possibilitar uma instanciação rápida e simples,
sem termos que nos preocupar com referência a endereços e alocação dinâmica de
memória, pois quem trata de manipular a memória é o próprio Java. Sem contar
que, se um objeto não é mais referenciado dentro do programa, o próprio Java
trata de liberar os recursos de memória consumidos pelo objeto usando o Garbage
Colletor - Coletor de Lixo.

Quem faz o papel de instanciador em Java é o new. New trata de reservar


memória o suficiente para o objeto e criar automaticamente uma referência a ele.
Para new conseguir determinar o objeto, precisamos usar o método construtor que
será usado como base para instanciar a classe e gerar o objeto.

Tecnicamente, declaramos uma variável qualquer como sendo do tipo da


classe (ex.: TV minhaTV; ), depois instanciamos o objeto atribuindo a variável o
resultado obtido por new mais o método construtor (ex.: minhaTV = new TV(); ).

Apesar de parecer muitos detalhes, isso fica mais facilmente visualizado no


código abaixo.

01.public class TV {
02. int tamanho;
03. int canal;
04. boolean ligada;
05.
06. TV() {
07. tamanho = 21;
08. canal = 0;
09. ligada = false;
10. }
11.
12. public static void main(String[] args) {
13. TV objeto1 = new TV();
14. TV objeto2;
15. objeto2 = new TV();
16. }
17.}

No código acima, criamos uma classe chamada TV com os mesmos atributos


do exemplo da página Criação de Classes, e criamos um método construtor que
inicializa os atributos da classe TV com alguns valores.

Declaramos duas variáveis chamadas objeto1 e objeto2 sendo do tipo TV.


Depois, instanciamos o objeto usando new e o método construtor.

This
This é usado para fazer auto-referência ao próprio contexto em que se
encontra. Resumidamente, this sempre será a própria classe ou o objeto já
instanciado.

Esse conceito de auto-referência é importante para que possamos criar


métodos construtores sobrecarregados e métodos acessores mais facilmente.

Por base, se criarmos um método que receba um argumento chamado


ligado que queremos atribuir para o atributo da classe, que também se chama
ligado, devemos diferenciar ambos mostrando a quem cada um pertence. Como
this se refere ao contexto empregado, então o usamos para identificar que ligado
será o atributo da classe e ligado sem o this se refere ao parâmetro do método. O
que resultaria nisto:

01.public class TV {
02. //atributos
03. int tamanho;
04. int canal;
05. boolean ligada;
06.
07. // método contrutor com parâmetro
08. TV(boolean ligada) {
09. this.ligada = ligada;
10. /**
11. * Onde this.ligada é o atributo
12. * e ligada é o valor do parâmetro
13. */
14. }
15.}

Traduzindo, this.ligada seria: a variável ligada desta classe recebe o valor de


ligada, ou seja, o único ligada que existe fora o atributo é o parâmetro.

Sobrecarga de métodos
Java nos permite criar vários métodos com o mesmo nome desde que tenham
parâmetros diferentes. Isso é o que chamamos de sobrecarga de métodos.

A sobrecarga de métodos consiste em criarmos o mesmo método com


possibilidades de entradas diferentes. Essas entradas, caracterizadas como parâmetros,
devem sempre ser de tipos diferentes, quantidades de parâmetros diferentes ou posições
dos tipos diferentes.

Para visualizarmos um cenário, vejamos a classe abaixo:

1.public TV {
2. int canal;
3. int volume;
4. boolean ligada;
5. int tamanho;
6.}

Agora, criaremos o método ligar. O método ligar, simplesmente, muda o


valor dos atributos canal e volume para 3 e 25, respectivamente.

1.void ligar (){


2. canal = 3;
3. volume = 25;
4. ligada = true;
5.}

Agora, vamos personalizar este método para que ele mude o atributo ligada
de acordo com o parâmetro.

1.void ligar (boolean ligada){


2. canal = 3;
3. volume = 25;
4. this.ligada = ligada;
5.}

Poderíamos utilizar ambos os métodos na mesma classe se quisermos,


porque um possui argumentos e o outro não.

01.void ligar (){


02. canal = 3;
03. volume = 25;
04. ligada = true;
05.}
06.
07.void ligar (boolean ligada){
08. canal = 3;
09. volume = 25;
10. this.ligada = ligada;
11.}

Porém, o mesmo não pode ser aplicado aos atributos canal e volume.
Porque não é possível criar um método que recebe um inteiro e criar um outro
método com o mesmo nome que também recebe um inteiro, mesmo que estes dois
inteiros sejam totalmente diferentes. Se visualizarmos como Java interpreta o
método, veríamos:

void ligar (int volume) = void ligar (int canal)


void ligar (int) = void ligar (int)

Por outro lado, é perfeitamente possível criarmos dois métodos que


recebam um booleano e um inteiro, inclusive se forem os mesmos, mas em
posições diferentes. Isso acontece porque Java não verifica o nome do parâmetro,
mas apenas o tipo dele.

void ligar (boolean ligada, int canal) l void ligar (int canal, boolean ligada)
void ligar (boolean, int) l void ligar (int, boolean)

Portanto, podemos fazer muitas combinações desde que essas combinações


não sejam em números iguais, de tipos iguais e nas mesmas posições.

Abaixo, está a classe com algumas combinações possíveis. É um bom


costume sempre referenciar para o método que recebe mais argumentos.

01.public class TV {
02. int canal;
03. int volume;
04. boolean ligada;
05. int tamanho;
06.
07. void ligar() {
08. this.ligar(3, 25, true);
09. }
10.
11. void ligar(boolean ligada) {
12. this.ligar(3, 25, ligada);
13. }
14.
15. void ligar(int canal, int volume) {
16. this.ligar(canal, volume, true);
17. }
18.
19. void ligar(int canal, int volume, boolean ligada) {
20. this.canal = canal;
21. this.volume = volume;
22. this.ligada = ligada;
23. }
24.}

Acesso a Atributos e Métodos


Vimos, até agora, como criar uma classe, definir um método construtor,
sobrecarregar métodos e instânciar objetos. Nesse momento, vamos ver como
acessar seus membros e métodos.

Os acessos a membros ou métodos de uma classe são dados a partir do


objeto instanciado usando um separador que é o ponto (.).

Portanto, para acessar qualquer membro da classe, basta que usemos o


nome do objeto, mais um ponto e o nome do membro que queremos acessar.
Ainda tomando como exemplo a classe TV já vista antes, vamos modificar
dentro do programa dois atributos: os atributos canal e volume.

01.public class TV {
02. int canal;
03. int volume;
04. boolean ligada;
05. int tamanho;
06.
07. public TV(){
08. this.tamanho = 21;
09. this.ligada = true;
10. }
11.
12. public static void main (String args []){
13. TV minhaTV = new TV();
14. minhaTV.canal = 3;
15. minhaTV.volume = 25;
16. }
17.}

Como percebemos é construído um objeto chamado minhaTV da classe TV


com o tamanho de 21" e já ligada. Durante a execução do programa modificamos
diretamente seu canal e volume usando o objeto que instanciamos.

Da mesma forma que acessamos um atributo, também podemos acessar um


método. No exemplo abaixo, criaremos o método para aumentar volume da TV.

01.public class TV {
02. int canal;
03. int volume;
04. boolean ligada;
05. int tamanho;
06.
07. public TV(){
08. this.tamanho = 21;
09. this.ligada = true;
10. this.canal = 3;
11. this.volume = 25;
12. }
13.
14. public void aumentarVolume(){
15. this.volume += 5;
16. }
17.
18. public static void main (String args []){
19. TV minhaTV = new TV();
20. minhaTV.aumentarVolume();
21. }
22.}

Aqui, o objeto minhaTV começa com volume 25 e depois de chamar seu


método aumentarVolume() fica com 30.

Algumas considerações que devemos ter é saber diferenciar funções de


métodos. Apesar da essência de ambos ser a mesma coisa, funções são chamadas
estaticamente, ou seja, ela pode ser chamada diretamente sem o intermédio de
nenhum objeto. Já os métodos são chamados de dentro das classes, portanto,
obrigatoriamente devemos ter um objeto instanciado para conseguirmos utilizar o
método. Vejamos a diferença:

01.public class TV {
02. int canal;
03. int volume;
04. boolean ligada;
05. int tamanho;
06.
07. public TV(){
08. this.tamanho = 21;
09. this.ligada = false;
10. this.canal = 0;
11. this.volume = 0;
12. }
13.
14. // método da classe
15. public void ligar(boolean ligada){
16. this.ligada = ligada;
17. }
18.
19. // função
20. public static void estahLigada (TV objeto){
21. if (objeto.ligada)
22. System.out.println ("está ligada");
23. else
24. System.out.println ("não está ligada");
25. }
26.
27. public static void main (String args []){
28. TV televisao1 = new TV();
29. TV televisao2 = new TV();
30. // chamando o método ligar
31. televisao1.ligar(true);
32. televisao2.ligar(false);
33. System.out.print ("A televisão 1 ");
34. // chamando a função estahLigada
35. estahLigada (televisao1);
36. System.out.print ("A televisão 2 ");
37. estahLigada (televisao2);
38. }
39.}

Observemos que chamamos o método ligar() de cada objeto, portanto,


existem dois métodos ligar distintos - o método ligar() da televisao1 e o método
ligar() da televisao2. A função é estática, portanto, existe apenas uma função
estahLigada().
Capítulo 8
Pacotes
Usamos pacotes para organizar as classes semelhantes. Pacotes, a grosso
modo, são apenas pastas ou diretórios do sistema operacional onde ficam
armazenados os arquivos fonte de Java e são essenciais para o conceito de
encapsulamento, no qual são dados níveis de acesso as classes.

Java posssui um pacote padrão que é utilizado quando programamos,


mesmo embora não seja recomendado pela Sun usá-lo.

Criar Pacotes
Muitos compiladores criam automaticamente os pacotes como uma forma
eficaz de organização, mas a criação de pacote pode ser feita diretamente no
sistema operacional. Basta que criemos uma pasta e lhe demos um nome. Após
isso, devemos gravar todos os arquivos fonte de java dentro desta pasta.

Definir Pacotes
Agora que já possuímos a pasta que será nosso pacote, devemos definir em
nossa classe a qual pacote ela pertence. Isso é feito pela palavra reservada package.

Package deve ser a primeira linha de comando a ser compilada de nossa


classe.

Portanto, se tivéssemos criado uma pasta chamada tiexpert e fossemos criar


uma classe nesta pasta (pacote), o começo de nosso código seria: package tiexpert;.

Importar Pacotes
Java possui vários pacotes com outros pacotes internos e várias classes já
prontas para serem utilizadas.

Dentre os pacotes Java podemos determinar dois grandes pacotes: o pacote


java, que possui as classes padrões para o funcionamento do algorítmo; e o pacote
javax, que possui pacotes de extensão que fornecem classes e objetos que
implementam ainda mais o pacote java.

Exemplo: o pacote AWT (Abstract Windowing Toolkit) possui as classes


necessárias para se criar um ambiente gráfico API (Janelas) e está fortemente
ligado as funções nativas do Sistema Operacional, ou seja, ele pertence ao pacote
java. Mas, o pacote SWING não é ligado fortemente as funções nativas do Sistema
Operacional, mas as funções do AWT, ou seja, SWING complementa o AWT,
portanto SWING faz parte do pacote de extensão javax.

Para utilizar as milhares de classes contidas nos inúmeros pacotes de Java


devemos ou nos referenciar diretamente a classe ou importá-la.

Para importar um pacote usamos o comando import.

Para separar um pacote de seu sub-pacote usamos um ponto (como no


acesso a membros de classe).

Ao importarmos um pacote podemos utilizar um coringa, o asterísco (*). O


asterísco serve para importar todos os sub-pacotes e classes do pacote que está
definido.

Ex.: import java.awt.*;. Isso importará todos os sub-pacotes pertencentes ao


pacote AWT.

Ou podemos definir diretamente qual pacote desejamos.

Ex.: import javax.swing.JOptionPane;. Isso irá importar apenas o sub-pacote


JOptionPane do pacote SWING.

A diferença entre as duas formas de importação de pacotes é o consumo de


recursos do computador. Como o asterísco importa todos os sub-pacotes, o
consumo de memória será alto e, muito provavelmente, não usaremos todas as
classes de todos os pacotes importados. Por isso, o recomendado é sempre
importar apenas o pacote que será utilizado.

Para consolidar o que foi visto até aqui, o código abaixo ilustra o uso de
pacotes.

01.package tiexpert;
02.
03.import javax.swing.JOptionPane;
04.
05.public class Mensagem {
06. public static void main (String args[]){
07. JOptionPane.showMessageDialog(null,
08. "Bem vindo ao mundo de Java!");
09. }
10.}

A classe acima está no pacote tiexpert. No nosso programa estamos


utilizando o método showMessageDialog que pertence à classe JOptionPane que
está no pacote de extensão SWING que tivemos que importar.
Capítulo 9
Encapsulamento
Se outros programadores usam nossa classe, nós queremos garantir que
erros pelo mau uso não ocorram. Encapsulamento serve para controlar o acesso
aos atributos e métodos de uma classe.

É uma forma eficiente de proteger os dados manipulados dentro da classe,


além de determinar onde esta classe poderá ser manipulada.

Usamos o nível de acesso mais restritivo que faça sentido para um membro
particular. Sempre usamos private, a menos que tenhamos um bom motivo para
deixá-lo com outro nível de acesso.

Não devemos permitir o acesso público aos membros, exceto em caso de ser
constantes. Isso porque membros públicos tendem a nos ligar a uma
implementação em particular e limita a nossa flexibilidade em mudar o código.

Basicamente, usamos quatro tipos de encapsulamento que são divididos em


dois níveis:

• Nível de classe ou topo: Quando determinamos o acesso de uma classe


inteira que pode ser public ou package-private (padrão);
• Nível de membro: Quando determinamos o acesso de atributos ou métodos
de uma classe que podem ser public, private, protected ou package-
private (padrão).

Para utilizarmos estes modificadores de acesso, basta que nós os digitemos


antes do nome da variável, atributo, método, função ou classe, com exceção de
package-private, que é entendido como padrão, portanto, é qualquer membro ou
classe que não tenha modificador especificado.

Exemplo:

1.public class MinhaClasse { //classe public


2. private int inteiro; //atributo inteiro private
3. protected float decimal; //atributo float protected
4. boolean ativado; //atributo booleano package-private
5.}

Public
O modificador public deixará visível a classe ou membro para todas as
outras classes, subclasses e pacotes do projeto Java.

Private
O modificador private deixará visível o atributo apenas para a classe em que
este atributo se encontra.

Protected
O modificador protected deixará visível o atributo para todas as outras
classes e subclasses que pertencem ao mesmo pacote. A principal diferença é que
apenas as classes do mesmo pacote tem acesso ao membro. O pacote da subclasse
não tem acesso ao membro.

Sem Modificador (Padrão)


Por padrão, a linguagem Java permite acesso aos membros apenas ao
pacote em que ele se encontra.

De forma ilustrativa, abaixo está uma tabela demonstrando todas estas


características.

Modificador Classe Pacote Subclasse Globalmente


Public sim sim sim sim
Protected sim sim sim não
Sem Modificador (Padrão) sim sim não não
Private sim não não não

Get e Set - Métodos Acessores


Como visto anteriormente, o encapsulamento "protege" os atributos ou
métodos dentro de uma classe, portanto devemos prover meios para acessar tais
membros quando eles são particulares, ou seja, quando possuem o modificador
private.

O que torna isso possível é a criação de métodos.

Em programação orientada a objetos, esses métodos são chamados de


métodos acessores ou getters e setters, pois eles provêm acesso aos atributos da
classe, e geralmente, se iniciam com get ou set, daí a origem de seu nome.

Na verdade, não há nada de diferente entre os métodos comuns e os


métodos acessores. A única importância está no fato da orientação a objeto. Pois,
sempre que formos acessar um membro em Java usaremos get ou set.

Set
Nomeamos um método acessor com set toda vez que este método for
modificar algum campo ou atributo de uma classe, ou seja, se não criarmos um
método acessor set para algum atributo, isso quer dizer que este atributo não deve
ser modificado.

Portanto, como o valor de um atributo da classe será modificado, não é


necessário que este método retorne nenhum valor, por isso, os métodos setters são
void. Porém, obrigatoriamente, eles tem que receber um argumento que será o
novo valor do campo.

Get
Nomeamos um método acessor com get toda vez que este método for
verificar algum campo ou atributo de uma classe.

Como este método irá verificar um valor, ele sempre terá um retorno como
String, int, float, etc. Mas não terá nenhum argumento.

Is
Nomeamos um método acessor com is toda vez que este método for
verificar algum campo ou atributo de uma classe que tenha retorno do tipo
boolean.

Levando em consideração as informações acima, nossa classe de exemplo


TV ficaria:

01.public class TV {
02. private int tamanho;
03. private int canal;
04. private int volume;
05. private boolean ligada;
06.
07. public TV(int tamanho, int canal, int volume, boolean ligada) {
08. this.tamanho = tamanho;
09. this.canal = canal;
10. this.volume = volume;
11. this.ligada = ligada;
12. }
13.
14. public int getTamanho() {
15. return tamanho;
16. }
17.
18. public void setTamanho(int tamanho) {
19. this.tamanho = tamanho;
20. }
21.
22. public int getCanal() {
23. return canal;
24. }
25.
26. public void setCanal(int canal) {
27. this.canal = canal;
28. }
29.
30. public int getVolume() {
31. return volume;
32. }
33.
34. public void setVolume(int volume) {
35. this.volume = volume;
36. }
37.
38. public boolean isLigada() {
39. return ligada;
40. }
41.
42. public void setLigada(boolean ligada) {
43. this.ligada = ligada;
44. }
45.}
Capítulo 1M
Herança
Enquanto programamos em Java, há a necessidade de trabalharmos com
várias classes. Muitas vezes, classes diferentes tem características comuns, então,
ao invés de criarmos uma nova classe com todas essas características usamos as
características de um objeto ou classe já existente.

Ou seja, herança é, na verdade, uma classe derivada de outra classe.

Para simplificar de uma forma mais direta, vejamos:

Vamos imaginar que exista uma classe chamada Eletrodomestico, e nela


estão definidos os seguintes atributos: ligado (boolean), voltagem (int) e consumo
(int).

Se levarmos em conta a classe TV que estamos usando de exemplo até


agora, podemos dizer que TV deriva de Eletrodomestico. Ou seja, a classe TV
possui todas as características da classe Eletrodomestico, além de ter suas próprias
características.

Extends e Super
Para fazermos uma classe herdar as características de uma outra, usamos a
palavra reservada extends logo após a definicação do nome da classe. Dessa forma:

class NomeDaClasseASerCriada extends NomeDaClasseASerHerdada

Importante: Java permite que uma classe herde apenas as características de


uma única classe, ou seja, não pode haver heranças múltiplas. Porém, é permitido
heranças em cadeias, por exemplo: se a classe Mamifero herda a classe Animal,
quando fizermos a classe Cachorro herdar a classe Mamifero, a classe Cachorro
também herdará as características da classe Animal.

Como estamos tratando de herança de classes, toda classe tem seu método
construtor. Portanto, se estamos trabalhando com duas classes, temos dois
métodos construtores. Para acessarmos o método construtor da classe que está
sendo herdada usamos o super().
Podemos usar o super para qualquer construtor da classe pai, pois o Java
consegue diferenciar os construtores por causa da sobrecarga de métodos.

Para finalizar, iremos mostrar o exemplo citado mais acima da classe


Eletrodomestico e TV. Observe:

Classe 1: Eletrodomestico

01.package tiexpert;
02.
03.public class Eletrodomestico {
04. private boolean ligado;
05. private int voltagem;
06. private int consumo;
07.
08. public Eletrodomestico(boolean ligado, int voltagem, int consumo) {
09. this.ligado = ligado;
10. this.voltagem = voltagem;
11. this.consumo = consumo;
12. }
13. // (...)
14.}

Classe 2: TV

01.package tiexpert;
02.
03.public class TV extends Eletrodomestico {
04. private int canal;
05. private int volume;
06. private int tamanho;
07.
08. public TV(int voltagem, int consumo, int canal, int volume, int tamanho) {
09. super(false, voltagem, consumo);
10. this.canal = canal;
11. this.volume = volume;
12. this.tamanho = tamanho;
13. }
14. //(...)
15.}

Classe que mostra a instanciação de TV.

01.package tiexpert;
02.
03.public class ExemploHeranca {
04. public static void mostrarCaracteristicas(TV obj) {
05. System.out.print("Esta TV tem as seguintes características:\n"
06. + "Tamanho: " + obj.getTamanho() + "\"\n"
07. + "Voltagem Atual: "+ obj.getVoltagem() + "V\n"
08. + "Consumo/h: " + obj.getConsumo() + "W\n");
09. if (obj.isLigado()) {
10. System.out.println("Ligado: Sim\n"
11. + "Canal: " + obj.getCanal() + "\n"
12. + "Volume: " + obj.getVolume()+"\n");
13. } else {
14. System.out.println("Ligado: Não\n");
15. }
16. }
17.
18. public static void main(String args[]) {
19. TV tv1 = new TV(110, 95, 0, 0, 21);
20. TV tv2 = new TV(220, 127, 0, 0, 29);
21. tv2.setLigado(true);
22. tv2.setCanal(3);
23. tv2.setVolume(25);
24. mostrarCaracteristicas(tv1);
25. mostrarCaracteristicas(tv2);
26. }
27.}

O código acima irá mostrar o seguinte resultado:

Esta TV tem as seguintes características:


Tamanho: 21"
Voltagem Atual: 110V
Consumo/h: 95W
Ligado: Não

Esta TV tem as seguintes características:


Tamanho: 29"
Voltagem Atual: 220V
Consumo/h: 127W
Ligado: Sim
Canal: 3
Volume: 25