Programação Desktop: Uma abordagem com Java

73
Programação Desktop Uma abordagem com Java ROSICLÉIA FRASSON DE SOUZA

description

Programação Desktop: Uma abordagem com Java

Transcript of Programação Desktop: Uma abordagem com Java

Programação Desktop

Uma abordagem com Java

ROSICLÉIA FRASSON DE SOUZA

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."); } } }