Upload
rosicleia-frasson
View
314
Download
6
Embed Size (px)
DESCRIPTION
Programação Desktop: Uma abordagem com Java
Citation preview
Fundamentos da Linguagem Java Rosicléia Frasson
1
Fundamentos da linguagem Java
Histórico da linguagem Java
por Bruno Bitencourt Luiz
Em 1991, atenta a grande tendência dos microprocessadores e dispositivos inteligentes, a Sun
Microsystems dá início a um projeto de pesquisa com a ideia de desenvolver uma linguagem sólida para
o mercado. O líder do projeto era James Gosling. O objetivo era que aplicações rodassem em qualquer
aparelho de pouca memória como switchboxes de televisores. Para cumprir este objetivo a linguagem
deveria ser pequena, porém potente. Infelizmente, o mercado para estes dispositivos não se
desenvolveu como a Sun esperava. Porém, em 1993, a Web se populariza de uma forma repentina. A
Sun vê então a possibilidade de usar esta linguagem para a Web. A ideia é que esta linguagem
baseada em C++ tornasse as aplicações Web e suas animações mais dinâmicas. Oficialmente, o Java
só é apresentado em 1995 durante uma conferência.
Finalmente, no início de 1996 é lançado o Java 1.0. Versão que de imediato causou decepção
na comunidade Java, pois pecava em vários requisitos como: segurança e interface visual. Mais
adiante, foi lançada a versão 1.1, com várias melhorias de segurança e graficamente mais amigável,
mas ainda não era satisfatória. Na conferência JavaOne em 1998 a versão 1.2 é lançada. Continha
várias melhorias de segurança e substituía por completo a interface anterior. Esta versão foi um marco
na história do Java, dias depois a versão 1.2 passou a se chamar Java 2 Standart Edition Software.
Posteriormente foram sendo lançadas várias atualizações. A última versão que adicionou uma série de
recursos significativos foi a versão 5, pois mais de 1000 classes e interfaces foram implementadas.
Atualmente o Java está na versão 8 com mais de 3 mil classes e interfaces existentes.
O Java é amplamente aceito por parte dos desenvolvedores. Isso se deve a características
como: simplicidade, orientação a objetos, compatibilidade com redes, robustez, segurança,
portabilidade, alto desempenho, capacidade de múltiplos threads. Além disso, deve-se destacar que sua
licença é GPL, e que é multiplataforma, ou seja, para desenvolver em Java não é necessário adquirir
qualquer tipo de licença e a compatibilidade com todos os principais sistemas operacionais é garantida.
Durante o desenvolvimento deste trabalho, a versão Java mais recente é a 8.0. Esta é mais uma
daquelas que causam uma revolução. Diversas melhorias como a expressão Lambda (λ) foram
adicionadas. Este é um recurso novo no Java, porém já existia em outras linguagens. O foco desta nova
versão é fazer mais, com menos código.
Distribuições do Java
Java pode ser encontrada em três distribuições principais, cada uma com sua finalidade
específica:
● Java StandartEdition (JSE): Usada em computadores pessoais, notebooks e arquiteturas com
poder de processamento consideráveis. Várias APIs acompanham esta versão.
● Java Enterprise Edition (JEE): É a tecnologia Java para aplicativos distribuídos em rede em larga
escala e aplicativos baseados na web . Possui um grande número de APIs voltadas para a
segurança da aplicação. Usada em servidores, contendo suporte para JSP, XML e servlets.
● Java Micro Edition (JME): Usada em dispositivos com recursos limitados, como sistemas
embarcados e dispositivos móveis. Possui APIs bem simples e leves para economizar memória
e processamento.
Fundamentos da Linguagem Java Rosicléia Frasson
2
Além das três principais distribuições, também existe o Java Card, que é uma edição específica
para cartões inteligentes, extremamente reduzida. Nesta tecnologia até a máquina virtual é dividida
entre o sistema do cartão e o sistema operacional do terminal.
Compilador e interpretador Java
O processo de tradução da linguagem Java para a linguagem de máquina é um pouco diferente
das demais linguagens de programação. Os programas Java são compilados e interpretados.
Após a criação de um programa Java, um compilador transforma o programa em uma linguagem
intermediária, chamada de bytecodes. Os bytecodes representam uma linguagem de máquina para uma
máquina abstrata, executada pela máquina virtual nos dispositivos que suportam a linguagem de
programação Java. Sendo assim, o bytecode é independente de plataforma.
Todas as vezes que o programa é executado, a JVM (Java Virtual Machine) lê o arquivo com a
extensão .class que está em bytecode e o interpreta para o processador. Vale mencionar que quando
uma classe é carregada na JVM, a mesma é verificada para garantir que os bytecodes são bem
formados e atendem aos critérios de segurança e confidencialidade.
Com o uso da máquina virtual, o programa fica independente de sistema operacional e de
plataforma. Uma máquina virtual é muito mais ampla do que um interpretador. Uma máquina virtual é
uma espécie de computador de mentira, tem tudo o que um computador tem: gerenciamento de
memória, thread, pilha de execução.
Nas primeiras versões do Java, o processo de interpretação feito pela JVM era lento, o que
tornava um problema para a linguagem. Na versão 1.2 surgiu o Compilador Just In Time ou Compilador
JIT. O compilador JIT trabalha em conjunto com o interpretador Java. O interpretador verifica quais
trechos de código são executados mais vezes e pede que o compilador JIT os compile, convertendo o
bytecode na linguagem de máquina do processador que está executando o programa. O JIT também
possui informações relativas ao ambiente em que está executando, como quantidade de usuários
simultâneos e memória disponível. Com essas informações a JVM muda a estratégia de compilação em
busca de um melhor desempenho.
Java SE
A Java Standart Edition é o segmento base da plataforma. Com o Java SE é possível criar
Fundamentos da Linguagem Java Rosicléia Frasson
3
aplicações Desktop e applets. A Java SE possui duas grandes divisões:
● JRE: ambiente de execução Java para quem quer apenas executar programas em Java. É
composta pela JVM e as APIs Java. Uma API é uma coleção de softwares prontos, que incluem
desde estruturas para a manipulação de arquivos até a construção de aplicativos gráficos.
● JDK: é o conjunto de ferramentas necessárias para o desenvolvimento de programas Java. É
composto pela JRE, javac (compilador), jar (empacotador) e o javadoc (documentação).
IDEs
Programas em Java podem ser construídos usando apenas um bloco de notas e um prompt de
comando. No entanto, com apenas essas duas ferramentas o processo fica bem dispendioso. Para
deixar o processo de desenvolvimento mais produtivo, existem programas específicos, chamados de
IDEs (Ambiente de Desenvolvimento Integrado).
Uma IDE é um software que tem como objetivo maximizar a produtividade no processo de
desenvolvimento. Alguns recursos que as IDEs possuem:
● Editor de código: Escrita rápida de código, auto completar, gerenciamento de importações, dicas
para correção e geração de código.
● Depurador: Facilidade na busca por erros no código através da análise cuidadosa de cada passo
executado pelo software.
● Compilador: Geração de código de máquina a partir do código fonte automaticamente.
● Deploy: Publicação da aplicação, geração de executáveis.
● Código limpo e automatizado: Facilidade no entendimento do projeto por todos os envolvidos.
● JVM: Processo de interpretação de bytecodes automático.
Fundamentos da Linguagem Java Rosicléia Frasson
4
Principais IDEs para o desenvolvimento Java
Existem uma infinidade de IDEs para o desenvolvimento Java, abaixo segue uma listagem das
líderes de mercado:
● JDeveloper: O JDeveloper é uma ferramenta da Oracle que tem como principal característica a
cobertura de todo o ciclo de desenvolvimento: análise, codificação, manutenção, otimização e
implantação. Esta ferramenta é pouco flexível e seu uso é recomendado quando o software for
produzido usando toda a arquitetura com produtos Oracle.
● Eclipse: Poderosíssima IDE de desenvolvimento, leve, rápido, configurável e com inúmeros plug-
ins. Deixa a desejar no desenvolvimento de telas para desktop.
● Netbeans: Juntamente com o Eclipse, uma das IDEs mais utilizadas pela comunidade de
desenvolvimento. Tem editor de GUI nativo.Gera muito código automático, não editável.
Gerenciamento de memória JVM
Quando a JVM é inicializada um bloco de memória é capturado do sistema operacional para o
programa Java ser executado. Em Java, existem duas áreas de memória. Aquela que os objetos
residem, chamado de heap e a pilha de execução, onde estão as variáveis locais e as chamadas de
métodos a serem executados.
Variáveis de instância são declaradas dentro de uma classe, mas não dentro de um método.
Elas representam o atributo de um objeto. Sendo assim elas residem dentro do objeto a que pertencem,
ou seja, no heap.
A vida de uma variável local é limitada a existência do método em que a mesma está declarada
na pilha de execução. Entende-se por variável local as variáveis declaradas dentro de um método,
inclusive como parâmetros do método. Se uma variável local não for do tipo primitivo, um objeto
correspondente a mesma deve existir no heap. No entanto, como uma variável não primitiva armazena
apenas a referência a um objeto e não o próprio objeto, a variável que contém a referência estará
armazenada na pilha de execução.
Quando um programa chama um método, o método entra na pilha de execução de programas.
Na pilha de chamadas o estado do método e os valores de todas as variáveis locais são armazenados.
O método do topo da pilha é sempre o que está sendo executado no momento. Um método e suas
variáveis locais permanecem na pilha até o fim da sua execução.
GarbageCollector
O Garbage Collector é um dos componentes da JVM e é responsável por liberar espaços da
memória que não estão sendo mais utilizados. Diferente do gerenciamento manual, onde o
desenvolvedor é responsável tanto pela alocação quanto pela liberação de memória, em Java, o
desenvolvedor não define os pontos de coleta, apenas libera as referências dos objetos e em algum
momento a coleta é efetuada. Vale ressaltar que um objeto não é excluído do heap no momento em que
o mesmo deixa de ser referenciado. O Garbage Collector define o melhor momento de efetuar a coleta.
O propósito da coleta de lixo é descartar os objetos que não estão sendo mais usados. Isso
garante espaço de memória para que o software continue sua execução. Um objeto pode deixar de ser
utilizado quando a variável que o está referenciando passa a ser null, quando a variável passa a
referenciar outro objeto ou um método termina sua execução e as variáveis locais do mesmo deixam de
existir.
Basicamente o processo de coleta de lixo pode ser descrito em alguns passos. Embora os
Fundamentos da Linguagem Java Rosicléia Frasson
5
coletores de lixo sejam um pouco mais sofisticados e dependem do fabricante e versão da JVM,
basicamente a coleta de lixo é dividida em duas partes: diferenciação de objetos vivos e mortos e
remoção de objetos mortos.
● Marcação: Nesta etapa o coletor de lixo identifica quais partes da memória estão em uso e quais
não estão.
● Remoçao normal: Objetos não referenciados são removidos, espaços livres ficam espalhados
pela memória.
● Remoção com compactação: Além da remoção dos objetos sem referência, os objetos restantes
são realocados.
A máquina virtual garante que qualquer objeto vai permanecer na memória enquanto existir a
possibilidade de o mesmo ser alcançado pela pilha de execução, além de liberar espaço quando o
objeto não é mais referenciado. O fato do desenvolvedor não se preocupar com a coleta de lixo é um
dos pontos positivos do garbage collector. No entanto, pode se tornar um ponto crítico pela sua
imprevisibidade.
Sintaxe da Linguagem Java Rosicléia Frasson
6
Sintaxe da linguagem Java
Ponto e vírgula, blocos, espaços em branco e case-sensitive
Java é uma linguagem de formato livre, ou seja, não existem regras especiais para o
espaçamento vertical ou para a indentação horizontal. Porém, para uma melhor legibilidade do código, é
interessante usar espaços, tabulações e novas linhas. Em Java, espaços em branco podem ser usados
sem restrições.
Um bloco é formado por uma ou mais instruções agrupadas entre chaves indicando que formam
uma só unidade. O uso de chaves em Java indica a presença de um bloco, onde a abertura da chave
indica o início do bloco e o fechamento da chave, o fim do bloco. Os blocos podem ser organizados em
estruturas aninhadas infinitamente.
Uma instrução é composta por uma ou mais linhas terminadas com um ponto-e-vírgula. No fim
de cada instrução, indispensavelmente deve ser usado o sinal de pontuação ponto-e-vírgula. A quebra
de linha não separa instruções.
O Java é uma linguagem case-sensitive, ou seja, diferencia maiúsculas de minúsculas. Portanto,
escrever letra e LETRA é diferente para o Java.
Palavras reservadas
O Java possui uma lista de palavras que possuem um significado especial para o compilador.
Essas palavras não podem ser usadas na declaração de classes, métodos e variáveis.
catch case byte break boolean assert abstract
double do default continue const class char
float finally final false extends enum else
int instanceof import implements if goto for
private package null new native long interface
super strictpf static short return public protected
try transient throws throw this synchronized switch
while volatile void
Tipos primitivos
No Java existem apenas oito tipos primitivos de dados. Os tipos primitivos fazem parte da
linguagem e não são instâncias de outras classes.
Descricão Tipo Classificação
O tipo boolean pode armazenar apenas dois valores: true ou false, que
representam os valores verdadeiro e falso, respectivamente. O valor boolean lógico
Sintaxe da Linguagem Java Rosicléia Frasson
7
padrão do tipo boolean é false.
Variáveis do tipo byte podem representar valores inteiros com 8 bits de
precisão, ou seja, valores entre -128 a 127. byte
inteiro
Variáveis do tipo short podem representar valores inteiros com 16 bits
de precisão, ou seja, valores entre -32768 a 32767. short
Variáveis do tipo int podem representar valores inteiros com 32 bits de
precisão, ou seja, valores entre -2147483648 a 2147483647. int
Variáveis do tipo long podem armazenar valores inteiros com 64 bits
de precisão, ou seja, valores entre -9223372036854775808 a
9223372036854775807.
long
Variáveis do tipo float podem armazenar valores em ponto flutuante
com 32 bits de precisão, na faixa de - 1.40239846E-45 a 3.40282347E
+ 38 (9 dígitos significativos de precisão).
float
ponto flutuante Variáveis do tipo double podem armazenar valores em ponto flutuante
com 64 bits de precisão, na faixa de - 4.94065645841246544E-324 a
1.79769313486231570E + 308 (18 dígitos significativos de precisão).
double
O tipo char representa um único caracter em Java. Caracteres em
Java são representados usando o conjunto de caracteres Unicode,
com dois bytes por caracter. Esta representação permite a
representação em várias línguas respectivamente.
char caracter
` Ao escolher um tipo de dado para ser usado, o programador deve estar atento a faixa de valores que o campo pode vir a ocupar. A tentativa de armazenar um valor maior do que o esperado pelo tipo pode ocasionar erros no software. Para representar valores decimais em Java é utilizado o ponto ao invés da vírgula. Além dos caracteres normais, existem os caracteres de controle, que efetuam uma ação diferenciada quando utilizados. Segue uma lista dos mesmos:
Descrição Caracter
aspa dupla \”
aspa simples \’
nova linha \n
tabulação \t
barra \\
enter \r
Conversão entre tipos primitivos
Valores de tipos numéricos podem ser transformados em outros tipos numéricos de duas
formas:
● Implicitamente: A JVM transforma em tempo de execução, quando acha conveniente, tipos
restritos em tipos com maior amplitude, ou seja, uma variável pode receber valores de variáveis
de tipos com tamanho menor do que a mesma foi declarada. . Nenhuma informação é perdida.
● Através de uma operação chamada casting ou conversão explícita. Para efetuar a conversão
Sintaxe da Linguagem Java Rosicléia Frasson
8
explícita, basta colocar o tipo de dado para o qual se deseja converter entre parênteses antes da
expressão a ser convertida. Neste caso, o programador estará se responsabilizando por
possíveis perdas de valores.
Na tabela a seguir, estão relacionados todos os casts possíveis na linguagem Java.
double float long int char short byte PARA: DE:
implícito implícito implícito implícito (char) implícito ----- byte
implícito implícito implícito implícito (char) ----- (byte) short
implícito implícito implícito implícito ----- (short) (byte) char
implícito implícito implícito ----- (char) (short) (byte) int
implícito implícito ----- (int) (char) (short) (byte) long
implícito ----- (long) (int) (char) (short) (byte) float
----- (float) (long) (int) (char) (short) (byte) double
Declaração de variáveis
Variáveis são espaços na memória onde podemos guardar informações. Cada valor é convertido
para binário e então pode ser alocado na memória. Praticamente todos os programas usam variáveis. E
como o próprio nome diz, elas podem ter o valor modificado durante a execução do programa. As
variáveis possuem tipos diferentes, dependendo da informação a ser armazenada.
No Java, para declarar uma variável é necessário especificar o tipo, dar um nome a ela e
preferencialmente inicializá-la. Valores iniciais são estabelecidos por expressões de inicialização
usando o operador = quando as variáveis são declaradas.
Os nomes de variáveis ou identificadores possuem algumas regras para que o compilador
identifique como válido:
● Os nomes de variáveis em Java devem ser inicializados por uma letra, um cifrão ou por
undescore;
● Após o primeiro caracter, vale qualquer combinação de números, letras e caracteres;
● Os identificadores não podem ter o nome igual ao de uma palavra reservada.
Além das regras que são definidas pela linguagem, algumas convenções de nomes foram
estabelecidas pela comunidade de programadores com o intuito de deixar o código mais legível. Segue
uma lista das principais convenções:
● O nome de uma variável deve ser escrito em letras minúsculas. Caso o nome da variável seja
uma palavra composta, a primeira letra a partir da segunda palavra deve ser escrita com letra
maiúscula;
● O nome de uma variável deve ser significativo, indicando claramente o que a variável
representa. Isso significa que se o nome de uma variável necessita de um comentário para
explicar o porquê da sua existência, ele deve ser trocado.
● É indicado utilizar nomes que refletem o domínio em que o software será utilizado.
● As abreviações e siglas devem ser usadas com cautela. Decifrar uma abreviação adiciona um
Sintaxe da Linguagem Java Rosicléia Frasson
9
tempo extra na execução de uma tarefa.
● Nomes semelhantes devem ser evitados, pois podem confundir o desenvolvedor, principalmente
quando o recurso de autocompletar disponível nas IDEs de desenvolvimento é utilizado.
● É considerada uma boa prática não utilizar como identificadores nomes confusos que podem
levar quem lê o código a conclusões erradas.
● Identificadores de variáveis devem ser escritos no singular, exceto quando a variável representar
uma coleção de dados.
● É indicado utilizar nomes pronunciáveis para facilitar a leitura e comunicação.
● É preferível declarar uma variável por linha, ao invés de várias na mesma linha.
Entrada e saída de dados
A classe Scanner possui uma série de métodos convenientes para ler o fluxo de entrada. A
mesma faz parte do pacote java.util e é necessário importá-lo para a utilização da classe. Para a leitura
de dados do console, na criação do objeto é necessário passar como argumento Sistem.in.
Para cada tipo primitivo existe um método da classe Scanner que retorna um valor do tipo que
foi invocado. Sendo assim, existem os métodos nextInt(), nextDouble(), nextFloat(), nextBoolean(), entre
outros. O método close() fecha o escaneamento de leitura.
O objeto System.out permite exibir uma saída de texto no console. Dentro deste objeto existem
os métodos println(), print() e printf(). O método println() gera uma saída de texto juntamente com uma
quebra de linha, o método print gera uma saída de texto sem quebra de linha e o método printf() exibe
dados formatados.
package br.com.rosicleiafrasson.sintaxeBasica; import java.util.Scanner; public class EntradaSaidaDadosConsole { public static void main(String[] args) { Scanner entrada = new Scanner(System.in); int idade; String nome; double peso; System.out.println("Informe o seu nome: "); nome = entrada.nextLine(); System.out.println("Informe a sua idade: "); idade = entrada.nextInt(); System.out.println("Informe o seu peso: "); peso = entrada.nextDouble(); System.out.println(nome + ", você possui " + idade + " anos. "); System.out.print("Seu peso é "); System.out.printf("%.2f", peso); entrada.close(); } }
Sintaxe da Linguagem Java Rosicléia Frasson
10
Operadores básicos
Referência a método, função ou atributo de um objeto. .
Separador de identificadores. ,
Finalizador de declarações e comandos. ;
Declarador de vetores e delimitador de índices. [ ]
Separador de blocos. { }
Lista de parâmetros. ( )
Operador de atribuição. =
Operadores lógicos
Maior >
Maior ou igual >=
Menor <
Menor ou igual <=
Igual ==
Diferente !=
E &&
OU ||
Operadores aritméticos
Adição +
Subtração -
Multiplicação *
Divisão /
Módulo (resto da divisão) %
É importante ressaltar que a divisão de números inteiros sempre resulta em um inteiro. Mesmo
que a variável responsável por armazenar o resultado seja do tipo double ou float.
Sintaxe da Linguagem Java Rosicléia Frasson
11
Operadores de incremento e decremento
Os operadores de incremento e decremento são operadores que atuam sobre uma única
variável numérica, aumentando ou diminuindo ou seu valor.
● incremento: adiciona o valor de uma unidade ao valor atual. O operador de incremento é o sinal
de ++;
● decremento: diminui uma unidade do valor atual. O operador de decremento é o --;
Os operadores de incremento e decremento podem ser posicionados imediatamente antes ou
imediatamente após o nome da variável. Vale ressaltar que esses operadores funcionam de forma
diferente dependendo da posição em relação a variável. Se o operador for colocado antes, a variável é
incrementada no momento da sua avaliação. Caso contrário, a variável é incrementada após a sua
avaliação. Maiores detalhes podem ser vistos na tabela a seguir:
Significado Exemplo Operador
Incrementa a variável e depois usa. ++x
++
Usa a variável e depois incrementa. x++
Decrementa a variável e depois usa. --x
--
Usa a variável e depois decrementa. x--
Operadores de atribuição
Expressão equivalente Exemplo Operador
x = x + y x += y +=
x = x - y x -= y -=
x = x * y x *= y *=
x = x / y x /= y /=
x = x % y x%=y %=
Operador condicional ternário ( ?:)
O operador condicional ternário retorna um entre dois valores de acordo com o resultado de uma
expressão booleana. O mesmo possui a seguinte estrutura:
Onde:
● o primeiro operador a esquerda do ? é a condição, normalmente representada por uma
expressão booleana;
● o segundo operando que fica entre ? e : representa o valor da expressão, caso a condição seja
Sintaxe da Linguagem Java Rosicléia Frasson
12
verdadeira;
● o terceiro operando a direita do : representa o valor da expressão se a condição for falsa.
Segue um trecho de código que deve mprimir na tela a mensagem aprovado, caso a nota do
aluno seja um valor maior ou igual a 7. Caso contrário deve imprimir a mensagem reprovado.
Scanner entrada = new Scanner(System.in); double nota; System.out.println("Informe a nota do aluno: "); nota = entrada.nextDouble(); System.out.println(nota >= 7 ? " Aluno aprovado " : " Aluno reprovado");
Diferença entre tipos primitivos e variáveis de referência
As variáveis primitivas guardam o real conteúdo da variável. Uma variável de tipo primitivo pode
armazenar exatamente um valor de seu tipo declarado por vez, quando outro valor for atribuído a essa
variável, seu valor inicial será substituído.
As variáveis de referência são as variáveis que apontam para um objeto, ou seja,guardam um
endereço de memória para um objeto criado.Desta forma, quando um outro valor é atribuído para a
variável, uma nova posição de memória aloca o novo valor e a referência aponta para a nova posição
de memória. O tamanho alocado para uma variável de referência é sempre fixo, pois se trata de um
endereço de memória que mostra como chegar ao objeto.
String
Em Java não existe um tipo primitivo para se trabalhar com textos. Para fazer uso dos mesmos é
necessário utilizar o tipo String que é um objeto presente no Java desde a primeira versão. A classe
String faz parte do pacote java.lang e por ser uma classe amplamente usada, ela não precisa ser
instanciada. Sua atribuição é composta por uma sequência de caracteres delimitados por aspas duplas.
Os objetos da classe String são imutáveis, ou seja, o conteúdo de uma String nunca pode ser
alterado. Cada vez que é executada uma operação para modificar uma String, o que ocorre é a criação
de um novo objeto, enquanto o objeto String original permanece inalterado.
A JVM mantém uma área especial chamada de pool de Strings. Cada vez que é atribuído uma
String a uma variável, é feita uma busca no pool a fim de encontrar uma String idêntica. Se existir, a
referência a nova String é direcionada a String existente. Caso contrário, é criada uma nova String no
pool.
A classe String fornece diversos métodos utilitários. Seguem os mais utilizados:
● equals: Retorna true se as duas Strings possuírem o mesmo tamanho e exatamente os mesmos
caracteres. O método equalsIgoreCase não diferencia letras maiúsculas e minúsculas.
● replace: Este método faz a substituição de um determinado conjunto de caracteres por outro,
retornando uma nova String. O método é case sensitive.
● trim: Retorna uma String sem os espaços em branco no começo e no final da mesma.
● contains: Este método avalia se a String original possui a String passada por parâmetro. Retorna
um valor booleano.
● lenght: Retorna o tamanho da String.
Sintaxe da Linguagem Java Rosicléia Frasson
13
● toUpperCase: Retorna uma nova String com todos os caracteres em maiúsculo.
● toLowerCase: Retorna uma nova String com todos os caracteres em minúsculo.
● charAt: Retorna o caracter que se encontra na posição passada por parâmetro da String.
● substring: Retorna um objeto String contendo os caracteres especificados entre o intervalo de
valores passados como argumentos para o método.
● valueOf: Retorna uma String a partir de uma dado numérico. É um método estático, sendo
assim, não pertence a um objeto e sim a classe String.
public class UtilitariosString { public static void main(String[] args) { String frase1 = "O rato roeu a roupa do rei de roma."; System.out.println(frase1.replace('r', 'p')); String frase2 = " É melhor prevenir do que remediar. "; System.out.println(frase2.trim()); String frase3 = "Um é pouco, dois é bom, três é demais"; System.out.println(frase3.contains("dois")); System.out.println(frase3.length()); System.out.println(frase3.toUpperCase()); System.out.println(frase3.toLowerCase()); System.out.println(frase3.substring(12,22)); System.out.println("dois".equals("dois")); System.out.println("dois".equalsIgnoreCase("DOIS")); System.out.println(frase3.charAt(8)); String numeroCasa = String.valueOf(45); } }
Para transformar uma String em um tipo numérico, é necessário utilizar as classes de ajuda para
os tipos primitivos correspondentes:
● Integer.parseInt: Para conversões para o tipo inteiro;
● Double.parseDouble: Para conversões para o tipo double.
● Long.parseLong: Para conversões para o tipo long.
● Float.parseFloat: Para conversões para o tipo float.
● Short.parseShort: Para conversões para o tipo short.
● Byte.parseByte: Para conversões para o tipo byte.
int idade = Integer.parseInt(JOptionPane.showInputDialog("Informe sua idade: ")); double peso = Double.parseDouble(JOptionPane.showInputDialog("Informe o seu peso: ")); float altura = Float.parseFloat(JOptionPane.showInputDialog("Informe sua altura: ")); long matricula = Long.parseLong(JOptionPane.showInputDialog("Informe sua matrícula: "));
Sintaxe da Linguagem Java Rosicléia Frasson
14
Estruturas condicionais
Comando if … else
A estrutura if ... else permite expressar duas alternativas de execução, uma delas executa caso
a condição seja verdadeira e a outra quando a condição não for satisfeita. A expressão contida dentro
do comando if deve resultar em um valor booleano. A cláusula else é opcional.
if (expressão){
bloco de comandos
}else{
bloco de comandos
}
Quando houver apenas um comando dentro do bloco if ou do bloco else, não é necessário o uso
das chaves.
É possível construir uma série de testes através do encadeamento de um outro if na cláusula
else. Quando houver comandos if aninhados, cada else está relacionado ao if que estiver dentro do
mesmo bloco que ele.
Segue um exemplo de utilização do comando if … else de um aplicativo que exibe uma
mensagem conforme a situação do aluno: aprovado, em recuperação ou reprovado.
import java.util.Scanner; public class CondicaoIfElse { public static void main(String[] args) { Scanner entrada = new Scanner(System.in); System.out.println("Informe a média do aluno: "); double media = entrada.nextDouble(); if (media >= 7){ System.out.println("Aluno aprovado!"); }else if (media >= 4){ System.out.println("Aluno em recuperação!"); }else{ System.out.println("Aluno reprovado!"); } entrada.close(); } }
Comando switch
O comando switch permite transferir o fluxo de controle para uma entrada rotulada em um bloco
de comandos, baseado no valor de uma expressão. A expressão deve ser do tipo inteiro ou um valor
enumerado. Em outras palavras, o comando switch faz o teste da expressão de seleção contra os
valores das constantes indicados nas cláusulas case, até que um valor verdadeiro seja obtido.
Sintaxe da Linguagem Java Rosicléia Frasson
15
switch (expressão){
case constante1:
bloco de comandos;
break;
case constante2:
bloco de comandos;
break;
•••
default:
bloco de comandos;
}
Se não for encontrado um rótulo case que combine com o valor da expressão switch, o fluxo de
controle é transferido para o primeiro comando que segue o rótulo default. O rótulo default é opcional.
Vale mencionar que um rótulo case ou default não força uma saída para fora do switch, nem
implica no final da execução dos comandos. Para forçar a saída do switch, é necessário utilizar o
comando break.
Segue um trecho de código com a utilização do comando switch.
import java.util.Scanner; public class CondicaoSwitch { public static void main(String args[]) { Scanner entrada = new Scanner(System.in); System.out.println("Informe um dia da semana"); int diaDaSemana = entrada.nextInt(); switch (diaDaSemana) { case 1: System.out.println("Domingo"); break; case 2: System.out.println("Segunda-feira"); break; case 3: System.out.println("Terça-feira"); break; case 4: System.out.println("Quarta-feira"); break; case 5: System.out.println("Quinta-feira"); break; case 6: System.out.println("Sexta-feira"); break; case 7: System.out.println("Sábado"); break; default: System.out.println("Este não é um dia válido!"); }
Sintaxe da Linguagem Java Rosicléia Frasson
16
entrada.close(); } }
Estruturas de repetição
Comando for
O comando for é usado quando é necessário repetir um bloco de comando sobre um intervalo
de valores do ínicio ao fim. O laço for introduz uma nova mecanismo de definição de variáveis, a
declaração no laço de inicialização. Sendo assim, o escopo da variável é reduzido a região exata em
que a mesma é necessária, ou seja, a variável existe apenas enquanto o laço estiver sendo executado.
for (inicialização; condição; incremento){
bloco de comandos;
}
O comando for permite expressar iterações combinando uma expressão de inicialização, um
teste de condição e uma expressão de incremento.
● inicialização: comando de atribuição que define o valor inicial da variável que controla o número
de repetições.
● condição: expressão relacional que define até quando as iterações serão executadas.
● incremento: expressão que define como a variável de controle do laço deve variar ( pode
aumentar ou diminuir).
O teste da condição do controle é feito no início do laço, o que significa que se a expressão de
condição for falsa os comandos dentro do laço não serão executados.
Segue um exemplo de utilização do comando for.
public class RepeticaoFor { public static void main(String[] args) { for (int num = 0; num <=10; num++){ System.out.println(num); } } }
Comando while
Como já mencionado no comando for, o comando while também é utilizado para repetir um
trecho de código diversas vezes. No entanto este comando possui apenas a expressão de condição, a
inicialização da variável de controle e o incremento não estão presentes na sintaxe do comando.
while (condição){
bloco de comandos;
}
Sintaxe da Linguagem Java Rosicléia Frasson
17
A expressão de condição pode ser qualquer expressão ou valor que resulte em um verdadeiro
ou falso. O laço while é executado enquanto a condição for verdadeira e o teste da condição de controle
é feito no ínicio do laço, o que significa que se a expressão resultar em um valor falso, os blocos de
comando dentro do laço não serão executados.
Segue um exemplo de utilização do comando while.
public class RepeticaoWhile { public static void main(String[] args) { int num = 0; while (num <= 10 ){ System.out.println(num); num++; } } }
Comando do … while
Similar ao comando while, porém, o teste da condição de controle é feito no fim do laço, o que
significa que os comandos dentro do laço são executados pelo menos uma vez.
do{
bloco de comandos;
}while (condição);
Segue um exemplo de utilização do comando do … while.
import java.util.Scanner; public class RepeticaoDoWhile { public static void main(String[] args) { Scanner entrada = new Scanner(System.in); int num; do{ System.out.println("Informe um número: "); num = entrada.nextInt(); }while(num > 0); entrada.close(); } }
Sintaxe da Linguagem Java Rosicléia Frasson
18
Instruções break e continue
Os comandos break e continue são estruturas auxiliares dos fluxos de repetição. Ambos os
comandos paralisam a execução antes do normal.
O comando break pode ser utilizado com as instruções while, for, do … while e switch e
ocasiona a saída imediata dessa instrução. A execução continua com o primeiro comando após a
instrução de controle.
public class ComandoBreak { public static void main (String args []){ for (int numero = 1; numero <= 1000; numero ++){ System.out.println("Número: "+ numero ); if (numero == 10) break; } } }
O comando continue ignora as instruções restantes no corpo do loop e prossegue para a
próxima iteração do laço. Pode ser utilizado nas estruturas de repetição for, while e do … while.
Nos laços while e do … while o programa avalia o teste de condição do loop imediatamente após
a execução da instrução continue. Nos laços for, a expressão de incremento é executada e então o
teste de condição do loop é avaliado.
public class ComandoContinue { public static void main(String[] args) { for (int num = 0; num <= 100; num ++){ if (num % 5 != 0){ continue; } System.out.println(num); } } }
Comentários
Comentário é a parte do código ignorada pelo compilador. É utilizado para deixar o código mais
inteligível. Java possui três tipos diferentes de comentário:
● Comentário de uma linha: O uso de barra dupla marca o início do comentário que se estende até
o fim da linha.
● Comentário de várias linhas: Os delimitadores /* e */ indicam início e fim de um comentário e
podem conter várias linhas.
● Comentário javadoc: É utilizado para gerar a documentação javadoc e é delimitado pelas
sequências de símbolos /** e */. Para gerar o javadoc é necessário que o comentário esteja
localizado imediatamente antes da classe, atributo ou método documentado.
Sintaxe da Linguagem Java Rosicléia Frasson
19
Arrays
Uma variável em Java corresponde a uma posição de memória, cujo conteúdo pode ser alterado
durante a execução do programa. Embora uma variável possa assumir diversos valores, ela só pode
armazenar um valor a cada instante. Quando é necessário que mais de um valor do mesmo tipo seja
armazenado, pode ser utilizada uma estrutura chamada vetor ou array.
Como o array pode guardar vários valores, em sua definição é necessário definir o seu tamanho,
ou seja, a quantidade máxima de valores que o mesmo pode armazenar. A quantidade de elementos de
um vetor é definida na criação do mesmo e não pode ser alterada.
String[] nome = new String[10];
Para declarar um vetor, é necessário colocar um par de colchetes antes ou depois do nome da
variável. Também é necessário reservar um espaço na memória e definir o tamanho do vetor, ou seja, a
quantidade total de elementos que podem ser armazenados no vetor. O operador new reserva espaço
de memória para alocar os elementos.
Implicitamente cada elemento no array é inicializado com um valor padrão, sendo 0 para
numéricos primitivos, false para booleanos e null para objetos. Os objetos arrays possuem um campo
length que indicam a quantidade de elementos do array.
nome[0] = "Maria";
Ao armazenar uma informação em um vetor é necessário indicar a posição em que esta será
alocada. Nos arrays em Java a primeira posição possui índice 0 e o mesmo aumenta gradativamente
até o número de posições reservadas menos um. Uma tentativa ao acesso de uma posição fora dos
limites do array lança uma exceção ArrayIndexOutOfBoundsException.
Um array pode ser inicializado com valores entre chaves que seguem a sua declaração
separados por vírgulas.
String [] frutas = {"Abacaxi", "Acerola", "Morango", "Jaca", "Jabuticaba"};
Quando um array é inicializado dentro da sua declaração, não existe a necessidade da
criação do vetor usando new. Neste caso, o tamanho do array é determinado pela quantidade de
valores fornecidos na inicialização.
import java.util.Scanner;
public class Vetor {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
String[] nome = new String[6];
for (int i = 0; i < 6; i++){
System.out.println("Informe o aluno " + i + " :");
Sintaxe da Linguagem Java Rosicléia Frasson
20
nome[i] = entrada.nextLine();
}
System.out.println("\nAlunos: ");
for(int i = 0; i < nome.length; i++){
System.out.println(nome[i]);
}
entrada.close();
}
}
Estrutura de repetição for each
O comando for each possui como objetivo facilitar o loop em um array ou em uma coleção e é
indicado para percorrer todo o conjunto de dados, sem a necessidade de indicar o tamanho do mesmo.
Os loops for each ficam mais legíveis e tendem a minimizar as oportunidades de erros pela ocultação
do iterador, sem perda de desempenho.
for ( declaração: expressão){
bloco de comandos;
}
Na declaração é necessário indicar o tipo de dado presente no array ou coleção e atribuir um
identificador. Caso o tipo de dado indicado na declaração for diferente do tipo de dado dos elementos
do array, o código não compila. A expressão consiste no array ou coleção que deve ser percorrida.
Cada vez que o loop é executado, a variável do laço assume o próximo valor do conjunto e o
bloco de comandos é executado. Normalmente a variável do laço é utilizada dentro do bloco de
comandos. Esse processo continua até o término do conjunto de dados.
É importante ressaltar que a instrução for-each pode ser usada apenas para obter elementos de
um array, ela não pode ser utilizada para modificar os elementos. Em outras palavras, não é possível
adicionar, remover ou alterar um valor do array utilizando o comando for aprimorado, nesses casos
deve ser utilizada a estrutura for padrão.
public class ComandoForAprimorado { public static void main(String[] args) { int somaNumeros = 0; int [] numeros = {87, 45, 65, 32, 44, 26, 7, 90}; for(int numero: numeros) somaNumeros += numero; System.out.println("Soma dos elementos do vetor: " + somaNumeros); } }
Sintaxe da Linguagem Java Rosicléia Frasson
21
Pacotes
Os pacotes possuem como objetivo agrupar classes de funcionalidades semelhantes ou
relacionadas. Um pacote é um diretório onde ficam armazenadas classes, interfaces, subpacotes e
arquivos de recursos adicionais, como imagens, usados pelas classes do pacote. Os pacotes são
correspondentes as bibliotecas em outras linguagens de programação.
A utilização de pacotes promove a reutilização de código, auxilia na manutenção e promove os
príncipios de encapsulamento e modularidade da orientação a objetos. O empacotamento é
recomendado pelos padrões de programação Java a fim de diminuir a possibilidade de colisão de
classes, ou seja, classes com o mesmo nome em um mesmo contexto.
Com o intuito de evitar conflitos de nomes de pacotes e ao mesmo tempo possuir um nome
significativo é utilizado um padrão para a nomeação de pacotes:
● Nomes de pacotes devem ser compostos exclusivamente por letras minúsculas, não importando
a quantidade de palavras que o mesmo contenha;
● Os nomes de pacotes devem ser relativos a empresa que desenvolveu os mesmos. Geralmente
é utilizada a nomeação reversa de domínios, onde o início do nome do pacote é dado pela
ordem inversa do nome do domínio da instituição na internet.
Em Java, as classes devem possuir como primeira instrução a indicação do pacote a que
pertencem. A instrução começa com a palavra chave package, seguida pelo caminho do pacote
delimitado por pontos. Classes que não possuem a instrução package pertencem ao pacote default que
correspondem a raiz do projeto.
package br.com.nomeempresa.sintaxeBasica;
Classes declaradas sem o modificador de visibilidade public ficam invisíveis para outros pacotes.
Classes que não possuem utilidade fora do pacote em que estão declaradas devem possuir o
modificador de acesso default.
A utilização de classes fora do pacote a que pertencem, necessita da indicação do caminho
onde estão armazenadas. Isso pode ser feito de duas formas: através do nome plenamente qualificado
do tipo ou através da importação do pacote.
A utilização do nome plenamente qualificado é uma opção viável. No entanto, pode ser tedioso e
causar confusão no código, se levando em consideração que os pacotes possuem nomes longos.
javax.swing.JOptionPane.showMessageDialog(null, "Exemplo utilização de nome plenamente qualificado do tipo");
A outra maneira de utilizar classes de um pacote, é importar parte ou todo o pacote através da
instrução import. A instrução import permite que código fonte de classes de outros pacotes sejam
incluídas dentro de um código fonte em tempo de compilação. A instrução import inclui a palavra chave
import seguida pelo caminho do pacote, delimitado com pontos e terminando com o nome de uma
classe ou o coringa *. As instruções import ocorrem depois da instrução package e antes da definição
de classe.
import javax.swing.JOptionPane; public class Pacote { public static void main(String[] args) { JOptionPane.showMessageDialog(null, "Exemplo utilização de importação de
Sintaxe da Linguagem Java Rosicléia Frasson
22
pacote"); } }
A API do JSE é composta por vários pacotes. Todos os pacotes iniciados por java ou javax
fazem parte da API padrão. As funcionalidades dos mesmos são detalhadas na documentaçao do Java.
Na tabela a seguir, estão os pacotes mais utilizados e uma descrição sucinta dos mesmos:
Funcionalidade Pacote
Fornece classes que são fundamentais para a concepção da linguagem Java. É importado automaticamente.
java.lang
Pacote utilitário. Fornece classes para trabalhar com coleções, entrada de dados (Scanner) e componentes de data e hora.
java.util
Fornece classes para definir interfaces gráficas com o usuário. java.awt
Extensão do pacote java.awt. javax.swing
Fornece classes para realizar operações de entrada e saída de dados através do sistema de fluxo de dados (streams) e serialização de objetos .
java.io
Classes para acesso a base de dados via JDBC. java.sql
Orientação a objetos Rosicléia Frasson
23
Programação Orientada a Objetos
Programar consiste em desenvolver softwares que executam determinadas funcionalidades. Um
software pode ser descrito como uma série de instruções organizadas que operam sobre um conjunto
de dados. Operar sobre um conjunto pequeno de dados é uma tarefa que pode ser facilmente
executada. No entanto, a medida que a complexidade do software aumenta, trabalhar com um extenso
conjunto de dados inter relacionado deixa de ser uma tarefa trivial.
A Programação Orientada a Objetos, também conhecida pelas iniciais POO, oferece uma forma
para tratar a complexidade citada, auxiliando na construção de softwares mais confiáveis e de fácil
manutenção. O uso do paradigma orientado a objetos melhora a organização e reduz a quantidade de
código em um software, além disso, toda a lógica de negócio fica encapsulada, o que garante que as
responsabilidades são concentradas nos pontos certos, aumentando a flexibilidade.
Na POO, um software é conceituado como um conjunto de objetos que interagem e mantém seu
próprio estado local, fornecendo ações baseadas nesse estado. Cada objeto constitui uma parte
separada do programa e interage com outras partes. Essa interação deve ser feita de maneira
controlada, de modo que a representação do estado de um objeto deve ser privativa, ou seja, o estado
de um objeto só pode ser acessado pelo próprio objeto.
As classes constituem a unidade fundamental de um projeto orientado a objetos. São as classes
que definem os objetos de um sistema e suas interações. Durante a execução de um software orientado
a objetos, objetos são criados dinamicamente a partir de definições de classes.
Princípios da programação orientada a objetos
Os pilares que sedimentam a POO são: abstração, encapsulamento, herança, composição e
polimorfismo:
● Abstração: Consiste em focar somente os aspectos importantes de determinado ponto de vista e
desconsiderar os aspectos restantes. A abstração é um meio de reduzir a complexidade. Sendo
assim, no modelo OO, a abstração significa concentrar-se no que é e no que faz um objeto e
não em como o mesmo será implementado.
● Encapsulamento: Consiste em ocultar detalhes da implementação de uma classe. Utilizando o
encapsulamento, os métodos devem ser o único meio de acessar os dados de um objeto. Os
dados não podem ser acessados diretamente, isso assegura que um dado não seja modificado
acidentalmente por funções externas ao objeto.
● Herança: Mecanismo da POO que permite a criação de classes derivadas de classes já
existentes. As classes derivadas herdam atributos e métodos das classes bases. Sendo assim,
existe uma significativa redução na quantidade de código das mesmas.
● Composição: É o mecanismo que permite o uso de uma ou mais classes para compor uma outra
classe. Na composição uma classe é usada como tipo de atributo em uma outra classe, para
que seus atributos possam ser utilizados.
● Polimorfismo: Mecanismo que garante que classes derivadas de uma mesma superclasse
invoquem métodos com a mesma identificação, mas com comportamentos distintos. Em outras
palavras, o polimorfismo é o mecanismo que permite escrever programas que processam
objetos de uma mesma superclasse como se todos fossem do tipo da superclasse.
Orientação a objetos Rosicléia Frasson
24
Notação UML
A UML (Unified Modeling Language) é uma linguagem gráfica para a modelagem de sistemas de
software que ajuda na descrição e no projeto de sistemas, particularmente daqueles construídos
utilizando o estilo orientado a objetos. Ela é composta por uma série de diagramas que estão divididos
em diagramas estruturais e de comportamento. Dentre os diagramas estruturais, um deles, o diagrama
de classes, possibilita modelar com clareza os principais conceitos da orientação a objetos.
A criação de um modelo de classes resulta de um processo de abstração no qual são
identificados os objetos relativos ao contexto que se pretende modelar. Além disso, este modelo
descreve os membros das classes, como atributos e métodos, identificando com clareza a visibilidade
de cada membro. O diagrama de classe também fornece as relações existentes entre as classes.
Objetos
Um objeto é a unidade central da POO. Em um sistema computacional pode ser definido como
uma abstração de alguma coisa em um determinado domínio. Essa abstração deve permitir que o
software mantenha informações sobre a mesma e interaja com ela. Sendo assim, um objeto em um
software é algo que se visualiza, se utiliza e pode assumir um papel.
Em uma definição mais informal, um objeto é qualquer entidade do mundo real que possui um
estado e um conjunto definido de operações para funcionar nesse estado. O estado é composto por um
conjunto de características do objeto. As operações fornecem serviços a outros objetos quando estes
solicitam a realização de uma ação.
Quando um programa é construído utilizando o paradigma orientado a objetos, é necessário
descobrir os objetos que assumem um papel no domínio do problema. Após a descoberta, devem ser
analisados os aspectos relevantes ao problema que o software deve resolver. O mesmo tipo de objeto
pode requerer características e comportamentos distintos em domínios de negócios distintos, ou seja,
um objeto carro em um software para uma montadora possui um enfoque diferente de um carro em um
software de uma locadora de veículos.
Como os objetos em um software são independentes, softwares desenvolvidos usando POO,
são mais fáceis de manter. Mudanças na implementação de um objeto ou adição de novas
funcionalidades não devem afetar outros objetos do sistema. Além disso, os objetos podem ser
componentes reusáveis, visto que um projeto pode utilizar objetos criados em projetos anteriores. Isso
reduz os custos do projeto, visto que na reutilização são aproveitados objetos já implementados e
validados.
Classes
Uma classe é a especificação para a criação de um objeto, ou seja, uma classe fornece a
estrutura necessária para que um objeto possa ser criado. Sendo assim, ela descreve as propriedades
e funcionalidades de um objeto em forma de atributos e métodos.
Além dos atributos e métodos, uma classe pode possuir classes aninhadas. Uma classe
aninhada ou interna é uma classe declarada dentro de outra classe.
Vale ressaltar que uma declaração de classe cria um tipo. Em Java a declaração de uma classe
não cria um objeto. Os objetos devem ser explicitamente criados. Sendo assim, é correto afirmar que
uma classe é o projeto de um objeto. Este projeto possui como objetivo orientar a JVM na criação de um
objeto. Cada objeto criado possui valores próprios para os atributos da classe.
Na notação UML, uma classe é representada como um retângulo vertical com três seções. O
Orientação a objetos Rosicléia Frasson
25
nome da classe do objeto está na seção superior, os atributos da classe estão na seção intermediária e
as operações associadas a classe estão na seção inferior do retângulo.
Em Java, uma classe é definida utilizando a palavra chave class. Após a palavra chave class,
deve seguir o nome da classe, que deve ser um identificador válido. Os membros de uma classe -
atributos, métodos e classes aninhadas - são listados entre as chaves após a declaração.
Na declaração de uma classe também é informado o modificador de acesso. O modificador
public indica que a classe é publicamente acessível, ou seja, outras classes podem declarar referências
a objetos da classe e acessar seus membros public.
Para nomear classes por convenção devem ser usados substantivos. A primeira letra deve ser
maiúscula. Na concatenação de palavras a primeira letra de cada palavra deve ser maiúscula. Um outro
cuidado é que o nome de uma classe deve descrever o que ela faz.
Atributos
Na definição de classes foi descrito que uma classe possui propriedades que determinam o
estado de um objeto. Essas propriedades de uma classe são denominadas atributos ou variáveis de
instância. Uma variável de instância possui valores distintos para cada objeto criado.
Uma declaração de atributo é composta pelo tipo do atributo, que pode ser um tipo primitivo ou
um objeto, seguido por um identificador e opcionalmente uma claúsula de inicialização que fornece ao
atributo um valor inicial. Vale ressaltar que se o atributo não possuir um valor inicial explicitamente
declarado, um valor inicial padrão é atribuído. Para tipos numéricos o valor padrão é 0, para booleanos
o valor padrão é false e para objetos é null.
Orientação a objetos Rosicléia Frasson
26
Um ponto crucial para a criação de atributos significativos para o objeto é um estudo do escopo
do problema que o software deve resolver.
Métodos
Dentro da POO, os métodos representam o mecanismo de comunicação entre os objetos. A
troca de informações entre os objetos é feita através de parâmetros e valores de retorno dos métodos.
Além disso, um método pode mudar o estado do objeto, ou seja, um método pode alterar o valor de um
ou mais atributos que estão contidos no objeto.
Uma declaração de um método é composta de duas partes: cabeçalho e corpo do método. No
corpo do método fica o código executável que possui a função de manipular os dados armazenados nos
objetos. Já o cabeçalho do método é composto por um conjunto opcional de modificadores, o tipo de
retorno do método, a assinatura do método e uma claúsula throws opcional que relaciona as exceções
lançadas pelo método.
A assinatura de um método consiste no nome do método e na lista de parâmetros entre
parênteses, que pode ser vazia. Obrigatoriamente todos os métodos devem possuir uma assinatura e
um tipo de retorno.
Os métodos que não possuem retorno usam a palavra chave void como tipo de retorno. Métodos
void não retornam nenhuma informação para a classe que o chamou. Para os métodos com retorno, é
utilizado o tipo de retorno que pode ser um tipo primitivo ou uma classe Java. Os métodos com retorno
podem retornar apenas um único resultado, seja um valor primitivo ou a referência a um objeto.
O fato de um método possuir retorno ou não, altera o encerramento da execução. Quando um
método não possui valor de retorno, a execução é encerrada quando o bloco do corpo do método chega
ao final. Já quando o método possui valor de retorno, a execução é encerrada através do comando
return.
Orientação a objetos Rosicléia Frasson
27
Os métodos podem receber argumentos representados por uma lista de parâmetros separados
por vírgula, onde para cada parâmetro é indicado o tipo e o nome. Todos os parâmetros de métodos
são passados por valor, independente de serem tipos primitivos ou objetos. Parâmetros do tipo objeto
passam a referência ao objeto e não o próprio objeto. Dessa forma, se o estado do objeto for alterado
durante a execução do método, o objeto é alterado para cada parte do programa que possui uma
referência para ele.
Vale ressaltar que um parâmetro de um método é uma variável local. Isso significa que ao fim da
execução do método ela deixa de existir.
Para serem executados os métodos devem ser invocados. Métodos são invocados como operações
sobre objetos através de referências. Os métodos com parâmetros quando invocados, obrigam o
invocador a fornecer um argumento do tipo apropriado para cada um dos parâmetros declarados pelo
método.
referencia.método (argumentos);
Quando um método é invocado, o fluxo de execução passa para o método invocado e os
comandos deste são executados em sequência. Um método retorna ao invocador em uma das três
condições: a execução de um comando return, o bloco de execução acaba nos casos dos métodos void
ou uma exceção não capturada é lançada.
Sobrecarga de métodos
A sobrecarga de métodos ou overloading é o mecanismo que permite a criação de vários
métodos com o mesmo nome, mas com possibilidades de entradas diferentes. Essas entradas que
consistem nos parâmetros dos métodos devem ser tipos diferentes, quantidade de parâmetros distintas
Orientação a objetos Rosicléia Frasson
28
ou posições de tipos diferentes.
A sobrecarga é comumente utilizada quando é necessário criar métodos que realizem as
mesmas tarefas, porém com tipos de dados diferentes ou números distintos de argumentos.
O compilador distingue os métodos sobrecarregados pela sua assinatura, sendo assim, não é
possível declarar métodos com a mesma assinatura e tipos de retorno distintos, pois no momento da
invocação do método, o compilador não seria capaz de determinar a versão do método a ser chamada
porque o valor de retorno é ignorado.
A API do Java contempla uma série de métodos sobrecarregados, um bom exemplo é o método
max da classe Math, que possui quatro métodos sobrecarregados que possuem como objetivo retornar
o maior valor de dois números.
Métodos da classe Object
Em Java todos os objetos derivam da classe Object. A classe Object possui uma série de
métodos que podem ser utilizados pelas classes criadas. Dentre eles, os mais importantes são:
● toString
O método toString possui como objetivo retornar a representação String de um objeto, ou seja,
retorna uma String que textualmente representa esse objeto. Este método é chamado automaticamente
quando um objeto é passado para print ou para um operador de concatenação de Strings. O método
toString de Object retorna a String com o package, o nome da classe, o caracter @ e um número de
identidade em hexadecimal.
br.com.rosicleiafrasson.oo.Produto@58c3d9ac
Orientação a objetos Rosicléia Frasson
29
Para retornar informações mais concisas sobre o objeto, o toString pode ser reescrito.
public String toString() { return "Produto " + "\nCódigo: " + codigo + "\nNome: " + nome + "\nPreço: " + preco ; }
● getClass
O método getClass retorna informações do objeto como o package e o nome da classe.
● equals
O método equals faz a comparação entre dois objetos e retorna o valor true se ambos ocuparem
o mesmo espaço de memória. O método equals pode ser reescrito para que outros critérios de
comparação sejam utilizados.
Métodos com um número variável de parâmetros
A partir do Java 5, os métodos podem ser construídos com uma quantidade variável de
parâmetros. Tais métodos são chamados de varargs.
Na declaração de um método varargs, o último parâmetro é declarado como uma sequência de
um dado tipo. Para indicar que um parâmetro é uma sequência são colocadas reticências (...) após o
tipo do parâmetro. Os parâmetros de sequência permitem que a invocação do método tenha um número
variável de argumentos, incluindo zero.
Quando um parâmetro é declarado como uma sequência, o compilador constrói implicitamente
um array e adiciona neste os elementos passados como argumento. Apenas um parâmetro de
sequência é permitido por método.
public double calculaValorVenda (double ... precosProdutos){ double valorTotal = 0; for (double preco : precosProdutos) { valorTotal += preco; } return valorTotal; }
Quando um parâmetro é declarado como uma sequência, o compilador constrói um array do tipo
especificado pelo parâmetro de sequência e armazena os argumentos passados nesse array.
Instâncias de classes
Uma classe é a especificação de um objeto. No entanto, para ser criado, um objeto precisa ser
instanciado. Quando um objeto é criado, ele adquire espaço em memória para armazenar seu estado e
um conjunto de operações podem ser aplicadas ao mesmo. Sendo assim, para atribuir valores a
quaisquer atributos e invocar métodos é necessária a instanciação de um objeto da refererida classe.
A maneira mais comum de instanciar um objeto é através da palavra chave new. Para a criação
Orientação a objetos Rosicléia Frasson
30
de um objeto através do comando new, é necessário especificar o tipo de objeto que deve ser criado e
os argumentos da sua construção.
O new aloca espaço para armazenar os campos do objeto e os inicializa. Quando a inicialização
está completa, o sistema de execução retorna uma referência ao novo objeto. É importante ressaltar
que no momento da alocação se o sistema não encontra espaço suficiente para criar o objeto, ele
efetua uma coleta de lixo para tentar recuperar espaço. Após a coleta se não existir espaço livre, é
lançada uma exceção: OutOfMemoryError.
Construtores
Quando a palavra chave new é utilizada, um objeto é construído. A palavra chave new executa o
construtor da classe. Construtores são blocos de código que são usados para inicializar um objeto,
antes que a referência seja retornada por new.
Um construtor é um bloco declarado com o mesmo nome da classe seguido por uma lista de
parâmetros entre parênteses. Os argumentos passados ao construtor podem inicializar informações.
Sendo assim, os construtores podem obrigar a passagem de argumentos para o objeto durante o
processo de criação do mesmo. Vale ressaltar que o construtor é invocado após os atributos terem sido
configurados com seus valores iniciais default. Um construtor não possui valor de retorno.
Orientação a objetos Rosicléia Frasson
31
Em uma classe em que não existe um construtor declarado, a JVM cria implicitamente um
construtor default. O construtor default não recebe nenhum argumento e seu corpo é vazio. A partir do
momento em que um construtor é declarado, o construtor default deixa de ser fornecido.
Uma classe pode ter mais de um construtor. Desde que a lista de argumentos seja diferente.
Neste caso, no momento da instanciação do objeto é necessário escolher o construtor apropriado. Um
construtor pode invocar outro construtor da mesma classe usando a invocação this() como seu primeiro
comando executável. Se o construtor a ser invocado possui argumentos, os mesmos podem ser
passados na invocação do construtor. O construtor invocado é determinado pela quantidade e tipo de
argumentos usados.
Palavra chave this
A palavra chave this é usada para passar uma referência ao objeto atual. Comumente é usada
quando o nome do campo a ser acessado é o mesmo nome de uma variável local ou parâmetro.
Orientação a objetos Rosicléia Frasson
32
O this permite uma diferenciação entre atributos e parâmetros de métodos. Dessa forma, é
possível ter o mesmo identificador para uma variável de instância e um parâmetro de método. Essa
prática tende a deixar o código mais legível e amigável.
Atributos estáticos
Os atributos estáticos consistem em campos pertencentes as classes, ou seja, não existe uma
cópia do atributo para cada objeto. Sendo asssim, todos os objetos compartilham a mesma cópia da
variável. Um campo estático deve ser declarado com o modificado static.
Variáveis estáticas possuem escopo de classe. Sendo assim, elas podem ser acessadas por
meio de uma referência a qualquer objeto da classe ou pelo nome da classe, seguido pelo atributo.
As variáveis estáticas são inicializadas quando uma classe é carregada. Uma classe é carregada
pela JVM quando uma instância da mesma é criada pela primeira vez ou quando uma variável ou
método estático é utilizado. Vale mencionar que as variáveis estáticas são inicializadas antes que
qualquer objeto da classe possa ser criado e antes de qualquer método estático da classe ser
executado.
Orientação a objetos Rosicléia Frasson
33
Métodos estáticos
Os métodos estáticos realizam procedimentos sem estarem vinculados a um objeto. Sendo
assim, eles pertencem a uma classe e não a uma instância da mesma. Em outras palavras, um método
estático pode ser executado sem a existência de uma instância da classe a que pertence.
Os métodos estáticos só podem realizar operações sobre atributos estáticos, isto é, para a sua
execução nenhuma instância específica da classe pode ser utilizada. Sendo assim, métodos estáticos
também não podem utilizar métodos não estáticos. Métodos estáticos são adequados para métodos
utilitários que não dependam do valor de uma variável de instância específica.
Como exemplo de método estático da classe Java pode ser citado o método
showMessageDialog da classe JOptionPane. É importante perceber que para utilizar o mesmo, não é
necessária nenhuma instância da classe JOptionPane.
Classe Math
A classe Math é constituída por uma série de métodos estáticos para operações matemáticas,
Orientação a objetos Rosicléia Frasson
34
entre elas potências, raízes, logaritmos, arredondamentos e operações trigonométricas. Além disso
possui duas constantes, o PI e E.
Por pertencer ao pacote java.lang não precisa ser instanciada. Seguem alguns métodos
disponíveis na classe:
● Math.PI - Constante PI
● Math.pow(a, b) - Potência na forma ab
● Math.sqrt(a) - Raiz quadrada de a
● Math.cbrt(a) - Raiz cúbica de a
● Math.abs(a) - Retorna o valor absoluto de a
● Math.min(a, b) - Retorna o menor valor
● Math.max(a, b) - Retorna o maior valor
● Math.ceil(a) - Arredonda para cima
● Math.floor(a) - Arrenda para baixo
Campo final
Um campo final não pode ter seu valor alterado após ter sido inicializado. Sendo assim, ele é
usado para definir uma propriedade imutável dentro de uma classe ou objeto. Na maioria dos casos os
campos final são também campos estáticos. Isso significa que todos os objetos da classe compartilham
um valor imutável.
Por convenção os identificadores dos campos final devem possuir todas as letras maiúsculas.
Nos casos de palavras compostas, as mesmas devem ser separadas pelo caractere underscore.
Enum
Em Java, um Enum é um tipo especial de classe que corresponde a um conjunto fixo de
constantes. Os Enums deixam o código menos vulnerável a erros de programação e mais legível.
A declaração de uma enumeração é similar a declaração de uma classe, exceto que ao invés da
palavra chave class, é utilizada a palavra chave enum. Outra particularidade é que antes de declarar
qualquer membro da classe, é necessário declarar todas as constantes de enumeração. Seguindo a
convenção de constantes, o identificador é escrito com todas as letras em maiúsculas.
Orientação a objetos Rosicléia Frasson
35
Agregação e composição
Em um sistema orientado a objetos, é necessário que existam relacionamentos entre as classes.
Para a UML, existem diversos relacionamentos possíveis. Entre eles, agregação e composição.
Agregação é uma especialização da associação e indica que uma classe é parte de um todo.
Ainda, que a parte pode existir sem o todo. Como exemplo pode ser citado o relacionamento entre um
cargo e um funcionário. Se o funcionário deixar de existir, o cargo pode ser usado por um outro
funcionário. Na UML, a agregação é representada por uma linha sólida com um losango vazio na
extremidade que representa o todo.
A composição é similar a agregação. No entanto, na composição a parte existe somente
enquanto o todo existir. Como exemplo pode ser citada a relação que existe entre um pedido e os itens
que estão contidos nesse pedido. Se o pedido deixar de existir, os itens relacionados a ele não fazem
mais sentido. Na UML, a composição é representada por uma linha sólida com um losango preenchido
na extremidade que representa o todo.
Tanto a composição quanto a agregação são relacionamentos do tipo TEM UM. Na definição de
classes Java, os dois relacionamentos se comportam da mesma maneira. Uma classe possui como um
tipo de atributo uma outra classe.
Orientação a objetos Rosicléia Frasson
36
Encapsulamento
O encapsulamento consiste em ocultar dados e implementações da classe. Em outras palavras,
membros de uma classe podem ser escondidos de forma a prever acessos indevidos. A orientação a
objetos recomenda que o estado de um objeto deve ser mantido oculto. Os objetos devem ser
manipulados apenas através de métodos públicos, dos quais apenas as assinaturas devem ser
expostas. Vale ressaltar que apenas os métodos que são importantes para as classes externas devem
ser visíveis.
A utilização do encapsulamento protege as classes cliente contra os efeitos de uma alteração.
Isso é possível porque o cliente conhece apenas a assinatura do método. Sendo assim, a
implementação do mesmo pode ser alterada sem que nenhuma modificação na assinatura seja
necessária.
Outro ponto, é que o estado do objeto fica protegido contra modificações inválidas feitas pelas
classes clientes. Visto que o estado só pode ser alterado através de métodos, é possível incluir
validadores de dados nesses métodos ou lançar um erro ao cliente no caso de valores indevidos.
Modificadores de acesso
A restrição de acesso a classes e a membros da mesma é parte fundamental da orientação a
objetos. Sendo assim, faz-se necessário um meio para restringir o acesso a classes e membros desta.
Em Java, são utilizados os modificadores de acesso para controlar a visibilidade de classes,
construtores, atributos e métodos. Existem quatro modificadores de acesso: private, default, protected e
public.
Orientação a objetos Rosicléia Frasson
37
O modificador public indica que a classe ou o membro pode ser acessado em qualquer parte do
programa. Este modificador deve ser utilizado para construtores e métodos que devem ser acessados
por outras classes. Também pode ser usado em métodos e constantes estáticas. Construtores e
métodos de uso restrito e campos de dados de objetos não devem utilizar public como modificador.
O modificador protected deixa os membros acessíveis a subclasses e classes do mesmo pacote.
A ausência de um modificado de acesso, constitui o chamado modificador default. Este
modificador deixa o membro acessível a classes do mesmo pacote. Classes cosntruídas com a
ausência de modificador só podem ser instanciadas no pacote a que pertencem. O mesmo vale para os
demais membros.
Por fim, o modificador private deixa os membros acessíveis somente dentro da própria classe.
Este modificador deve ser utilizado em atributos de classes, construtores e métodos que não devem ser
acessados por outras classes.
Gets e sets
A visibilidade dos atributos pode ser restrita se aplicados os modificadores de acesso aos
mesmos. No caso de um atributo com modificador private, os atributos só são acessíveis na própria
classe. Isso significa que o estado das propriedades só pode ser alterado através de métodos públicos.
Existe uma convenção para a criação de métodos que possuem como objetivo alterar ou
recuperar o valor de uma propriedade com visiblidade restrita.
Os métodos que possuem como objetivo alterar o valor da propriedade são chamados de
métodos sets. Os métodos sets não retornam nenhum valor, portanto são métodos void. No entanto,
Orientação a objetos Rosicléia Frasson
38
eles devem receber obrigatoriamente um argumento, que corresponde ao valor atribuído ao campo.
Já os métodos que recuperam um valor são chamados de métodos gets. Os métodos gets
obrigatoriamente possuem valor de retorno e não possuem argumentos.
Herança
O mecanismo de herança permite uma hierarquia entre classes. Sendo assim, novas classes
podem ser criadas a partir de outras classes já existentes. As subclasses herdam as características e
comportamentos das superclasses. Isto significa que a herança viabiliza o reúso de código.
Normalmente, uma subclasse além de herdar membros da superclasse, também possui seus
próprios atributos e métodos. Sendo assim, uma subclasse é mais específica que a sua superclasse,
representando deste modo, um grupo mais especializado de objetos.
As novas classes são chamadas de subclasses e as classes já existentes que deram origem as
subclasses são chamadas de superclasses. Uma subclasse pode se tornar superclasse para outras
subclasses. Ou seja, a herança pode ter vários níveis de hierarquia.
Vale ressaltar que a herança é um relacionamento do tipo É UM. Sendo assim, um objeto de
uma subclasse pode ser tratado como um objeto da superclasse.
Orientação a objetos Rosicléia Frasson
39
A nível de codificação, a herança é implementada utilizando a palavra chave extends, seguida
do nome da superclasse. Quando a máquina virtual cria um novo objeto que faz uso de herança, são
definidas todas as variáveis pertencentes a classe e também as variáveis que estão definidas na
superclasse. Quanto aos métodos, o objeto criado possui todos os métodos de sua classe e
superclasse. Sempre que um método é chamado, a JVM verifica a classe do objeto; se o método não
for encontrado, a JVM procura na superclasse dessa classe e assim sucessivamente até que o método
seja encontrado.
A referência aos métodos da superclasse é feita através da palavra-chave super. Para a
chamada de métodos da superclasse, é utilizada a palavra chave super seguida do nome do método. O
comando super também é utilizado para invocar um construtor da superclasse. Neste caso, é utilizada
apenas a palavra super(), com os aurgumentos relativos ao construtor que deve ser invocado.
public class Fabricante extends PessoaJuridica{ public Fabricante() { super(); } }
Orientação a objetos Rosicléia Frasson
40
No Java a hierarquia de classes é iniciada com a classe Object, do pacote java.lang. Em outras
palavras, implicitamente todas as classes extendem de Object e herdam os métodos desta superclasse.
Por este motivo, todos os objetos criados possuem os métodos equals, toString, clone, getClass e
hashCode.
Diferente de outras linguagens, o Java não suporta herança múltipla. A herança múltipla permite
que uma classe herde de mais de uma superclasse.
Sobrescrita de métodos
A sobrescrita de métodos ou overriding é o mecanismo que permite a alteração do
comportamento de uma superclasse pelas suas subclasses, ou seja, a sobrescrita de um método é uma
nova implementação para o mesmo. A sobrescrita de um método ocorre somente se a assinatura do
mesmo permanece intacta, isto é, o tipo de retorno e os parâmetros devem ser os mesmos.
A procura pelos métodos tem início no fim da hierarquia. Isso significa que quando um método é
sobrescrito, a JVM executa o método definido na subclasse. Um exemplo clássico de overriding é a
sobrescrita do método toString da classe Object por outras classes.
Vale ressaltar que os métodos sobrepostos nunca devem ser mais restritivos do que os métodos
originais. Isto significa que:
● Se o método original for public, a sobrescrita deste método obrigatoriamente terá modificador de
acesso public;
● Se o método original for protected, a sobrescrita deste pode ser protected ou public;
● Se o método original não possuir modificador de acesso, a sobrescrita pode não possuir
modificador, ser protected ou public;
● Se um método for private, ele não é visível pela subclasse, sendo assim, não pode ser
sobrescrito.
Modificador final
O modificador final quando usado em uma declaração de classe impede que a mesma seja
extendida. Muitas classes das API Java são final, como a classe String e a classe Math. Isso significa
que é impossível extender as classes String e Math.
Orientação a objetos Rosicléia Frasson
41
Classes devem ser marcadas como final para garantir que subclasses não sejam criadas a partir
da mesma. Sendo assim, o modificador final deve ser usado apenas quando a classe já possuir todos
os métodos implementados e nunca será necessário implementar um comportamento específico.
Um método também pode possuir o modificador final. Neste caso, o método não pode ser
sobrescrito pelas subclasses. O modificador final garante segurança a métodos não podem ser
sobrescritos.
Polimorfismo
A herança e o polimorfismo em Java estão intimamente ligados. O polimorfismo em Java é o
mecanismo que garante que quando um método é invocado por meio de uma referência a superclasse,
em tempo de execução, a versão correta do método da subclasse é executada. Sendo assim, o
polimorfismo garante que objetos de múltiplos tipos sejam referenciados como se fossem do tipo de sua
superclasse.
Em outras palavras, o polimorfismo permite que hierarquias inteiras sejam referenciadas a partir
do tipo da superclasse. Sendo assim, um método que recebe como parâmetro o tipo Object, pode
receber como argumento qualquer tipo de objeto, visto que em Java todas as classes extendem de
Object.
Classe abstrata
Uma classe abstrata constitui uma classe que não pode ser instanciada. Classes são marcadas
como abstratas ficam no topo ou nos níveis próximos ao topo da hierarquia e servem como modelo para
as classes concretas. Sendo assim, as classes abstratas para serem utilizadas precisam herdadas por
classes concretas.
Uma classe abstrata pode conter métodos com sua implementação definida, os métodos
concretos; e métodos que contenham apenas a assinatura, que são chamados de métodos abstratos.
Orientação a objetos Rosicléia Frasson
42
Quando uma subclasse herda uma classe abstrata, obrigatoriamente todos os métodos
abstratos devem ser sobrescritos, pois os mesmos não possuem implementação na superclasse. Uma
classe abstrata pode ser extendida por outra classe abstrata. Dessa forma, a implementação dos
métodos abstratos podem ser postergados para os níveis mais baixos da hierarquia.
Na notação UML, o nome de uma classe abstrata é escrito em itálico. A mesma formatação
também é aplicada para os métodos abstratos.
Orientação a objetos Rosicléia Frasson
43
Interface
Uma interface, assim como uma classe abstrata, possui como propósito forçar uma subclasse a
reescrever todos os métodos abstratos, definindo um comportamento para eles. No entanto, as
interfaces não possuem métodos concretos, apenas abstratos. Uma interface também não possui
atributos, apenas constantes e variáveis estáticas. Uma interface não possui construtores.
Os métodos declarados em uma interface devem ser implementados em todas as classes que
implementam a interface. A implementação de uma interface por uma classe indica um relacionamento
do tipo É UM com a interface. Uma classe pode implementar mais de uma interface.
Uma interface pode estender outra interface. Se uma interface estendida por outra, for
implementada por uma subclasse, esta última deverá implementar todos os métodos abstratos definidos
nas duas interfaces.
Orientação a objetos Rosicléia Frasson
44
Classes Wrappers
As classes Wrappers fornecem um mecanismo para empacotar valores primitivos em um tipo
objeto, para que estes sejam inclusos em atividades reservadas a objetos. Além disso, estas classes
fornecem um conjunto de funções utilitárias para os tipos primitivos, como a conversão de um tipo
primitivo em String e vice-versa.
Com exceção da classe Character, as classes wrappers possuem dois construtores: um que
recebe o tipo primitivo como argumento e outro que recebe uma String como argumento.
Double d1 = new Double(1.0); Double d2 = new Double("1.0"); Integer i1 = new Integer(3); Integer i2 = new Integer("6");
As classes Wrappers fornecem métodos para conversão de uma String em um tipo primitivo
correspondente.
● Boolean.parseBoolean;
● Byte.parseByte;
● Short.parseShort;
● Integer.parseInt;
● Long.parseLong;
● Float.parseFloat;
● Double.parseDouble;
As classes wrappers também fornecem um método que retorna o tipo primitivo por ela
encapsulado. Para efetuar essa conversão existem os métodos intValue, doubleValue, floatValue,
booleanValue, byteValue, shortValue e longValue. Embora a partir do Java 5, existe o recurso de
autoboxing que efetua o desencaixotamento de forma automática.
Integer a = new Integer(12); int b = a.intValue();
Exceções
Na linguagem de programação Java e na grande maioria das linguagens de programação, os
métodos invocados são empilhados em uma estrutura de dados. Isso significa que quando um método
termina a sua execução, o fluxo do programa volta para o método que o invocou, ou seja, o próximo
Orientação a objetos Rosicléia Frasson
45
elemento da pilha. Caso aconteça alguma situação inesperada durante a execução do método, a JVM
verifica se existe algum tratamento para o erro e em caso negativo, faz uma varredura nos métodos da
pilha em busca de um tratamento para o problema. A inexistência de um tratamento para o erro gerado
faz com que o programa seja encerrado.
O mecanismo da linguagem Java relativo a exceções é baseado no conceito que as exceções
são lançadas e capturadas. Quando uma exceção ocorre um objeto do tipo Exception é criado e
lançado dentro do método. Se o método não capturar a exceção a mesma é passada para o invocador.
Isso acontece sucessivamente até que a exceção seja capturada ou chegue na JVM, onde é capturada
automaticamente. O trabalho com exceções se resume a decidir onde as exceções serão capturadas e
como será o tratamento da mesma.
Orientação a objetos Rosicléia Frasson
46
Todas as exceções herdam direta ou indiretamente da classe Throwable, formando uma
hierarquia de herança.
Como todas as exceções descendem de Throwable, todas herdam os métodos desta
superclasse. Seguem os mais utilizados:
Método Descrição
getMessage Retorna uma descrição para a exceção.
printStackTrace Exibe o rastreamento da pilha.
toString Retorna um objeto String contendo uma descrição completa da exceção.
Na hierarquia de exceções exibida anteriormente, pode ser observado que a classe Throwable
possui as subclasses Error e Exception. As classes derivadas de Error representam situações graves
durante a execução do programa e que não podem ser tratados pelo programador, como por exemplo,
a JVM ficar sem espaço na memória. Geralmente os programas não conseguem se recuperar de um
Error, sendo assim, não é necessário codificar um tratamento para o mesmo.
A classe Exception e suas subclasses representam situações excepcionais que podem ser
capturadas pelo aplicativo. Consequentemente podem ser tratadas. Dentro das exceptions ainda
existem as exceções checadas e não checadas.
As exceções que são instâncias ou subclasses da classe RuntimeException refletem erros na
lógica do programa e não são verificadas pelo compilador. Isso significa que pode haver um tratamento
para o erro, no entanto, não existe a obrigatoriedade desse tratamento. As exceções não checadas
mais comuns são:
● ArithmeticException: Indica situações de erro em processamentos aritméticos.
● NumberFormatException: Exceção lançada na tentativa de converter uma String em um valor
numérico, onde o conteúdo da mesma não representa um número adequado para o formato.
● ArrayIndexOutOfBoundsException: Indica a tentativa de acesso a um elemento de um array fora
dos limites válidos.
● NullPointerException: Indica a tentativa de acessar a referência a um objeto que não foi criado.
Já as exceções verificadas compreendem as classes derivadas de Exception e que não derivam
de RuntimeException. Essas exceções necessariamente precisam ser tratadas e normalmente são
Orientação a objetos Rosicléia Frasson
47
causadas por condições que não estão no controle do programa, como uma falha de conexão de rede
ou uma resposta de um outro aplicativo.
As exceções verificadas precisam ser tratadas. O tratamento de uma exceção através do bloco
try catch. Dentro do bloco try são colocados os comandos que podem gerar uma exceção. O bloco try
deve ser seguido por um ou mais blocos catch e/ou um bloco finally. Vale ressaltar que um método
pode lançar várias exceções. Neste caso, todas as exceções que eventualmente possam ser lançadas
devem ser tratadas.
Nos blocos catch são capturadas as exceções. Cada bloco catch define o tipo de exceção que
pode tratar. Vários blocos catch podem ser definidos para um mesmo bloco try. No entanto, apenas um
será executado. O tipo de exceção deve coincidir com o tipo especificado em uma instrução catch. Se
não coincidir a exceção não será capturada.
A captura de uma exceção impede que o programa seja encerrado anormalmente. Quando uma
exceção é lançada ela deve ser capturada e tratada em alguma parte do código fonte. Quando um
programa não captura a exceção, a mesma é tratada pela JVM. O tratador de exceções padrão da JVM
apenas encerra a execução e exibe uma mensagem de erro seguida por uma lista das chamadas de
métodos que levaram a exceção.
O bloco finally contém instruções que sempre serão executadas, independente de uma exceção
ser lançada pelo try . Geralmente esse bloco possui instruções que liberam recursos utilizados durante
o processamento do bloco try precisam ser liberados, independente da execução ter encerrado com
Orientação a objetos Rosicléia Frasson
48
sucesso ou ter sido interrompida por uma exceção. O bloco finally será executado mesmo que exista
um comando return no bloco try. Normalmente esse bloco é indicado para o fechamento de arquivos e
operações de limpeza.
A cláusula throws é utilizada para propagar a exceção para um nível acima na pilha de
execução. Na cláusula throws são especificadas as exceções que o método pode lançar, porém não
serão tratadas dentro do mesmo. Essa cláusula aparece após a lista de parâmetros e antes do corpo do
método. Ela contém a lista de exceções que o método pode lançar caso algum problema ocorra em
tempo de execução.
Em Java, é possível que uma aplicação defina seu próprio tipo de exceção. Para criar um novo
tipo de exceção é necessário que a classe extenda de uma das classes da hierarquia de exceções. O
comando throw lança uma exceção manualmente.
Collections Rosicléia Frasson
49
Collections
Uma coleção é um objeto onde vários elementos podem ser agrupados. Em java, existe uma
arquitetura para representar e armazenar as coleções.
Essa arquitetura e composta por interfaces e classes concretas com uma série de métodos que
realizam operações como inserção, remoção, pesquisa e ordenação dos elementos de uma coleção.
List
A interface List é responsável por armazenar elementos em forma de lista. Uma lista permite
elementos duplicados e mantém os mesmos na ordem em que foram inseridos. A interface List resolve
alguns problemas do array como tamanho infinito e métodos para inserção e pesquisa.
A interface List possui as implementações ArrayList, LinkedList e Vector.
ArrayList<String> arrayList = new ArrayList(); LinkedList<String> linkedList = new LinkedList(); Vector<String> vector = new Vector();
A interface List possui uma série de métodos. Seguem os mais utilizados:
Collections Rosicléia Frasson
50
● add: O método add adiciona no fim da lista um elemento.
● size: O método size retorna a quantidade de elementos que a lista possui.
● remove: O método remove retira um elemento da lista.
● contains: O método constains verifica se um elemento está na lista.
● sort: O método sort recebe um List como argumento e ordena em ordem crescente. Para efetuar
a ordenação um objeto precisa implementar a interface Comparable que define o método
compareTo.
● min: Retorna o menor elemento da coleção.
● reverse: O método reverse inverte a lista.
Set
Um conjunto Set não permite elementos duplicados. Os elementos possuem uma forma
especial de ordenação. A interface Set deve ser utilizada quando a ordem dos elementos não é
importante, visto que performance é muito superior a List.
Collection<Integer> colecao = new HashSet<Integer>(); long tempoInicial = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { colecao.add(i); } for (int i = 0; i < 10000000; i++) {
Collections Rosicléia Frasson
51
colecao.contains(i); } long tempoFinal = System.currentTimeMillis(); System.out.printf("Tempo em milisegundos: ", (tempoFinal - tempoInicial));
Conexão com a base de dados JDBC Rosicléia Frasson
52
Conexão com a base de dados
As bases de dados estão presentes em nossa sociedade há muito tempo e correspondem a um
conjunto de dados inter relacionados referentes a um determinado domínio. Antes dos advento dos
computadores, as empresas armazenavam seus dados em arquivos físicos. Com a popularização da
informática, esses dados passaram a ser armazenados em softwares específicos para este fim. A estes
softwares damos o nome de SGBD. Um Sistema Gerenciador de Banco de Dados possui um ambiente
adequado e eficiente para armazenamento e recuperação de dados.
Modelo Entidade-Relacionamento
O modelo entidade-relacionamento é composto por atributos, entidades compostas pelos
atributos e o relacionamento entre as entidades.
Entidades : São objetos do mundo real dentro do domínio da aplicação, que possuem
informações necessárias para armazenamento na base de dados. A entidade é representada por um
retângulo que contém o nome da entidade.
Atributos: São as propriedades que descrevem as entidades. Poderiam ser atributos da entidade
livro, por exemplo, o título, autor, edição, ano de publicação e a editora.
Chaves: São atributos ou conjuntos de atributos que permitem identificar sem ambiguidade cada
instância de uma entidade, ou seja, garante a distinção entre as ocorrências das entidades.
Relacionamentos: São associações entre duas entidades ou entre uma entidade e ela mesma. O
relacionamento é representado por um losango. Esse losango é ligado por linhas aos retângulos que
representam as entidades participantes do relacionamento.
Conexão com a base de dados JDBC Rosicléia Frasson
53
Tipos de relacionamento: Existem três tipos de relacionamento entre as entidades.
● um para um: é usado quando uma entidade A, se relaciona com uma entidade B e vice-versa.
Este relacionamento é representado pelo sinal 1:1.
● um para muitos: é usado quando uma entidade A pode se relacionar com uma ou mais
entidades B. Este relacionamento é representado pelo sinal 1:N.
● muitos para muitos: é usado quando várias entidades A se relacionam com várias entidades B.
Este relacionamento é representado pelo sinal N:M ou N:N.
Modelo Relacional
O modelo relacional representa os dados em uma base de dados como uma coleção de tabelas
(relações). Todas as tabelas possuem um nome e um conjunto de atributos com seus respectivos
nome e domínios.
Tabela: É onde as informações ficam armazenadas.
Atributos: São todas as informações que existem em uma tabela. Essas informações também
são chamadas de campos.
Domínio: Representa todos os valores possíveis que um atributo pode receber.
Tuplas: Representam as informações armazenadas em uma tabela. Informalmente as tuplas são
chamadas de registros.
Chave primária: É uma coluna ou um conjunto de colunas cujos valores distinguem uma linha
Conexão com a base de dados JDBC Rosicléia Frasson
54
das demais dentro da tabela.
Chave estrangeira: É uma coluna ou uma combinação de colunas, cujos valores aparecem
necessariamente na chave primária de uma tabela. A chave estrangeira permite a implementação dos
relacionamentos em um banco de dados.
Exemplo Supermercado
Linguagem SQL
A linguagem SQL - Structured Query Language - é a linguagem padrão utilizada para gerenciar
a base de dados. O SQL é uma linguagem padrão para a grande maioria das bases de dados, embora
existam algumas variações entre fabricantes diferentes de SGBDs. A linguagem SQL está subdividida
em duas linguagens: DML e DDL.
Os comandos contidos neste documento são baseados no SGBD da Oracle.
DDL
A linguagem DDL - Data Definition Language - é composta por comandos usados para alterar a
estrutura da base de dados. Em outras palavras, comandos para inserir, atualizar e apagar a estrutura
da base de dados. Seguem os comandos mais utilizados:
CREATE TABLE
É o comando utilizado para criar uma tabela na base de dados. As tabelas são organizadas por
linhas e colunas. As tabelas e as colunas da mesma devem possuir um identificador.
CREATE TABLE nome_tabela ( nome_coluna1 tipo_dado (tamanho), nome_coluna2 tipo_dado (tamanho), nome_coluna3 tipo_dado (tamanho), ....
);
Conexão com a base de dados JDBC Rosicléia Frasson
55
ALTER TABLE
Comando utilizado para adicionar, remover ou alterar uma coluna de uma tabela.
● Para adicionar uma coluna:
ALTER TABLE nome_tabela ADD nome_coluna tipo_dado;
● Para remover uma coluna:
ALTER TABLE nome_tabela DROP COLUMN nome_coluna;
● Para editar uma coluna:
ALTER TABLE nome_tabela MODIFY COLUMN nome_coluna tipo_dado;
DROP TABLE
Comando que elimina todos os dados e a estrutura da tabela.
DROP TABLE nome_tabela;
RENAME
Comando utilizado para renomear uma tabela ou sequência.
DROP TABLE nome_tabela;
NOT NULL
Garante a não existência de valores nulos para a coluna. Deve ser definido para cada coluna.
UNIQUE
A restrição unique bloqueia a possibilidade de registros repetidos para uma coluna, ou seja,
garante que todos os valores de uma coluna sejam diferentes.
Conexão com a base de dados JDBC Rosicléia Frasson
56
PRIMARY KEY
Uma primary key é utilizada para identificar de forma única cada linha em uma tabela. A coluna
referente a chave primária não pode conter valores nulos e/ou repetidos.
As chaves primárias podem ser especificadas quando a tabela é criada ou com a alteração de
estrutura com o comando alter table.
FOREING KEY
Uma chave estrangeira define o relacionamento entre duas tabelas. Uma chave estrangeira
consiste de um campo que aponta para a chave primária de outra tabela ou da mesma tabela nos
autorelacionamentos. A chave estrangeira garante a integridade dos dados, pois somente valores
existentes na tabela relacionada podem preencher o campo referente a chave estrangeira.
Onde:
● foreign key define a coluna da tabela filha;
● references indentifica a coluna e a tabela pai.
SEQUENCE
Uma sequence gera números sequenciais de acordo com regras predefinidas no momento de
sua criação. Normalmente, as seqüências são usadas para criar um valor de chave primária que deve
ser exclusivo para cada linha de uma tabela.
Conexão com a base de dados JDBC Rosicléia Frasson
57
CREATE SEQUENCE nome_da_seqüência [increment by n] [start with n] [maxvalue n] or [minvalue n] [cycle | nocycle] [cache n | nocache];
Onde:
● increment by n: define o número a ser incrementado cada vez que a coluna nextval for
referenciada.
● start with n: define o primeiro valor a ser gerado na sequência.
● minvalue n: define o valor mínimo a ser produzido na sequência.
● maxvalue n: define o valor máximo a ser produzido na sequência.
● cycle: especifica se a seqüência continuará a gerar valores após alcançar seu valor máximo ou
mínimo
● cache n: especifica quantos valores o servidor Oracle alocará previamente na memória. Se o
cache não for especificado explicitamente, o Oracle irá assumir o padrão, que é de gerar um
cache de 20 valores.
O comando nextval retorna o próximo número da sequência.
Tipos de dados
A tabela a seguir lista os tipos de dados mais utilizados no banco Oracle.
Descrição Tipo de dado
Armazena dados do tipo caracter de comprimento variável. VARCHAR2(comprimento)
Armazena dados do tipo caracter de comprimento fixo. CHAR(comprimento)
Armazena números flutuantes, porém aceita números inteiros. NUMBER(precisão, escala)
Armazena datas e horas. DATE
Armazena valores inteiros. INTEGER
Vale ressaltar que a única diferença entre o CHAR e o VARCHAR é que o CHAR armazena
caracteres alfanuméricos de tamanho fixo. Isso significa que se a string leite que corresponde ao nome
de um produto for armazenada em uma coluna CHAR(50), a coluna conterá a string LEITE + 45
espaços em branco que são adicionados automaticamente para preencher o tamanho total da coluna..
DML
Conexão com a base de dados JDBC Rosicléia Frasson
58
A linguagem DML - Data Manipulation Language - é composta por comandos usados para
manipular as informações contidas na base de dados. Dentre os comandos mais utilizados estão:
INSERT
Comando utilizado para inserir um registro na base de dados.
INSERT INTO nome_tabela (coluna1,coluna2,coluna3,...)
VALUES (valor1,valor2,valor3,...);
UPDATE
Instrução utilizada para atualizar os registros existentes em uma tabela.
UPDATE nome_tabela SET coluna1=valor1, coluna2=valor2, ... WHERE alguma_coluna = algum_valor;
DELETE
Comando utilizado para remover registros existentes em uma tabela.
DELETE FROM nome_tabela WHERE alguma_coluna = algum_valor;
SELECT
Comando utilizado para recuperar dados de uma ou mais tabelas. O * seleciona todas as
colunas de uma tabela.
SELECT nome_coluna, nome_coluna FROM nome_tabela;
SELECT * FROM nome_tabela;
LIKE
Conexão com a base de dados JDBC Rosicléia Frasson
59
Utiliza-se o operador LIKE para realizar pesquisas com base em coringas em valores string. A
condição de consulta pode conter qualquer caracter literal ou números.
● % para zero ou qualquer caracter
● _ para um caracter qualquer
SELECT nome_coluna FROM nome_tabela WHERE nome_coluna LIKE string;
SQL JOIN
Os joins consistem de uma forma de efetuar a ligação entre tabelas em um comando SELECT.
● Inner join: retorna todos os registros da tabela esquerda (tabela A) que têm correspondência
com a tabela direita (tabela B).
SELECT * FROM A INNER JOIN B ON A.Key = B.Key
● Left join: retorna todos os registros da tabela esquerda (tabela A) e as correspondências que
existirem com a tabela direita (tabela B).
SELECT * FROM A LEFT JOIN B ON A.Key = B.Key
● Right join: retorna todos os registros da tabela direita (tabela B) e as correspondências que
existirem com a tabela esquerda (tabela A).
Conexão com a base de dados JDBC Rosicléia Frasson
60
SELECT * FROM A RIGHT JOIN B ON A.Key = B.Key
● Full join: retorna todos os registros das duas tabelas.
SELECT * FROM A FULL OUTER JOIN B ON A.Key = B.Key
Conexão com a base de dados
A grande maioria das aplicações comerciais necessita de uma base de dados para armazenar
informações que devem ser consultadas posteriormente. Desta forma, ao desenvolver um aplicativo de
uso comercial, é necessário que o mesmo interaja com uma base de dados, seja alterando a mesma ou
consultando informações que estão presentes nela.
O processo de armazenamento de dados é chamado de persistência. A persistência pode ser
efetuada em uma infinidade de bancos de dados. Considerando que cada banco de dados se comunica
com a aplicação de uma forma diferente, faz-se necessário que os programadores conheçam várias
APIs e uma troca de fabricante de banco de dados gera um grande transtorno. Para abstrair as
especificidades de comunicação com os bancos, uma nova camada, chamada de JDBC (Java
Database Connectivity) pode ser adicionada.
Conexão com a base de dados JDBC Rosicléia Frasson
61
JDBC é uma API para acesso aos SGBD (Sistemas Gerenciadores de Banco de Dados)
relacionais por meio de comandos SQL. A JDBC provê um conjunto de interfaces para acesso a um
banco de dados.
Pacote java.sql
Para evitar que cada banco tenha a sua própria API e conjunto de classes e métodos existe um
conjunto de interfaces bem definidas que devem ser implementadas por cada fabricante de banco de
dados. Esse conjunto de interfaces fica dentro do pacote java.sql. A documentação do mesmo pode ser
consultada em: http://docs.oracle.com/javase/7/docs/api/java/sql/package-summary.html. Segue um
descritivo sobre as principais classes e interfaces do pacote.
A classe DriverManager é responsável pela abertura da conexão, especificada através de uma
URL, com uma base de dados utilizando o driver correto. A mesma possui um registro de todos os
drivers já carregados. Para efetuar a abertura da conexão percorre cada Driver verificando se o mesmo
consegue abrí-la ou não até encontrar um driver que consiga.
As conexões implementam a interface Connection. No contexto de uma conexão statements são
executados e os resultados das consultas são retornados. A inicialização de uma conexão é feita
através do método getConnection da classe DriverManager.
Connection con = null; con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "rosi","123");
O objeto Statement controla e executa instruções SQL. A obtenção de objetos Statements se dá
por meio do método createStatement do objeto Connection e a execução dos comandos SQL através
dos métodos execute e executeQuery.
Statement st = con.createStatement(); st.execute("select * from categorias");
Conexão com a base de dados JDBC Rosicléia Frasson
62
O PreparedStatement representa um Statement pré-compilado, o que garante melhor
performance na execução do comando SQL, pois este já foi processado pelo banco de dados. Com a
utilização do PreparedStatement também é possível utilizar parâmetros na consulta. Isso é feito
incluindo o caracter ? nos locais a serem substituídos pelos parâmetros. A inicialização do
PreparedStatement é feita pelo método prepareStatement do objeto Connection.
private static final String INSERT = "insert into categorias (nm_cat) values (?) "; Connection con = null; con = ConnectionFactory.getConnection(); PreparedStatement pstm = con.prepareStatement(INSERT); pstm.setString(1, categoria.getNome()); pstm.execute();
O objeto ResultSet é responsável pelo armazenamento dos dados resultantes de uma consulta
SQL. A inicialização do ResultSet é feita através do método executeQuery dos objetos Statement ou
PreparedStatement.
public static final String LIST = "select * from categorias order by cd_cat"; PreparedStatement pstm = con.prepareStatement(LIST); ResultSet rs = pstm.executeQuery(); while(rs.next()){ Categoria cat = new Categoria(); cat.setCodigo(rs.getInt("cd_cat")); cat.setNome(rs.getString("nm_cat")); categorias.add(cat); }
Drivers
Como o pacote java.sql é apenas um conjunto de interfaces, são necessárias classes concretas
que implementem as mesmas. Essas classes concretas são chamadas de drivers e são elas que
efetuam a ponte entre o código da aplicação Java e o banco de dados.
Os drivers devem ser adicionados as CLASSPATH da aplicação e podem ser baixados no site
do fabricante do banco de dados.
Driver de conexão
Para abrir a conexão com o banco é necessário utilizar um driver. A classe DriverManager é
responsável pela comunicação como os drivers disponíveis. A abertura da conexão é feita pelo método
getConnection que recebe uma uma String de conexão como argumento.
Essa String, chamada de String de conexão JDBC, utilizada para acessar o Oracle, possui a
seguinte forma: jdbc:oracle:thin:@ip:porta:instância. O ip deve ser substituído pelo IP da máquina onde
está armazenado o banco de dados e a instância pelo nome da instância a ser utilizada. Também é
necessário informar o usuário e a senha do banco de dados. Segue código para efetuar a conexão.
Conexão com a base de dados JDBC Rosicléia Frasson
63
Connection con = null; try{
con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "rosi","123");
JOptionPane.showMessageDialog(null, "Conectado com sucesso"); }catch(SQLException e){ JOptionPane.showMessageDialog(null, "Erro ao conectar: " + e.getMessage()); }finally{ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } }
Em uma aplicação comercial, a conexão com a base de dados deve ser feita em diversas partes
da aplicação. Por este motivo, é interessante que a conexão fique centralizada em uma classe e sempre
que necessário, a mesma seja invocada. Comumente essa classe é chamada de fábrica de conexão, já
que a mesma deve ser responsável por devolver conexões.
public class ConnectionFactory { private static final String STR_CONEXAO = "jdbc:oracle:thin:@localhost:1521:xe"; private static final String USER = "rosi"; private static final String PASSWORD = "123"; public static Connection getConnection() throws SQLException {
try { return DriverManager.getConnection(STR_CONEXAO, USER, PASSWORD); } catch (Exception e) { throw new SQLException(e.getMessage()); }
} }
Envio de comandos SQL
O envio de um comando SQL é feito por meio de um Statement. Um Statement pode ser criado:
● através da classe Statement: para comandos SQL simples.
● por meio da classe PreparedStatement: utilizando essa classe, o comando SQL é pré-compilado
e utilizado posteriormente, sendo mais eficiente nos casos onde o mesmo comando é utilizado
várias vezes.
O método executeQuery é utilizado para comandos SQL que retornam uma tabela.
A classe ResultSet oferece a aplicação a tabela resultante de um select e mantém o cursor
posicionado em uma linha da tabela. Inicialmente este cursor está antes da primeira linha e a
mensagem next move o cursor para frente.
Equivalência de tipos Java X SQL
Conexão com a base de dados JDBC Rosicléia Frasson
64
Tipo Java Método para recuperar dados
Tipo SQL
String getString() CHAR
String getString() VARCHAR
int getInt() INTEGER
float getFloat() FLOAT
double getDouble() DOUBLE
long getLong() BIGINT
java.sql.Date getDate() DATE
Interface Gráfica Swing Rosicléia Frasson
65
Interface Gráfica Swing
A grande maioria dos softwares interagem com os usuários através da troca de informações. As
interfaces gráficas consistem do meio utilizado para que o aplicativo possa se comunicar com a parte
humana e vice-versa. Sendo assim, é através da interface que o usuário solicita a execução de alguma
tarefa para o aplicativo e também através da interface que o aplicativo envia respostas para os usuários.
A interface gráfica de um software deve ser composta por uma série de componentes gráficos
intuitivos que permitam ao usuário um aprendizado rápido da ferramenta. Sendo assim, a construção de
uma interface gráfica deve garantir facilidade de aprendizado, eficiência de uso, facilidade de
memorização, baixa taixa de erros e principalmente satisfação do usuário no uso da mesma.
Componentes
Os componentes são as partes individuais das quais uma GUI - Interface Gráfica do Usuário) é
construída. Como exemplos de componentes podem ser citados: botões, caixas de texto, menus, caixas
de seleção e campos de texto. A API do Java contém um grande número de componentes prontos e
inúmeros outros podem ser criados.
A organização dos componentes na tela é chamada de layout. Para organizar os componentes
na tela, é necessário levar em consideração diferentes resoluções, fontes, redimensionamento de
janelas pelos usuários, entre outros aspectos.
Interfaces gráficas em Java
Os elementos básicos para criar uma interface gráfica com o usuário residem em dois pacotes:
awt e swing. A AWT foi a primeira API para interfaces gráficas e posteriormente surgiu o Swing que
trabalha em conjunto com AWT.
O pacote awt usa código nativo. Isso significa que ao crir um botão, o mesmo vai funcionar tanto
no Linux como no Windows, porém, a aparência do mesmo é um pouco diferente. No entanto, o pacote
awt possui recursos limitados por depender do suporte de cada plataforma para os componentes
oferecidos.
A biblioteca Swing foi criada em resposta as limitações do pacote awt. A biblioteca Swing possui
a vantagem que os componentes possuem o mesmo comportamento independente do sistema
operacional. As classes Swing são identificadas com a letra J. Por exemplo JButton, JFrame e JMenu.
Interface Gráfica Swing Rosicléia Frasson
66
Hierarquia de classes dos componentes
As operações comuns à maioria dos componentes GUI, tanto Swing como AWT são definidas na
classe Component. Isso inclui métodos relativos à posicionamento, personalização, tamanho,
visibilidade, pintura, registro de tratadores de eventos.
A classe JComponent é a superclasse da maioria dos componentes Swing. Com exceção dos
containers JFrame e JDialog, todos os demais componentes Swing cujo nome começa com “J”
descendem da classe JComponent
Container
Um Container é o local onde ficam dispostos os componentes. Qualquer programa que tenha
uma interface gráfica terá pelo menos um container:
● JFrame: janela principal do programa;
● JDialog: janela para diálogos;
● JApplet: janela para applets.
Ao objeto da classe Container é atribuída uma chamada ao método getContentPane( ), que devolve
uma referência para o painel de conteúdo do aplicativo ou do applet. O painel de conteúdo compreende
a área imediatamente inferior a barra de título de uma janela, extendendo-se até os limites da mesma.
A classe Container define o método add(Component), para adicionar elementos, e setLayout
Interface Gráfica Swing Rosicléia Frasson
67
(LayoutManager), que configura um gerenciador de layout para gerir o posicionamento e
dimensionamento dos mesmos.
A disposição dos elementos adicionados a um contêiner obedece a ordem em que eles foram
anexados e ao gerenciador de layout previamente definido. Se um container não é suficientemente
dimensionado para acomodar os componentes anexados a ele, alguns ou todos os elementos GUI
simplesmente não serão exibidos.
JFrame
Esta classe define objetos que são frequentemente utilizados para criar aplicativos baseados em
GUI. Eles consistem em uma janela com barra de título e uma borda e fornecem o espaço para a GUI
do aplicativo ser construída.
JPanel
Um painel em Java é um componente utilizado para dividir a interface em seções de modo que o
agrupamento de componentes seja feito com mais facilidade.
A classe JPanel não tem painel de conteúdo como applets e JFrames, assim, os elementos
devem ser diretamente adicionados ao objeto painel.
Interface Gráfica Swing Rosicléia Frasson
68
JLabel
Um JLabel é um rótulo que apresenta textos e/ou imagens.
JTextField
Compreende a área de uma única linha que suporta a inserção ou exibição de texto. Podemos
definir se o texto pode ser manipulado com o método setEditable(boolean), utilizando no argumento o
valor true.
Interface Gráfica Swing Rosicléia Frasson
69
JPasswordField
É uma subclasse de JTextField e acrescenta vários métodos específicos para o processamento
de senhas. Sua aparência e comportamento quase nada diferem de uma JTextField, a não ser quando
o texto é digitado, pois o mesmo fica ocultado pelos asteriscos. Tal procedimento se justifica para
ocultar os caracteres inseridos, dado que esse campo contém uma senha.
JButton
É um componente que quando clicado dispara uma ação específica. Um programa Java pode
utilizar vários tipos de botões:
● botões de comando,
● caixas de marcação,
● botões de alternância,
● botões de opção.
Para criação de um botão, é necessário instanciar uma das muitas classes que descendem da
classe AbstractButton, a qual define muito dos recursos que são comuns aos botões do Swing.
Interface Gráfica Swing Rosicléia Frasson
70
As classes JButton, JCheckBox e JRadioButton são exemplificadas na imagem a seguir.
Gerenciadores de layout
Os gerenciadores de layout determinam como os componentes aparecem na tela. Existem
diversos gerenciadores de layout em Java, dentre eles pode-se citar:
Interface Gráfica Swing Rosicléia Frasson
71
Flow Layout
É o gerenciador de layout mais simples: dispõe os objetos seqüencialmente da esquerda para a
direita na ordem em que foram adicionados e centraliza os componentes na tela deixando uma distância
de 5 pixels entre eles.
Border Layout
Organiza os componentes em cinco áreas: norte, sul, leste, oeste e centro. Os componentes
devem ser adicionados a regiões nomeadas no gerenciador de layout, caso contrário não ficarão
visíveis: NORTH, SOUTH, EAST, WEST, CENTER.
Grid Layout
Divide o container em uma grade de modo que os componentes podem ser colocados em linhas
e colunas. Os componentes são adicionados iniciando na célula na parte superior esquerda da grade e
prosseguindo da esquerda para a direita até a linha estar cheia. Então, o processo continua na próxima
linha.
Interface Gráfica Swing Rosicléia Frasson
72
Eventos
Eventos de interface de usuário incluem o pressionamento de uma tecla, cliques em botões,
movimentos de mouse, seleções de menu, entre outros. Sempre que o usuário efetua uma das ações
citadas, o gerenciador de janela envia uma notificação ao programa que um evento ocorreu.
Para tratar os eventos relativos a botões ou itens de menus, devem ser criadas classes para
manipulação que implementem a interface java.awt.ActionListener. Essa interface possui apenas um
método: actionEvent e é através do mesmo que as ações relativas ao evento do componente devem ser
implementadas.
public class BotaoLogarListener implements ActionListener{ @Override public void actionPerformed(ActionEvent arg0) { if ( cxTexto.getText().equals("teste") && (cxSenha.getText().equals("123"))){ JOptionPane.showMessageDialog(null, "Logado com sucesso"); }else{ JOptionPane.showMessageDialog (null,"Login e/ou senha incorretos."); } } }