Você está na página 1de 193

Linguagem de Programação IV

Ementa da Disciplina
Fundamentos do paradigma orientado a objetos em Java.
Bibliotecas de suporte, componentes gráficos,
interfaces e estruturas de dados, classes coletivas.
Tratamento de exceção.
Gerência de memória.
Multithreading (concorrência).
Applets Java.
Bibliografia
LIVRO TEXTO:
DEITEL, H.M., DEITEL, P.J. Java, Como Programar. 4ª Edição. Porto Alegre: Bookman, 2003.
LEMAY, L. e CADENHEAD, R. Aprenda em 21 Dias Java 2: Professional Reference. 3a. Ed. São Paulo:
Campus, 2003.
OBRAS DE REFERÊNCIA:
HORSTMANN, Cay. Big Java. Porto Alegre: Bookman, 2004.
HORSTMANN, Cay, et al. Core Java 2, Volume 1: Fundamentos. S. Paulo: Makron Books, 2001.
HORSTMANN, Cay, et al. Core Java 2, Volume 2: Recursos Avançados. S. Paulo: Makron Books, 2001.
FURGERI, Sérgio. Java 2 Ensino Didático. São Paulo: Editora Érica, 2002.
CAMARÃO, C. e FIGUEIREDO, L. Programação de Computadores em Java. Rio de Janeiro: LTC, 2003
SANTOS, R. Introdução à Programação Orientada a Objetos usando Java. Rio de Janeiro: Campus, 2003.
MECENAS, I. Java 2 Fundamentos, Swing e JDBC. Rio de Janeiro: Alta Books, 2003.
OLIVEIRA, Alcione P. Notas de Aula DPI-UFV. Viçosa, 2001.
CHAN, Mark C. et al. Java: 1001 Dicas de Programação. São Paulo: Makron Books, 1999.
ECKEL, Bruce. Thinking in Java, 3rd Edition. (e-book).
DAVIS, Stephen R. Aprenda Java Agora. Rio de Janeiro: Campus, 1997.
LALANI, Suleiman S. e JAMSA, Kris. Java: Biblioteca do Programador. São Paulo: Makron Books, 1997.
NEWMAN, A. et al. Usando Java: O Guia de Referência Mais Completo. Rio de Janeiro: Campus, 1997.
WUTKA, Mark. Java: Técnicas Profissionais. São Paulo: Berkeley, 1997.
DAMASCENO JR., Américo. Aprendendo Java: Programação na Internet. São Paulo: Érica, 1996.
JEPSON, Brian. Programando Banco de Dados em Java. São Paulo: Makron Books, 1997.
RITCHEY, Tim. Java! Indianápolis, EUA: New Riders, 1995.
FLANAGAN, David. Java in a Nutshell. O’Reilley & Associates, 1997.
A história de Java
Origem: projeto de pesquisa da Sun Microsystems, iniciado em 1991,
destinado a desenvolver uma linguagem para a programação de dispositivos
eletrônicos em geral (pagers, celulares, PDAs, TV a cabo, etc).

Baseada em C e C++.
Seu criador, James Gosling, inicialmente a chamou de Oak, mas descobriu-se
que, na época, já havia uma outra linguagem com este mesmo nome. Conta a
lenda, que o nome Java foi escolhido em uma cafeteria, e refere-se a uma
variedade de café, originário da ilha homônima, do Pacífico.
Impulso ao uso de Java: a World Wide Web explode em popularidade a partir
de 1993 e a Sun percebe o seu grande potencial para a construção de páginas
com conteúdo dinâmico.

Em 1995, Java é anunciada formalmente à comunidade mundial.


Atualmente, a tecnologia Java divide-se em J2SE, J2EE e J2ME e está na
versão 1.5.0 (o chamado Core Java Software, ou, J2SE 5.0)
Um ambiente Java típico
O programa
criado no editor é
Fase 1 Editor armazenado em
Disco
disco.
O compilador cria
bytecodes e os
Fase 2 Compilador armazena em disco
Disco

Carregador
Fase 3
de Classe
O carregador de classe
coloca bytecodes na
memória principal
Disco
Um ambiente Java típico (cont.)
Verificador O verificador de
Fase 4 bytecodes confirma
de Bytecodes
que todos os bytecodes
são válidos e não violam
restrições de segurança
de Java

Fase 5 Interpretador O interpretador lê os


bytecodes e traduz
para a linguagem de
máquina do computador,
e executa o programa
Um primeiro exemplo em Java
Use o Edit ou qualquer outro editor e digite o seguinte programa Java:

//Um primeiro programa em Java 2


public class AloMundo
{
public static void main(String args[])
{
System.out.println("Alo, mundo!");
}
}

Após digitá-lo, salve com o nome da classe, ou seja: AloMundo.java

Java é uma linguagem case sensitive, ou seja, faz distinção


entre letras maiúsculas e minúsculas em variáveis, comandos
e arquivos.
Ao fazer a instalação no seu computador, verifique se as seguintes alterações foram
feitas no arquivo autoexec.bat (para o Windows 98):
SET JAVA_HOME = C:\JDK1.4.1 (ou o nome que você usou)
SET PATH = C:\JDK1.4.1\bin;%PATH%; ( idem )
SET CLASSPATH = C:\JDK1.4.1\LIB;.; ( idem )
Para compilar o programa, a partir da janela de comando, mude para o
diretório onde o arquivo fonte foi armazenado e digite:

javac AloMundo.java
A compilação vai gerar um arquivo de bytecodes chamado AloMundo.class
Para executar o programa, também a partir da janela de comando, digite:

java AloMundo

O comando java carrega o interpretador e indica que o arquivo AloMundo.class


deve ser interpretado e executado. A execução sempre começa pelo método main.
Obs.: o comando java deve omitir o
sufixo do arquivo a ser interpretado.
Entendendo o programa AloMundo
AloMundo apresenta vários recursos importantes de Java:

// Um primeiro programa em Java 2

Comentário de linha. Um comentário de múltiplas linhas, de acordo com as


especificações da ferramenta de documentação javadoc, segue a sintaxe:

/** Um primeiro programa em Java 2


* Autor: Prof. Wander
*/

Definição de classe para AloMundo. Todo programa java consiste de uma ou


mais classes definidas pelo programador.

public class AloMundo

As palavras reservadas de Java devem ser escritas sempre


em minúsculas.
Os nomes de classes, por convenção, são escritos com todas as palavras
iniciando com letras maiúsculas.

Nomes de classes e quaisquer outros identificadores definidos pelo


programador devem seguir as seguintes regras:
• pode conter letras, números, caractere de sublinhar e cifrão
• não pode começar com número
• não pode conter espaços em branco

Uma chave esquerda { inicia o corpo de cada definição de classe.


Uma chave direita } correspondente termina cada definição de classe.

public static void main(String args[])

O método main é parte de todo aplicativo Java, que começa a execução a


partir deste ponto.

Um método pode ser definido como um bloco de construção de


programa. Uma definição de classe em Java possui um ou mais
métodos.
A palavra-chave void indica o tipo de retorno do método main. Isto
significa que main não retorna valor algum.

Uma chave esquerda { inicia o corpo de cada definição de método.


Uma chave direita } correspondente termina cada definição de método.

System.out.println("Alo, Mundo!");

System.out é o objeto de saída padrão. Permite exibir informações


na janela de comando a partir da qual o aplicativo Java é executado.

O método System.out.println exibe uma linha de texto na janela de


comando. Ao final, o cursor é posicionado no início de uma nova linha.
Um método alternativo é System.out.print cuja diferença consiste em
manter o cursor imediatamente após o texto apresentado na janela de comando.
Esta linha do programa Java constitui uma instrução. Toda instrução
deve terminar com ponto-e-vírgula, chamado terminador de
instrução.
"Alo, Mundo" é uma string de caracteres, e deve ser definida entre aspas
duplas.

Nem toda classe necessariamente deve possuir um método main e, portanto, ser
um aplicativo Java. O exemplo a seguir ilustra isto:

public class Teste {


public static void main(String a[]){
AloMundo.Alo();
}
}
class AloMundo {
public static void Alo(){
System.out.println("Alo, mundo");
}
}
GUI em Java: pacote Swing
Java possui dois pacotes de interfaces gráficas com o usuário. O mais antigo é a
AWT (Abstract Windowing Toolkit), que utiliza os componentes gráficos
nativos do sistema operacional. O exemplo abaixo emprega o pacote Swing
(javax.swing), que emprega componentes gráficos Java.

//AloMundo com interface grafica


import javax.swing.JOptionPane;
public class AloMundo2
{
public static void main(String args[])
{
JOptionPane.showMessageDialog(
null,"Alô, Mundo!");
System.exit(0);
}
}

Após digitá-lo, salve com o nome da classe, ou seja: AloMundo2.java


Java possui uma extensa biblioteca de classes pré-definidas disponíveis para o
programador.
Estas classes são agrupadas em categorias de classes relacionadas, chamadas de
pacotes.
O conjunto de pacotes Java é denominado biblioteca de classes Java ou Java
Application Programming Interface – API.

O pacote javax.swing ajuda o programador a definir interfaces gráficas


com o usuário (Graphical User Interfaces – GUIs)

import javax.swing.JOptionPane;

O comando import indica a localização da classe JoptionPane, presente no


pacote de classes javax.swing

Saída do programa AloMundo2.java:


JOptionPane.showMessageDialog(null,"Alô, Mundo!");

O método showMessageDialog requer dois argumentos, separados


por vírgulas. O segundo argumento deve ser do tipo String.

System.exit(0);

O método exit() da classe System termina o programa.


É obrigatório em todo programa que usa interface gráfica.
O argumento 0 indica que o aplicativo terminou com sucesso.

A classe System é parte do pacote java.lang, que é importado automatica-


mente em todo programa Java.

O método exit()termina a JVM após o encerramento da aplicação


gráfica.
Variáveis
Em Java, é necessário definir formalmente uma variável antes de utilizá-la.
Isto implica em declarar o seu nome e tipo de informação que irá armazenar.

int numero;
String nome;
double preco;
boolean flag;

É uma boa prática de programação definir uma variável por linha.


Existem três tipos de variáveis em Java: locais, de instância e de classe.
As variáveis locais podem ser declaradas em qualquer lugar dentro de um
método. Uma boa prática de programação consiste em defini-las imediata-
mente após a chave de abertura do método.
Atenção: todas as variáveis locais precisam ser inicializadas antes de serem
utilizadas, caso contrário, o compilador acusará erro!
As variáveis de instância podem ser declaradas em qualquer lugar dentro de
uma classe. Uma boa prática de programação consiste em defini-las imediata-
mente após a chave de abertura da classe.
As definições de variáveis de instância, ao contrário das variáveis locais, rece-
bem automaticamente um valor inicial padrão, especificado pelo compilador.
Variáveis numéricas recebem 0, de caracteres, '\0', lógicas, false,
objetos, null.

class Teste {
int numero;
public static void main(String args[]) {
Teste teste = new Teste();
System.out.println(teste.numero);
}
}

Uma variável de instância só pode ser referenciada em uma instância da


classe.
As variáveis de classe, definidas pelo modificador static, podem ser
declaradas em qualquer lugar dentro de uma classe.
As definições de variáveis de classe, da mesma forma que as variáveis de
instância, recebem automaticamente um valor inicial padrão, especificado
pelo compilador. Variáveis numéricas recebem 0, de caracteres, '\0',
lógicas, false, objetos, null.
class Teste {
static int numero;
public static void main(String args[]) {
System.out.println(numero);
}
}

Uma variável de classe pertence à classe, independe de qualquer instanciação


de objetos da classe.
Tipos de dados
Existem oito tipos de dados primitivos em Java para o armazenamento de
inteiros, números de ponto flutuante, caracteres e valores lógicos.
Ao contrário do que acontece em outras linguagens de programação, em Java
estes tipos primitivos têm o mesmo tamanho e características em qualquer
plataforma de hardware e sistema operacional.

boolean 08 bits true ou false


char 16 bits '\u0000' a '\uFFFF'
byte 08 bits -128 a 127
short 16 bits -32.768 a 32.767
int 32 bits -2.147.483.648 a 2.147.483.647
long 64 bits até 9.223.372.036.854.775.807
float 32 bits até 3.40292347E+38
double 64 bits até 1.7976931348623157E+308

Obs.: Os caracteres Unicode são usualmente expressos em termos de um esquema


de codificação hexadecimal. O prefixo \u indica um valor Unicode.
import javax.swing.JOptionPane;
public class Teste {
public static void main(String[] args) {
JOptionPane.showMessageDialog(null,""+Double.MAX_VALUE);
System.exit(0);
}
}

O exemplo acima ilustra a utilização de uma variável de classe, MAX_VALUE,


da classe Double. Esta classe é chamada empacotadora ou wrapper. Cada um
dos tipos primitivos Java possui a sua correspondente classe empacotadora.
A variável de classe MAX_VALUE retorna o valor máximo do tipo primitivo
utilizado, no caso, double.
Se o valor de uma variável não deve ser alterado durante a execução do
aplicativo Java, você poderá usar uma variável constante, que é definida
através da palavra-chave final.

final double PI = 3.141592;


final char CODIGO = '&';

Por convenção, programadores Java utilizam


maiúsculas para definir nomes de constantes.

Um outro conceito importante em Java é o de literal, que consiste em qualquer


número – no caso de tipos numéricos – que representam diretamente um valor.

public class Teste {


public static void main(String a[]){
float total;
total = 5.5; //Erro!!
System.out.println(total);
}
}
public class Teste {
public static void main(String a[]){
float total;
total = 5.5F;
System.out.println(total);
}
}

O erro acontece porque Java trata todas as operações de ponto flutuante em


double e a conversão de double para float não é automática.
Também é possível declarar literais de ponto flutuante com expoentes:
public class Teste {
public static void main(String a[]){
double total;
total = 1.0e5;
System.out.println(total);
}
}
Literais de caracteres são expressos por meio de um único caracter delimitado
por apóstrofos. Alguns literais de caracteres úteis são apresentados abaixo:

\n nova linha
\t tabulação
\b retrocesso
\\ barra
\' apóstrofo
\" aspas

public class Teste {


public static void main(String a[]){
System.out.println("Clube Atletico Mineiro:
\n\"Galo forte e vingador!\"");
}
}
Saída de dados com printf
Um novo recurso, introduzido em J2SE 5.0, é o método System.out.
printf, capaz de formatar mais adequadamente uma saída em Java, em uma
forma semelhante à função printf da linguagem C.

public class Teste {


public static void main(String[] a) {
String s = "Atlético";
System.out.printf(" Grandioso %s\n",s);
}
}

Grandioso Atlético
O primeiro argumento de printf é a string de formatação, composta de
constantes string e caracteres de formatação. No exemplo acima, o
delimitador % seguido de s indica que o método deve ter um outro
argumento do tipo String.
Os caracteres de formatação podem também ser usados para compor uma
String, usando o método String.format, conforme no exemplo a seguir:
public class Main {
public static void main(String[] args) {
int a = 65;
String s = String.format("char: %c integer: %d
hexa: %h octal: %o",a,a,a,a);
System.out.println(s);
}
}
Para o exemplo acima, onde é usado o mesmo argumento para a formatação,
existem alternativas para a codificação:

String s = String.format("char: %c integer: %<d


hexa: %<h octal: %<o",a);

String s = String.format("char: %1$c integer: %1$d


hexa: %1$h octal: %1$o",a);
Entrada de dados com Scanner
A leitura de dados de entrada em aplicativos através da janela de
comando do sistema operacional era surpreendentemente complexa até a
versão 1.4.2 do J2SE. Isto não era problema para aplicativos com recursos
GUI, mas tornava-se desconfortável para estudantes interessados em escrever
programas simples com o propósito de aprender Java.

J2SE 5.0 introduz a classe java.util.Scanner para a entrada de dados,


inclusive através da entrada padrão, System.in.
O exemplo a seguir apresenta uma aplicação Java para a entrada de dois
números pelo teclado e a saída da soma na janela de comando do sistema
operacional.
É necessário criar uma instância da classe Scanner, passando como
argumento o objeto padrão de entrada, System.in, que irá capturar as
entradas de dados via o teclado. O método nextInt(), da instância da
classe Scanner, lê o valor digitado e o armazena em uma variável do tipo
int.
import java.util.Scanner;
public class Teste {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
int num1;
int num2;
int soma;
System.out.print("Entre com o primeiro número: ");
num1 = entrada.nextInt();
System.out.print("Entre com o segundo número: ");
num2 = entrada.nextInt();
soma = num1 + num2;
System.out.printf("A soma é: %d", soma);
}
}

Um exemplo de saída do aplicativo acima:


Entre com o primeiro número: 34
Entre com o segundo número: 23
A soma é: 57
O exemplo seguinte calcula o seno de um valor fornecido em tempo de
execução:
import java.util.Scanner;
public class Teste {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
double angulo;
double seno;
System.out.print("Entre com o ângulo em graus: ");
angulo = entrada.nextDouble();
seno = Math.sin(Math.toRadians(ângulo));
System.out.println("Seno: " + seno);
}
}
O método nextDouble(), da classe Scanner, captura um double da
entrada padrão System.in e o armazerna em uma variável do tipo double.

A classe Math do pacote java.lang define a constante PI através de uma


variável de classe. O método estático Math.sin(double)retorna o seno
de um ângulo em radianos passado como argumento.
Import Static
A versão J2SE 5.0 incorporou o recurso import static, que permite
importar os métodos e atributos estáticos, permitindo utilizá-los sem o
prefixo de classe.
O código anterior pode ser reescrito, a partir da versão 5.0, conforme abaixo:
import java.util.Scanner;
import static java.lang.Math.*;
public class Teste {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
double angulo;
double seno;
System.out.print("Entre com o ângulo em graus: ");
angulo = entrada.nextDouble();
seno = sin(toRadians(ângulo));
System.out.println("Seno: " + seno);
}
}
Entrada de dados com Swing
O próximo exemplo apresenta uma solução para a soma de dois números
inteiros usando o pacote javax.swing de interface gráfica de Java.
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.*;
public class Adição {
public static void main(String[] args){
String s1, s2;
int num1, num2, soma;
s1 = JOptionPane.showInputDialog
("Entre com o 1º número");
s2 = JOptionPane.showInputDialog
("Entre com o 2º número");
num1 = Integer.parseInt(s1);
num2 = Integer.parseInt(s2);
soma = num1 + num2;
JOptionPane.showMessageDialog(null,"A soma é " + soma,
"Resultado", PLAIN_MESSAGE);
System.exit(0);
}
}
Esta versão do método showInputDialog da classe JOptionPane
requer quatro argumentos. O primeiro será null. O segundo é a mensagem
a ser exibida na caixa de diálogo. O terceiro é o texto a ser exibido na barra
de título. O quarto é um valor que indica o ícone do tipo de diálogo de
mensagem a ser exibido.

No programa Adição.java, trocando-se


o quarto argumento de JOptionPane para
INFORMATION_MESSAGE, temos a
seguinte saída para a caixa de diálogo:
O método parseInt(String) da classe Integer recebe como argumento
um valor String e retorna o valor convertido em inteiros. Se o argumento
não puder ser convertido, a máquina virtual Java lançará uma exceção do tipo
NumberFormatException.
public class ParseInt {
static int i;
public static void main(String[] args) {
i = Integer.parseInt("um");
System.out.println(i);
}
}

As classes empacotadoras Double e Float, dentre outras, possuem também


seus métodos parse, para a conversão do valor de um objeto String em tipos
primitivos float e double, respectivamente.
public class ParseDouble {
public static void main(String[] args) {
double d = Double.parseDouble("25.4");
System.out.println(d);
}
}
Autoboxing
A versão J2SE 5.0 incorporou o recurso denominado autoboxing, que
consiste na conversão automática entre tipos primitivos e seus wrappers
(classes empacotadoras).

public class AutoBoxing {


public static void main(String[] args) {
int meuInt = 25;
Integer meuInteger = meuInt;
System.out.printf("Integer: %d\tint: %d",
meuInteger, meuInt);
}
}
public class Unboxing {
public static void main(String[] args) {
Integer meuInteger = new Integer("12");
int meuInt = meuInteger;
System.out.println(meuInt);
}
}
Comando if / else
import javax.swing.JOptionPane;
public class ParImpar{
public static void main(String args[]) {
String s;
String resp = "O número ";
int i;
s = JOptionPane.showInputDialog(
"Entre com o\nnúmero inteiro");
i = Integer.parseInt(s);
if((i % 2) == 0)
resp = resp + s + " é par!";
else
resp = resp + s + " é ímpar!";
JOptionPane.showMessageDialog(null, resp,
"Par ou Ímpar",
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
O exemplo anterior contêm apenas uma única instrução associada as
cláusulas if e else. Para incluir várias instruções no corpo do
comando é necessário chave de abertura { e fechamento } de bloco.

Os operadores aritméticos em Java são representados da seguinte forma:


+(soma), -(subtração), *(multiplicação), /(divisão), %(resto da divisão inteira).
Os operadores relacionais em Java são representados da seguinte forma:
== (igual), != (diferente), >, <, >= e <=.

public class Modulo {


public static void main(String[] args) {
System.out.print(5.5 % 2);
}
}
O exemplo anterior faz uma comparação entre uma variável e um literal do
tipo primitivo int. Cuidado com expressões relacionais para comparar
objetos, ao invés de tipos primitivos.

import java.util.Scanner;
public class Teste {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
String string;
System.out.print("Digite Sim: ");
string = entrada.nextLine();
if(string == "Sim")
System.out.println("Iguais");
else
System.out.println("Diferentes");
}
}
O resultado impresso será Diferentes, uma vez que o objeto sim referencia
uma posição de memória diferente do literal Sim.
Para comparar se o conteúdo de dois objetos String são idênticos, uma
sugestão é empregar o método equals() da classe String.
import java.util.Scanner;
public class Teste {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
String string;
System.out.print("Digite Sim: ");
string = entrada.nextLine();
if(string == "Sim")
System.out.println("Iguais");
else
System.out.println("Diferentes");
}
}

Outros dois métodos da classe String são equalsIgnoreCase(), seme-


lhante a equals() e charAt(), que obtém o tipo primitivo char corres-
pondente a posição informada como argumento para o método.
Um applet Java simples
Um applet Java é um tipo especial de programa que é executado em um
navegador de páginas da World Wide Web.

import javax.swing.JApplet;
import java.awt.Graphics;
public class AloMundoApplet extends JApplet {
public void paint(Graphics g){
g.drawString("Alô, Mundo!",25,25);
}
}

Para executar o programa acima em um browser, é necessário um arquivo html


do tipo AloMundoApplet.html, que carrega a classe AloMundoApplet:

<html>
<applet code="AloMundoApplet.class" width=300 height=30>
</applet>
</html>
A palavra-chave extends indica que a
classe AloMundoApplet é uma subclasse
(ou classe derivada) de JApplet (chamada
superclasse ou classe básica).
A classe JApplet faz parte do pacote
javax.swing.

Herança: AloMundoApplet herda to-


dos os atributos (dados) e comportamen-
tos (métodos) da classe JApplet.

AloMundoApplet sobrescreve o método paint da classe JApplet. Este


método requer como parâmetro um objeto da classe Graphics, por convenção
nomeado por g, usado por paint para desenhar imagens no applet. A classe
Graphics pertence ao pacote java.awt.
O método drawString da classe Graphics desenha o string de caracteres
Alô, Mundo! no applet, a partir da posição 25 pixels na horizontal e 25 pixels,
na vertical. A origem das coordenadas é o canto superior esquerdo do applet.
Para executar um applet é necessário criar um arquivo de html.
O utilitário appletviewer permite carregar o arquivo html
e este, por sua vez, carrega o applet.
Para executá-lo, use appletviewer AloMundoApplet.html

Os componentes width e height do tag <applet> indicam respectiva-


mente a largura e a altura do applet, em pixels, no navegador.

Cuidado! Se você não definir os componentes de largura e altura


adequadamente em html, seu applet pode não ser desenhado correta-
mente na tela.

Se você estiver utilizando o editor de programas TextPad ou o ambiente de


desenvolvimento Eclipse, não será necessário criar o arquivo html, uma vez
que ele o fará automaticamente e executará o seu applet no applet
viewer da Sun.

Ao utilizar o ambiente integrado BlueJ, você poderá ainda escolher se deseja


executar o applet através do appletviewer ou do navegador instalado em
seu computador.
import javax.swing.*;
import java.awt.*;
public class AloMundo2Applet extends JApplet {
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawLine(15,10,210,10);
g.drawLine(15,30,210,30);
g.drawString("Alô, Mundo!",25,25);
}
}

O método setColor(Color.red) de-


fine a cor vermelha para a instância g da
classe Graphics. red é uma constante
da classe Color do pacote java.awt.

O método drawLine da classe Graphics


desenha linhas no applet. Os 4 argumentos
referem-se as coordenadas x e y do pixel
inicial e do pixel final da linha a ser
desenhada.
Estrutura de repetição while
public class Soma {
public static void main(String[] args) {
int i = 1;
int soma = 0;
while (i <= 100) {
soma = soma + i;
i = i + 1;
}
System.out.println(soma);
}
}

É necessário uma chave de abertura { e uma chave de fechamento } de bloco,


delimitando o conjunto de instruções associadas a estrutura de repetição.
import java.text.DecimalFormat;
import java.util.Scanner;
public class Teste {
public static void main(String args[]) {
Scanner entrada = new Scanner(System.in);
byte n = 0; //contador de notas
int nota, soma = 0;
double media;
System.out.print("Nota do aluno, -1 termina: ");
nota = entrada.nextInt();
while (nota != -1) {
soma = soma + nota;
n = (byte) (n + 1);
System.out.print("Nota do aluno, -1 termina: ");
nota = entrada.nextInt();
}
DecimalFormat df = new DecimalFormat("0.00");
if (n != 0) {
media = soma / n;
System.out.println("Media igual a " + df.format(media));
}
else
System.out.println("Nenhuma nota foi digitada");
}
}
O pacote java.text disponibiliza classes para formatação de valores e
expressões. A classe DecimalFormat é usada neste exemplo. O formato
0.00 especifica que a saída terá pelo menos um dígito à esquerda do ponto
decimal e exatamente dois dígitos à direita do ponto decimal. O método
format desta classe é usado para formatar uma variável do tipo primitivo
double.

Este exemplo apresenta um operador de coerção explícita (casting) para


converter o resultado da expressão (n + 1) em um valor do tipo byte. Esta
conversão é necessária porque o literal 1 é do tipo int o que implica que a
expressão retornará um valor também do tipo int.

public class CoercaoExplicita {


public static void main(String[] args) {
float f;
f = (float) 5.5;
System.out.print(Float.toString(f));
}
}
A partir de J2SE 5.0, a classe Formatter, através do método printf,
também pode ser usada para a formatação da saída em System.out.
import java.util.Scanner;
import static java.lang.Math.*;
public class Teste {
public static void main(String args[]){
double raio;
double area;
Scanner entrada = new Scanner(System.in);
System.out.print("Informe o raio do círculo: ");
raio = entrada.nextDouble();
area = PI * pow(raio, 2);
System.out.printf
("A area do circulo equivale a %6.2f", area);
}
}
O método estático Math.pow(base,exp) implementa a exponenciação.
Este método recebe dois argumentos double e retorna um valor double.
A tabela a seguir apresenta alguns códigos de formatação da classe Formatter
e usados em System.out.printf.
f número de ponto flutuante em formato fixo

e,E número de ponto flutuante em notação exponencial (formato científico)

g,G número em ponto flutuante em formato genérico (fixo para números


pequenos e exponencial para grandes)

d inteiros em decimal.

o número inteiro em octal

x,X Número inteiro em hexadecimal

s,S converte qualquer valor e apresenta em string

t,T formato para data e hora (com códigos adicionais para dia, mês, ano, etc.)
import java.util.Date;
public class Teste {
public static void main(String args[]){
System.out.printf("Hoje: %1$td de %1$tB de
%1$tY", new Date());
}
}

A classe Date instancia um objeto contendo a data e hora do sistema


operacional. Os caracteres de formatação d, B e Y exibem, respectivamente, o
dia, com 2 caracteres, o mês, por estenso, e o ano, com 4 dígitos. A tabela de
caracteres de formatação para data e hora contempla diversas outras
possibilidades de apresentação.

Hoje: 05 de Janeiro de 2005


Operadores de Atribuição
Java herda de C/C++ a característica dos operadores de atribuição, usados
para abreviar as expressões de atribuição.

Operador Expressão Equivalência


+= c += 7 c = c + 7
-= d -= 4 d = d – 4
*= e *= 5 e = e * 5
/= f /= 3 f = f / 3
%= g %= 2 g = g % 2

Também estão disponíveis em Java o operador unário de incremento ++ e o


operador unário de decremento --.

++ pré-fixado ++a
++ pós-fixado a++
-- pré-fixado --b
-- pós-fixado b--
public class Incremento {
public static void main(String args[]) {
int i;
i = 1;
System.out.println(i);
System.out.println(i++);
System.out.println(i);
i = 1;
System.out.println(i);
System.out.println(++i);
System.out.println(i);
}
}

Os operadores de incremento e decremento (++ e --)


1
1 incrementam e decrementam variáveis de tipo inteiro de
2 uma unidade. Na forma pré-fixada o operador modifica o
1 valor da variável antes que o valor seja usado na expressão.
2 Na forma pós-fixada o operador modifica o valor da variável
2 depois que o valor é usado na expressão onde está a variável.
Estrutura de repetição for
A estrutura for em Java é constituída de um valor inicial, um teste e um
passo, delimitados por ponto-e-vírgula.

import java.awt.Graphics;
import javax.swing.JApplet;
public class TesteFor extends JApplet {
public void paint(Graphics g) {
for (int i = 1; i <= 10; i++)
g.drawLine(10, 10, 250, i * 10);
}
}

Exemplo de Applet Java utilizando a estrutura de


repetição for. Observe que não foi necessário
definir chaves de abertura e fechamento para
delimitar um bloco de comandos associados ao
for, uma vez que só há uma linha de instrução.
Exemplo: programa para somar os números pares entre 0 e 100, usando laço for.

import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.*;
public class SomaPar {
public static void main(String args[]) {
int soma = 0;
for (int i = 2; i <= 100; i += 2)
soma += i;
JOptionPane.showMessageDialog(null,
"Valor da soma: " + soma,
"Soma dos pares até 100",
INFORMATION_MESSAGE);
System.exit(0);
}
}
Exemplo: programa para calcular a potência de 2 dos números inteiros de 1 a 10.
import javax.swing.*;
public class Potencia {
public static void main(String args[]) {
double potencia;
JTextArea area = new JTextArea();
area.setText("Numero\tQuadrado\n");
for (int i = 1; i <= 10; i++) {
potencia = Math.pow(i, 2);
area.append("" + i + '\t' + potencia + '\n');
}
JOptionPane.showMessageDialog(null, area,
"Quadrado dos numeros de 1 a 10",
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}

Java não possui um operador nativo para exponenciação.


Este exemplo utiliza a classe JTextArea do
pacote javax.swing. Esta classe define um
componente GUI capaz de armazenar e exibir
múltiplas linhas de texto.
Os métodos setText(String) e append
(String) permitem, respectivamente, atribuir
e acrescentar Strings na instância da classe
JTextArea.

public class TestaFor {


static int i;
public static void main(String[] args) {
for( ; i < 10; )
System.out.print(i++ + " ");
}
}
Uma estrutura for pode ser construída sem um ou mais de seus componentes.
Estrutura de seleção múltipla switch
import javax.swing.*;
public class Calculadora {
public static void main(String args[]) {
String s1, s2, s3;
float f1, f2, f3=0;
char c;
s1 = JOptionPane.showInputDialog("Primeiro operando: ");
s2 = JOptionPane.showInputDialog("Segundo operando: ");
s3 = JOptionPane.showInputDialog("Operador aritmético: ");
f1 = Float.parseFloat(s1);
f2 = Float.parseFloat(s2);
c = s3.charAt(0);
switch (c) {
case '+' : f3 = f1 + f2; break;
case '-' : f3 = f1 - f2; break;
case '*' :
case 'x' : f3 = f1 * f2; break;
case '/' : f3 = f2 / f1; break;
default:
}
JOptionPane.showMessageDialog(null, "Resultado: " + f3,
"calculadora", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
A variável ou expressão de controle da estrutura de seleção switch deve
assumir um valor inteiro, ou seja, do tipo byte, short, int ou char.
O comando break é necessário para impedir que a execução do programa
continue nas cláusulas case seguintes.
A cláusula default não é obrigatória.
O método charAt() da classe String permite selecionar o caracter cuja
posição é especificada como parâmetro. A posição inicial corresponde a 0.
Estrutura de repetição do/while
A estrutura do/while testa a condição de continuação do laço depois do
corpo do laço ser executado. Portanto, o corpo do laço sempre é executado pelo
menos uma vez.

public class TestaDoWhile {


public static void main(String args[]) {
byte i;
do {
i = (byte) (Math.random() * 10);
System.out.print(i + " ");
} while (i != 0);
}
}
O método random() da classe Math gera um número aleatório do tipo
double compreendido entre 0, inclusive, e 1, exclusive. Não é necessário o
comando import para a classe Math, que pertence ao pacote java.lang.
Operadores Lógicos
Java possui vários operadores lógicos que podem ser utilizados para obter
combinações lógicas do tipo AND, OR, XOR e NOT.

Para combinações AND, os operadores lógicos & e && são utilizados. Se & for
empregado, as expressões em ambos os lados são avaliadas.
Para combinações OR, os operadores lógicos | e || são utilizados. A combina-
ção XOR possui o operador lógico ^. Isto resulta em um valor true se a
expressão contiver um valor true e um false. A combinação NOT utiliza o
operador lógico !.
public class TestaOR1 {
public static void main(String args[]) {
int i = 2;
int j = 3;
if((j == i++) | (i < ++j))
System.out.println("i = " + i + " j = " + j);
}
}
public class TestaOR2 {
public static void main(String args[]) {
int i = 2;
int j = 3;
if((j == i++) || (i < ++j))
System.out.println("i = " + i + " j = " + j);
}
}
Os dois exemplos retornam o mesmo resultado. Na prática, para avaliação de
expressões lógicas, recomenda-se empregar os operadores && e ||.
public class TestaXOR {
public static void main(String args[]) {
int i = 2;
int j = 3;
if((j == i++) ^ (i < ++j))
System.out.println("XOR OK");
else
System.out.println("XOR not OK");
}
}
Métodos
A maioria dos programas de computador usados profissionalmente são muito
mais extensos do que os exemplos apresentados. A abordagem para grandes
programas é construí-los a partir de pequenas partes ou módulos.
Os módulos em Java são chamados métodos e classes. Os programas são
escritos combinando novos métodos e classes do usuário com métodos e classes
disponíveis na Java API e também com métodos e classes já disponibilizados
por outros programadores.

Cada método deve se limitar a executar uma única e bem definida


tarefa e o nome do método deve efetivamente expressar isto.
import java.util.Scanner;
public class NomeUsuario {
public static void main(String args[]) {
Scanner ent = new Scanner(System.in);
System.out.print("Digite seu nome: ");
String nome = ent.nextLine();
System.out.println("Olá, %s", nome);
}
}
Neste exemplo, a classe NomeUsuario, definida pelo programador, invoca o
método readLine da classe Console. A definição desta classe encontra-se no
pacote corejava. Esta classe não faz parte da Java API. Foi escrita por
outros programadores Java e disponibilizada para uso em [Horstmann, 2001].

A classe do usuário Saudação abaixo, utiliza um método definido pelo


usuário chamado imprime. Este método possui um argumento do tipo String
e não retorna nenhum valor. É um método do tipo void.
import java.util.Scanner;
public class Saudação {
public static void main(String args[]) {
Scanner entrada = new Scanner(System.in);
String nome = entrada.nextLine();
imprime(nome);
}
static void imprime(String s){
System.out.printf("Olá, %s", s);
}
}
public class QuadInt {
public static void main(String args[]) {
int i;
for(int x = 1; x <= 10; x++) {
i = quadrado(x);
System.out.printf
("Quadrado de %02d: %03d\n", x, i);
}
}
//Método quadrado
public static int quadrado(int y){
return (int) Math.pow(y, 2);
}
}

A classe do usuário QuadInt utiliza um método definido pelo usuário


chamado quadrado. Este método possui um argumento do tipo int e retorna
um valor também do tipo int.
import javax.swing.*;
import java.awt.*;
public class Celsius extends JApplet {
double c;
double f;
public void init() {
String sc;
sc = JOptionPane.showInputDialog
("Entre com a temperatura\nem graus Celsius");
c = Double.parseDouble(sc);
f = ( 9 * c ) / 5 + 32;
}
public void paint(Graphics g) {
g.drawString("A temperatura " + c +
"°C equivale a " + f + "°F", 25, 25);
}
}

A classe do usuário Celsius sobrescreve os métodos init() e paint()


de JApplet. Em um applet, o método paint() deve ser usado unicamente
para formatar uma saída utilizando métodos da classe Graphics.
Regras de Escopo
Todos os exemplos vistos até aqui utilizam identificadores para nomes de
variáveis e de objetos. Identificadores também são usados para nomear classes
e métodos definidos pelo usuário.

Cada identificador tem como atributos a duração e o escopo. A duração ou tempo


de vida é o período durante o qual o identificador existe na memória. O escopo diz
respeito ao local onde o identificador pode ser referenciado no programa.
public class Escopo {
int x = 1;
public static void main(String args[]) {
Escopo escopo = new Escopo();
int x = 5;
System.out.println("x vale " + x);
escopo.metodoA();
escopo.metodoB();
escopo.metodoA();
escopo.metodoB();
System.out.println("x vale " + x);
}
public void metodoA() {
int x = 25;
System.out.println("x em A vale " + x);
x++;
System.out.println("x em A vale " + x);
}
public void metodoB() {
System.out.println("x em B vale " + x);
x *= 10;
System.out.println("x em B vale " + x);
}
}
x vale 5 Uma variável local só é visível no método onde foi
x em A vale 25 criada, este é o seu escopo. Uma variável de instância é
x em A vale 26 visível em todo o contexto da instância da classe, este é o
x em B vale 1
x em B vale 10 seu escopo. Uma variável de classe é visível por todas
x em A vale 25 as instâncias da classe.
x em A vale 26
x em B vale 10 Duração: uma variável local existe apenas durante a
x em B vale 100 execução do método. Uma variável de instância existe
x vale 5 durante a existência da instância da classe.
Sobrecarga de Métodos
Java permite que vários métodos com o mesmo nome sejam definidos, contanto
que tais métodos tenham diferentes conjuntos de parâmetros. Esta característica é
chamada sobrecarga de métodos.

public class Sobreposicao {


public static void main(String args[]) {
Sobreposicao sobre = new Sobreposicao();
System.out.println("Quadrado de 3: " +
sobre.quadrado(3));
System.out.println("Quadrado de 3.5: " +
sobre.quadrado(3.5));
}
public int quadrado(int i) {
return i*i;
}
public double quadrado(double f) {
return f*f;
}
}
Métodos sobrecarregados são distinguidos por sua assinatura, ou
seja, uma combinação do nome do método e seu tipo de parâmetro.

public class Area {


public static void main(String args[]) {
Area area = new Area();
System.out.println("Área quadrado.:" + area.area(3));
System.out.println("Área retângulo:" + area.area(3,4));
System.out.println("Área cubo.....:" +
area.area(3,2,3));
}
public int area(int i) {
return i * i;
}
public int area(int i, int j) {
return i * j;
}
public int area(int i, int j, int k) {
return i * j * k;
}
}
Arrays
Um array é um grupo de posições contíguas na memória que possuem o
mesmo nome e o mesmo tipo. Em java, os arrays são tratados como objetos
e, portanto, devem ser instanciados com o comando new.

int[] array; //declara o array


int array[]; //declara o array
array = new int[12]; //instancia o array

Que também pode ser escrito na forma:

int[] array = new int[12]; // ou...


int array[] = new int[12];

Quando um array é instanciado, seus elementos são automaticamente inicializa-


dos com zero para tipos de dados numéricos e null para referências a objetos.
Em Java, o primeiro elemento de um array é sempre referenciado pelo índice 0.
O array array acima, poderá ser referenciado pelos índices de 0 a 11.
import javax.swing.*;
public class Array {
public static void main(String args[]) {
String saida = "";
int[] i;
i = new int[10];
saida += "Índice - Valor\n";
for (int j = 0; j < i.length; j++) {
i[j] = (int) (Math.random() * 10);
saida += j + " - " + i[j] + "\n";
}
JOptionPane.showMessageDialog(null, saida,
"Inicializando um array",
JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
}
A variável de instância length é a forma adequada de "percorrer" os
elementos de um array em Java.
Os arrays, ao serem instanciados, sempre alocam valores iniciais para os seus
elementos, mesmo que declarados como variáveis locais.
public class TestaArray {
public static void main(String[] args) {
byte[] array;
array = new byte[5];
for(byte i = 0; i < array.length; i++)
System.out.println(array[i]);
}
}

Os elementos de um array podem ser alocados e inicializados na sua própria


declaração. O exemplo abaixo especifica um array instanciado implicitamente
com 4 elementos.

String nomes[] = {"Ana", "José", "Maria", "Rita"};

Se você tentar acessar um elemento cujo índice seja inexistente, lança-


rá uma exceção do tipo ArrayIndexOutOfBoundsException.
Passando arrays para métodos
Existem duas maneiras de se passar argumentos para métodos: por valor e por
referência. Em java, variáveis de tipo primitivo são sempre passadas por valor
e objetos, incluindo arrays, são sempre passados por referência.
public class Parametro {
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
System.out.println("Valores originais do array:");
for(int i = 0; i < array.length; i++)
System.out.print(array[i] + " ");
Parametro p = new Parametro();
p.modificaArray(array);
System.out.println("\nValores modificados no metodo:");
for(int i = 0; i< array.length; i++)
System.out.print(array[i] + " ");
System.out.println
("\nValor de a[3] antes da passagem: " + array[3]);
p.modificaElemento(array[3]);
System.out.println
("Valor de a[3] depois da passagem: " + array[3]);
}
public void modificaArray(int[] a) {
for(int j = 0; j < a.length; j++)
a[j] *= 2;
}
public void modificaElemento(int e) {
e *= 2;
}
}

Valores originais do array:


1 2 3 4 5
Valores modificados no metodo:
2 4 6 8 10
Valor de a[3] antes da passagem: 8
Valor de a[3] depois da passagem: 8

Para passar um array como argumento para um método, basta especi-


ficar o nome da instância, sem colchetes.
Arrays multidimensionais
Arrays com dois índices são utilizados normalmente para representar tabelas de
valores consistindo de informações organizadas em linhas e colunas.

Em java, um array bidimensional, do tipo m[2][2], pode ser declarado e


inicializado com:

int[][] m = {{1, 2}, {3, 4}};


O exemplo abaixo apresenta algumas das potencialidades de arrays em Java:
public class Arrays {
public static void main(String[] args) {
String[][] s1 = new String[2][2];
s1[0][0] = "Rita"; Rita
String[] s2 = {"Julia", "Augusto"}; null
s1[1] = s2; Julia
for(int i = 0; i < s1.length; i++) Augusto
for(int j = 0; j < s1[i].length; j++)
System.out.println(s1[i][j]);
}
}
Estrutura for each
J2SE 5.0 apresenta a estrutura for each, capaz de fazer a iteração de
arrays (e também outras estruturas de dados avançadas de Java).

public class TestaForEach {


public static void main(String args[]) {
int[] array = new int[10];
for(int i : array) {
array[i] = (int) (Math.random() * 10);
System.out.printf("%02d\n",array[i]);
}
}
}

A nova estrutura for each torna a iteração de arrays mais simples e


elegante, e deve ser empregada sempre que possível pelo programador Java.
Parâmetros na linha de comando
Os argumentos digitados na linha de comando são passados para o método
main() da classe invocada por meio de um vetor de Strings. Por exemplo, se
for executada a linha de comando java Teste um dois três o método
main() da classe Teste receberá o seguinte vetor de Strings:

args[0] = "um"
args[1] = "dois"
args[2] = "três"
O espaço serve como separador de argumentos. Se for necessário tratar uma
cadeia de caracteres com espaço como um único argumento será preciso delimitá-
la com aspas duplas. Assim, o comando java teste um "dois três"
resulta no seguinte vetor:
args[0] = "um"
args[1] = "dois três"
O exemplo a seguir imprime a soma dos argumentos passados na linha de
comando.
public class Argumentos {
public static void main(String[] args) {
int soma = 0;
for(int i = 0; i < args.length; i++)
soma += Integer.parseInt(args[i]);
System.out.print("Soma dos argumentos: ");
System.out.println(soma);
}
}

Para uma entrada do tipo java Argumentos 1 2 3 4 a saída será:

Soma dos argumentos: 10


Strings
Em Java, uma cadeia de caracteres é sempre um objeto da classe java.lang.
String. Não existe um tipo primitivo para armazenar cadeias de caracteres.
String s1;
s1 = new String("abcdef");
String s2 = "ghijkl";
É possível instanciar um objeto da classe String usando o
operador new ou atribuindo o valor diretamente, conforme acima.

public class Strings {


public static void main(String[] args) {
String s1 = new String("abcdef");
String s2 = s1;
if(s1 == s2)
System.out.print("s1 igual a s2");
else
System.out.print("s1 diferente de s2");
}
}
No exemplo anterior, a referência para a instância s2 é apontada para o mesmo
endereço de memória da instância s1, logo a saída da aplicação será:
s1 igual a s2

public class Strings2 {


public static void main(String[] args) {
String s1 = new String("abcdef");
String s2 = "abcdef";
if(s1 == s2)
System.out.print("s1 igual a s2");
else
System.out.print("s1 diferente de s2");
}
}
s1 diferente de s2

Neste caso, a nova instância s2 criada referencia um endereço de memória


diferente daquele apontado pela instância s1. Trata-se de objetos distintos!
Uma instância da classe String é um objeto imutável.
public class Strings3 {
public static void main(String[] args) {
String s1 = "abc";
String s2 = s1;
s1 = s1.concat("def");
if(s1 == s2)
System.out.print("s1 igual a s2");
else
System.out.print("s1 diferente de s2");
}
}

s1 diferente de s2

Sendo um objeto String imutável, a linha s1 = s1.concat("def"); irá


passar a referência ao objeto s1 para um outro endereço de memória. Assim, as
instâncias s1 e s2 não mais referenciam à mesma posição de memória.
public class Strings4 {
public static void main(String[] args) {
for(int i = 0; i < args.length; i++)
System.out.print(args[i].length());
}
}

Para uma execução do tipo java Strings4 Clube Atlético Mineiro,


a saída é:
587

A classe String possui o método length(), que retorna o tamanho da


cadeia de caracteres. Lembre-se que arrays possuem um atributo length que
contém o tamanho do array.
Como regra geral, os métodos que modificam o conteúdo de
instâncias da classe String, como concat(), visto na página
anterior, passam a referenciar para uma nova posição de memória.
Classe StringBuffer
A classe StringBuffer é uma alternativa mais adequada para a manipulação
de cadeias de caracteres quando for necessário fazer muitas alterações nos
valores armazenados.
Ao contrário da classe String, objetos da classe StringBuffer podem ser
alterados sem que a MVJ modifique a referência na memória.

public class TestaStringBuffer {


public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer("abc");
StringBuffer sb2 = sb1;
sb1 = sb1.append("def");
if(sb1 == sb2)
System.out.print("sb1 igual a sb2");
else
System.out.print("sb1 diferente de sb2");
}
}
sb1 igual a sb2
O método append() da classe StringBuffer altera o valor da instância
sb1, mantendo a referência a mesma posição de memória. Assim, sb2 e sb1
continuam apontando para o mesmo endereço.
Não é possível fazer uma conversão direta de String para StringBuffer,
conforme visto abaixo:
StringBuffer sb = new StringBuffer();
String s = "abcdef";
sb = s;
O método append() da classe StringBuffer pode ser usado para este fim:
StringBuffer sb = new StringBuffer();
String s = "abcdef";
sb.append(s);
Para converter um objeto StringBuffer em String, deve empregar o
método toString():
s = sb.toString();
Enumerated Types
J2SE 5.0 incorpora (finalmente!) o recurso de tipos enumerados, comum em
C/C++. Um enum é um tipo especial de classe, definida em java.lang.Enum.

public class TestaEnums {


enum Times {ATLÉTICO, VASCO, GRÊMIO, CORITIBA,
BAHIA};
public static void main(String[] args) {
for(Times time : Times.values())
System.out.printf("%s\n", time);
}
}
ATLÉTICO
VASCO
GRÊMIO
CORITIBA
BAHIA
Cada identificador (ex.: Times.ATLÉTICO) é um objeto da classe Enum.
É possível percorrer parte de um enum usando o método java.util.
EnumSet.range, conforme no exemplo que se segue.
import java.util.EnumSet;
public class Teste {
enum Semana {DOMINGO, SEGUNDA, TERÇA, QUARTA,
QUINTA, SEXTA, SÁBADO};
public static void main(String[] args){
for(Semana dia : EnumSet.range
(Semana.SEGUNDA, Semana.SEXTA))
System.out.println(dia);
}
}

Uma outra situação recomendada para o uso de enums é em comandos de


seleção múltipla switch, conforme exemplo que se segue.
import java.util.Scanner;
public class Teste {
enum Operador {MAIS, MENOS, VEZES, DIVIDIDO_POR};
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
double y = Double.parseDouble(args[1]);
double res = 0;
for (Operador op : Operador.values()) {
switch(op) {
case MAIS: res = x + y; break;
case MENOS: res = x - y;
break;
case VEZES: res = x * y;
break;
case DIVIDIDO_POR: res = x / y;
}
System.out.printf("%2.2f %s %.2f =
%2.2f\n", x, op, y, res);
}
Programação baseada em objetos
Em linguagens como Pascal e C, a programação é orientada à ação. Em Java, a
programação é orientada a objetos.

Os programadores Java concentram-se em escrever seus próprios tipos definidos


pelo usuário, chamados classes. Cada classe contém dados (atributos) bem como
o conjunto de métodos que manipulam os dados.
class Produto extends Object {
public int codigo;
public String nome;
public int quantidade;
public double preco;
public Produto(int c, String n, int q, double p){
codigo = c;
nome = n;
quantidade = q;
preco = p;
}
}
O exemplo anterior mostra a declaração de uma classe do usuário chamada
Produto que contém quatro atributos: codigo, nome, quantidade e
preco.
public class Produto extends Object indica que a classe do
usuário Produto estende a classe Object (do pacote Java.lang).

Na realidade, o usuário nunca cria uma classe a partir do zero. Neste exemplo, a
classe Produto herda os atributos (dados) e comportamentos (métodos) da
classe Object.
A palavra-chave public é um modificadores de acesso aos membros da classe.
O modificador public indica que o acesso é permitido a outras classes.
A classe Produto possui um método chamado Produto. Este é o método
construtor da classe. Um construtor é um método especial que inicializa as
variáveis de instância de um objeto de classe.

O método construtor somente pode ser invocado em um comando


new, para instanciar um novo objeto da classe.
Utilize agora o BlueJ para instanciar alguns objetos da classe Produto.

Você pode criar uma nova


instância da classe
Produto clicando com o
botão direito do mouse
sobre o ícone da classe.

Você pode acessar os


atributos de cada um dos
objetos dando um duplo
clique sobre o ícone das
instâncias.
Inclua uma nova classe do usuário TestaProd em seu projeto no BlueJ.
class TestaProd {
public static void main(String a[]){
String s = " ";
Produto produto;
produto = new Produto(10, "Sabonete", 12, 1.20);

System.out.println(produto.codigo + s +
produto.nome);
System.out.println(produto.quantidade + s +
produto.preco);
produto.quantidade = 100;
System.out.println(produto.quantidade + s +
produto.preco);
produto.preco *= 1.10;
System.out.println(produto.quantidade + s +
produto.preco);
}
}
A classe TestaProd declara uma variável produto do tipo Produto e a
instancia, através do comando new, que invoca o método construtor.
A linha tracejada indica
que a classe
TestaProd usa
métodos e/ou atributos
da classe Produto.

Atente para o importante fato de que a classe TestaProd só conseguiu acessar


diretamente os atributos da classe Produto porque estes foram declarados
como public. O que aconteceria se eles fossem declarados como private?
class Empregado {
private String nome;
private double salario;
//Método Construtor
public Empregado(String n, double s) {
nome = n;
salario = s;
}
public void print() {
System.out.println(nome + " " + salario);
}
public void aumentaSalario(double percentual) {
salario *= 1 + percentual / 100;
}
}

Os modificadores de acesso tem por objetivo definir a visibilidade de um


membro de uma classe (atributo ou método) em relação à outras classes. O
modificador private permite ao acesso apenas aos membros da própria
classe.
public class TestaEmpregado {
public static void main(String args[]) {
Empregado[] empregado = new Empregado[3];
empregado[0] = new Empregado("Rita", 1000);
empregado[1] = new Empregado("Maria", 1200);
empregado[2] = new Empregado("Julia", 1500);
for(int i = 0; i < empregado.length; i++) {
empregado[i].aumentaSalario(5);
empregado[i].print();
}
}
}

Rita 1050.0
Maria 1260.0
Julia 1575.0

Observe que empregado é um array de instâncias da classe


Empregado, contendo 3 objetos desta classe.
Os modificadores de acesso disponíveis são apresentados na tabela abaixo:
Modificador Descrição
default Somente classes do mesmo pacote possuem acesso
public Todos possuem acesso
private Apenas os membros da classe
protected Idêntico a default, com uma exceção:

O modificador protected, além de permitir o acesso a membros do mesmo


pacote, permite o acesso a partir de subclasses, ainda que em outros pacotes.

O modificador default é assumido, caso nenhum dos demais


modificadores seja especificado. Não existe uma palavra reservada
default em Java.
Sobrecarga de construtores
Os métodos de uma classe podem ser sobrecarregados. Para sobrecarregar um
método construtor, simplesmente forneça uma definição separada de cada um
dos métodos sobrecarregados. Tais métodos devem possuir listas de parâme-
tros diferentes.

class Empregado {
private String nome;
private double salario;
public Empregado(String n, double s) {
nome = n;
salario = s;
}
public Empregado(String n) {
nome = n;
salario = 500;
}
Métodos set e get
As variáveis de instância definidas como privadas só podem ser manipuladas
através de métodos da própria classe. Todavia, as classes podem fornecer
métodos public para permitir a clientes da classe atribuir valores (set) ou
obter (get) variáveis de instância declarados como private.
public class Cliente {
private String nome;
private String endereco;
private String telefone;
public Cliente(String n, String e, String t) {
nome = n;
endereco = e;
telefone = t;
}
public void setNome(String n) {nome = n;}
public void setEndereco(String e) {endereco = e;}
public void setTelefone(String t) {telefone = t;}
public String getNome() {return nome;}
public String getEndereco() {return endereco;}
public String getTelefone() {return telefone;}
}
public class TestaCliente {
public static void main(String args[]) {
Cliente fulano = new Cliente
("Fulano", "Rua Halfeld", "3213-5000");
Cliente beltrano = new Cliente
("Beltrano", "Rua Marechal", "3224-1000");
System.out.println("Cliente 1: " + fulano.getNome()+
", " + fulano.getEndereco() + ", " +
fulano.getTelefone() + "\n");
System.out.println("Cliente 2: " + beltrano.getNome() +
", "+ beltrano.getEndereco() + ", " +
beltrano.getTelefone() + "\n");
fulano.setNome("Ciclano");
beltrano.setEndereco("Rua Sao Joao");
fulano.setTelefone(beltrano.getTelefone());
System.out.println("Cliente 1: " + fulano.getNome()+
", " + fulano.getEndereco() + ", " +
fulano.getTelefone() + "\n");
System.out.println("Cliente 2: " + beltrano.getNome() +
", "+ beltrano.getEndereco() + ", " +
beltrano.getTelefone() + "\n");
}
}
Cliente 1: Fulano, Rua Halfeld, 3213-5000
Cliente 2: Beltrano, Rua Marechal, 3224-1000
Cliente 1: Ciclano, Rua Halfeld, 3224-1000
Cliente 2: Beltrano, Rua Sao Joao, 3224-1000

Os nomes dos métodos de para atribuir e obter valores das variáveis


de instância das classes não tem que ser necessariamente set e
get, mas esta é uma boa prática de programação em Java.
Varargs
J2SE 5.0 apresenta um novo recurso denominado varargs, que permite passar
um número variável de argumentos a um método, sem a necessidade de
encapsulá-lo em um array, por exemplo.

class VarOla {
public static void printSaudação(String... nomes) {
for(String n : nomes) {
System.out.println("Olá " + n + ". ");
}
}
public static void main(String[] args) {
printSaudação("Wander", "Rita", "Julia","Augusto");
}
}

A declaração de um argumento como varargs é denotada pelo seu tipo seguido


de reticências (...) e o nome.
Em tempo de compilação, um varargs é convertido para um array. Isto explica
porque o código abaixo executa sem problemas, alterando a clássica assinatura
do método main.

class VarOla {
public static void printSaudação(String... nomes) {
for(String n : nomes) {
System.out.println("Olá " + n + ". ");
}
}
public static void main(String... args) {
printSaudação(args);
}
}
A Sun, inclusive, aconselha o uso de varargs em lugar de arrays na assinatura
do método main.
Sobrecarga com Varargs
O exemplo a seguir ilustra o comportamento do compilador Java no caso de
haver métodos sobrecarregados com e sem varargs disputando a execução.

public class QualMétodo {


QualMétodo(Integer... size) {
System.out.println("Versão com varargs");
}
QualMétodo(int i, int j) {
System.out.println("Versão com tipo int");
}
QualMétodo(Integer i, Integer j) {
System.out.println("Versão com Integer");
}
public static void main(String[] args) {
System.out.println("Chamada com tipo int");
new QualMétodo(2, 3);
System.out.println("Chamada com Integer");
new QualMétodo(new Integer(2), new Integer(3));
}
}
Chamada com tipo int
Versão com tipo int
Chamada com Integer
Versão com Integer

Observa-se que a chamada com varargs não tem precedência, quando da


existência de métodos com assinatura igual à chamada. Ainda usando o exemplo
anterior, somente será chamado o método com varargs em situações como a
apresentada abaixo, onde não há correspondência com um método específico.

public static void main(String[] args) {


System.out.println("Chamada com tipo int");
new QualMétodo(2, 3, 4);
}

Chamada com tipo int


Versão com varargs
Referência this
Em algumas situações é necessário referenciar o próprio objeto corrente. Por
essa razão todo objeto possui um atributo especial identificado por this que é
uma referência para o próprio objeto. O exemplo abaixo mostra um uso típico do
atributo this. Ele mostra um método cujo parâmetro formal possui o mesmo
nome de um atributo de instância. Para distingui-los é necessário qualificar o
atributo da instância com o atributo this.

import java.awt.Color;
public class ObjGeo {
private Color cor;
private int larg;
private int alt;
public ObjGeo (Color cor, int larg, int alt) {
this.cor = cor; this.larg = larg; this.alt =
alt;
}
public Color getCor() {return cor;}
public int getLarg() {return larg;}
public int getAlt() {return alt;}
import java.awt.Color;
public class TestaObjGeo {
public static void main(String args[]) {
ObjGeo obj = new ObjGeo(Color.red,4,8);
System.out.println("Cor: " + obj.getCor());
System.out.println("Largura: " + obj.getLarg());
System.out.println("Altura: " + obj.getAlt());
}
}

Cor: java.awt.Color[r=255,g=0,b=0]
Largura: 4
Altura: 8

A classe Color, do pacote java.awt, é responsável pela manipulação das


cores em Java. A Color.red define a cor vermelha para a instância obj do
objeto ObjGeo.
Modificador static
Cada instância de um objeto tem sua própria cópia de todas as variáveis de
instância. Porém, em certas situações, pode ser útil usar uma variável de classe,
estática, cujo valor é compartilhado por todas as instâncias da classe.

public class Socio {


private String nome;
private String endereco;
private static int numSocios;
public Socio (String n, String e) {
nome = n;
endereco = e;
numSocios++;
}
public String getNome() {return nome;}
public String getEndereco() {return endereco;}
public static int getNumSocios() {return numSocios;}
}
public class TestaSocio {
public static void main(String args[]) {
Socio s1 = new Socio("Pedro","Rua Santa Rita");
Socio s2 = new Socio("Paulo","Av. dos Andradas");
Socio s3 = new Socio("Jose","Av. Rio Branco");
System.out.println("Socios do clube:\n"+
s1.getNome() + ", " + s1.getEndereco() +
"\n" + s2.getNome() + ", " + s2.getEndereco() +
"\n" + s3.getNome() + ", " + s3.getEndereco());
System.out.println("Numero de socios: "+
Socio.getNumSocios());
}
}

Socios do clube:
Pedro, Rua Santa Rita
Paulo, Av. dos Andradas
Jose, Av. Rio Branco
Numero de socios: 3
Pacotes
Pacotes é a solução proposta pela Sun para reunir interfaces e classes
relacionadas formando uma biblioteca. Esta organização evita a colisão de
nomes de classes. Veja a extensão do problema: sendo Java uma linguagem para
atuar na internet, como evitar que classes obtidas por download não tenham os
mesmos nomes de classes já existentes na máquina?!

Toda classe pertence a um pacote. Apenas o pacote default, que refere-se as


classes do diretório corrente e o pacote java.lang, que agrupa as classes do
núcleo básico de Java, não precisam ser importados com o comando import.
As classes de um pacote devem colocadas em um diretório obedecendo a estru-
tura do nome do pacote, a partir de algum diretório presente na variável de
ambiente classpath.
Suponha que eu tenha criado um conjunto de classes de objetos geométricos.
Poderia criar um pacote chamado wander para colocar as classes.
package wander;
public class ObjGeo {
Color cor;
int x;
int y;
public ObjGeo (Color cor, int x, int y) {
this.cor = cor;
this.x = x;
this.y = y;
}
}
A variável de ambiente classpath poderia ser definida como:
set classpath = .;c:\...\jdk1.4.1\lib;c:\java;
O arquivo ObjGeo.class deve ser colocado no diretório:
c:\java\wander

Os atributos da classe ObjGeo foram definidos com o modificador de acesso


default. Isto significa que somente classes do pacote wander poderão
acessar estes atributos.
import wander.ObjGeo;
import java.awt.Color;
public class TestaObjGeo {
public static void main(String[] args) {
ObjGeo obj = new ObjGeo(Color.CYAN, 10, 10);
System.out.println(obj.cor);
System.out.println(obj.x);
System.out.println(obj.y);
}
}

Este programa apresentará erro de compilação, informando que os atributos


obj.cor, obj.x e obj.y não são visíveis, mesmo declarando o comando
import para importar a classe ObjGeo do pacote wander.
Lembre-se, atributos definidos com o modificador de acesso
default só são visíveis por classes dentro do mesmo pacote. A
classe TestaObjeto não foi definida dentro do pacote wander.
Redefinição da classe TestaObjGeo dentro do pacote wander:
package wander;
import java.awt.Color;
public class TestaObjGeo {
public static void main(String[] args) {
ObjGeo obj = new ObjGeo(Color.CYAN, 10, 10);
System.out.println(obj.cor);
System.out.println(obj.x);
System.out.println(obj.y);
}
}

O programa compila normalmente. Qual seria o comportamento do compilador


se os atributos da classe ObjGeo fossem definidos com o modificador de acesso
protected? E com private?
Herança
Herança é um mecanismo que permite que características comuns a diversas
classes sejam especificadas em uma classe base, ou superclasse. A partir desta
superclasse, outras classes podem ser especificadas. Cada classe derivada ou
subclasse apresenta as características (atributos e métodos) da classe base e
acrescenta a elas o que for definido de particularidade na subclasse.

Por exemplo, podemos considerar que um objeto Circulo, Triangulo ou


Retangulo é também um objeto FormaGeometrica.
Neste contexto, FormaGeometrica é chamada uma superclasse e a classe
Circulo é uma subclasse. Também é válido dizer que a classe Triangulo
herda atributos e/ou métodos de FormaGeometrica.

Para especificar que uma classe é subclasse de uma outra classe,


Java emprega a palavra reservada extends.
import java.awt.Color;
public class FormaGeo {
protected Color cor;
protected int x, y;
public FormaGeo(Color c, int x, int y) {
cor = C;
this.x = x;
this.y = y;
}
public Color getCor() {
return cor;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
import java.awt.Color;
public class Circulo extends FormaGeo {
protected double raio;
public Circulo(Color c, int x, int y, int r) {
super(c, x, y);
raio = r;
}
public double area() {
return Math.PI * Math.pow(raio, 2);
}
}

A instrução super() é uma chamada explícita ao construtor da superclasse.


Esta instrução é necessária para passar à superclasse os parâmetros recebidos
pelo construtor da subclasse. Observe que a subclasse não define atributos
correspondentes a estes atributos, que pertencem a superclasse.

É um erro de sintaxe se uma chamada super por uma subclasse


não for a primeira instrução no construtor da subclasse.
A linha contínua indica
que a classe Circulo
herda métodos e/ou
atributos da classe
Forma.

Observe que você pode criar objetos (instâncias) da classe Forma e também da
classe Circulo, utilizando o BlueJ.
import java.awt.Color;
public class TestaHeranca {
public static void main(String[] args) {
FormaGeo fg = new FormaGeo(Color.red, 4, 8);
Circulo circ = new Circul
(Color.blue, 2, 5, 10);
System.out.println
("Cor da Forma Geometrica: " + fg.getCor());
System.out.println
("Cor do Circulo: " + circ.getCor());
System.out.println
("Area do Circulo: " + circ.area());
System.out.println
("Coordenada X da Forma Geometrica: " +
fg.getX());
System.out.println("Coordenada Y do Circulo: " +
circ.getX());
}
}
Outro exemplo utilizando herança:
public class Ponto extends Object {
protected int x;
protected int y;
public Ponto(int a, int b) {
x = a;
y = b;
System.out.println("Ponto - " + this);
}
public String toString() {
return "Centro: [" + x + ", " + y + "]";
}
}

O método toString() é definido originalmente na classe Object. Permite


converter uma representação interna do objeto em uma string que pode ser
apresentada ao usuário. Aqui, o método está sendo sobrescrito para formatar
mais adequadamente os atributos da classe Ponto.
public class Circulo extends Ponto {
protected double raio;
public Circulo(double r, int a, int b) {
super(a, b);
raio = r;
System.out.println("Circulo - " + this);
}
public String toString() {
return super.toString() + ", Raio: " + raio;
}
}
public class TestaHeranca {
public static void main(String[] args) {
Ponto pt;
Circulo circ1;
Circulo circ2;
pt = new Ponto(10, 5);
circ1 = new Circulo(4.5, 72, 29);
circ2 = new Circulo(10, 5, 5);
}
}
Ponto - Centro: [10, 6]
Ponto - Centro: [72, 29], Raio: 0.0
Circulo - Centro: [72, 29], Raio: 4.5
Ponto - Centro: [5, 5], Raio: 0.0
Circulo - Centro: [5, 5], Raio: 10.0
As classes Ponto e Circulo apresentam uma nova utilização para this,
usado para invocar implicitamente o método toString().

O objeto corrente, referenciado por this, nas instâncias da classe


Circulo, é sempre desta classe. O método toString() chamado,
neste caso, é o da classe Circulo.
Classes abstratas
Uma classe abstrata não pode ser instanciada, ou seja, não há objetos que
possam ser construídos diretamente de sua definição. Por exemplo, a compilação
do seguinte trecho de código dará erro:

abstract class ClasseAbstrata {


public static void main(String[] args) {
ClasseAbstrata ca = new ClasseAbstrata();
}
}
Somente classes concretas, ou seja, que não foram definidas como abstratas, é
que podem ser instanciadas.
As classes abstratas definem um conjunto de funcionalidades das quais pelo
menos uma está especificada mas não está definida — ou seja, contém pelo
menos um método abstrato.

abstract class ClasseAbstrata {


public abstract int metodo();
}
Um método abstrato não cria uma definição, mas apenas uma declaração de um
método que deverá ser implementado em uma classe derivada. Assim, para que
uma classe derivada de uma classe abstrata possa instanciar objetos, os métodos
abstratos devem ser definidos nestas classes derivadas.

class ClasseConcreta extends ClasseAbstrata {


public int metodo() {
return 0;
}
}
O exemplo a seguir ilustra um caso simples de uso de classe abstrata. A classe
Time define o método abstrato meuTime(), que é sobrescrito em seguida por
3 classes concretas.
public abstract class Time {
abstract void meuTime();
public static void futebol() {
System.out.println("Eu gosto de futebol");
}
}
public class America extends Time {
void meuTime() {
System.out.println("Eu sou americano...");
}
}

public class Atletico extends Time {


void meuTime() {
System.out.println("Eu sou ATLETICANO!");
}
}

public class Cruzeiro extends Time {


void meuTime() {
System.out.println("Eu sou cruzeirense...");
}
}
As classes America, Atletico e Cruzeiro redefinem o método abstrato
meuTime(), de acordo com as particularidades de cada torcedor.
public class MeuTime {
public static void main(String[] args) {
America america = new America();
Atletico atletico = new Atletico();
Cruzeiro cruzeiro = new Cruzeiro();
Time.futebol();
america.meuTime();
atletico.meuTime();
cruzeiro.meuTime();
}
}
Eu gosto de futebol.
Eu sou americano...
Eu sou ATLETICANO!
Eu sou cruzeirense...

O método futebol() é um método estático da classe Time,


portanto, não necessita de uma instância de classe para ser
referenciado. Observe que uma classe abstrata tanto pode ter
métodos abstratos quanto métodos concretos.
Suponha uma classe abstrata FormaGeometrica. Como calcular a área de
um objeto desta classe? Se as classes Retangulo, Elipse e Triangulo são
classes concretas derivadas de FormaGeometrica, então é possível utilizar
métodos específicos de cada uma dessas classes para calcular a área.

A técnica de polimorfismo permite que uma chamada de método faça


com que diferentes ações ocorram de acordo com o tipo de objeto
chamado.

public abstract class Forma {


public double area() {
return 0.0;
}
public abstract String getNome();
}
A classe Forma é uma classe abstrata, com um método abstrato getNome().
public class Ponto extends Forma {
protected int x, y;
public Ponto() {
x = 0;
y = 0;
}
public Ponto(int a, int b) {
x = a;
y = b;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public String getNome() {
return "Ponto";
}
public String toString() {
return "[" + x + ", " + y + "]";
}
}
public class Circulo extends Ponto {
protected double raio;
public Circulo() {
raio = 0;
}
public Circulo(double r, int a, int b) {
super(a, b);
raio = r;
}
public double area() {
return Math.PI * Math.pow(raio,2);
}
public String toString() {
return "Centro: " + super.toString() +
", Raio: " + raio;
}
public String getNome() {
return "Circulo";
}
}
public class Retangulo extends Ponto {
protected int base;
protected int altura;
public Retangulo() {
base = 0;
altura = 0;
}
public Retangulo(int x, int y, int b, int h) {
super(x, y);
base = b;
altura = h;
}
public double area() {
return base * altura;
}
public String toString() {
return "Centro: " + super.toString() + ", Base:"
+ base + ", Altura: " + altura;
}
public String getNome() {
return "Retangulo";
}
}
As classes Circulo e Retângulo estendem Ponto e sobrescrevem os
métodos area() e getNome() de Forma e também o método toString()
de Ponto.
public class Desenha {
public static void main(String args[]) {
Ponto pt = new Ponto(7, 11);
Circulo circ = new Circulo(3.5, 22, 8);
Retangulo ret = new Retangulo(10, 10, 5, 8);
Forma[] forma = new Forma[3];
forma[0] = pt;
forma[1] = circ;
forma[2] = ret;
for(int i = 0; i < forma.length; i++)
System.out.println(forma[i].getNome() + ": "
+ forma[i].toString() + "\nArea = "
+ forma[i].area());
}
}
A figura apresenta todas
as classes e os
relacionamentos
existentes entre elas em
um projeto construído
no BlueJ.

Ponto: [7, 11]


Area = 0.0
Circulo: Centro: [22, 8], Raio: 3.5
Area = 38.48451000647496
Retangulo: Centro: [10, 10], Base:5, Altura: 8
Area = 40.0
Interfaces
Interfaces são classes abstratas completamente não implementadas, ou seja,
todos os métodos são abstratos e devem ser sobrescritos por métodos das classes
concretas que as implementam.
A forma geral de uso de uma interface em Java é:

class Identificador implements Interface1,Interface2...

Considerando que todos os métodos de uma interface são abstratos, quando uma
classe implementa esta interface, deve escrever o código de todos esses métodos
abstratos. Este é o chamado contrato entre a interface e a classe que a
implementa.

O conceito de interface permite a implementação de uma espécie de herança


múltipla em Java, sobrepondo a regra de que uma subclasse somente pode ser
herdada de uma única superclasse.
O exemplo a seguir define uma interface Radio e uma interface Relogio. A
classe concreta RadioRelogio que herda os métodos destas interfaces.
public interface Radio {
void setEstacao(double d);
double getEstacao();
}

import java.util.Date;
public interface Relogio {
void setHorario(Date d);
Date getHorario();
}

Todos os métodos definidos em uma interface são obrigatoriamente


public e abstract, mesmo que isto não seja declarado
esplicitamente. A interface Radio abaixo é idêntica a anterior.

public interface Radio {


public abstract void setEstacao(double d);
public abstract double getEstacao();
}
import java.util.Date;
public class RadioRelogio implements Radio, Relogio {
private Date horario;
private double estacao;
public void setEstacao(double d) {
estacao = d;
}
public double getEstacao() {
return estacao;
}
public void setHorario(Date d) {
horario = d;
}
public Date getHorario() {
return horario;
}
public static void main(String[] args) {
RadioRelogio rr = new RadioRelogio();
rr.setEstacao(1.5);
rr.setHorario(new Date());
System.out.println(rr.getEstacao());
System.out.println(rr.getHorario());
}
}
Classes Internas
Em Java é possível declarar uma classe dentro da declaração de outra classe.
Tais classes são denominadas classes internas.

public class Externa {


private int x = 7;
class Interna {
public void imprimeExterna() {
System.out.println("x vale " + x);
}
}
}

Neste exemplo, a classe interna está acessando um membro privado da classe


externa. Isto está correto, afinal, a classe interna é também um membro da
classe externa.
public class Externa {
private int x = 7;
public void instanciaInterna(){
Interna in = new Interna(); //instancia interna
in.imprimeExterna(); //invoca método da interna
}
class Interna {
public void imprimeExterna() {
System.out.println("x vale " + x);
}
} //fim da classe interna
public static void main(String[] args){
Externa ex = new Externa(); //instancia externa
ex.instanciaInterna(); //invoca método da externa
}
}

Para instanciar uma classe interna, é necessário uma instância da classe


externa. Acima, a instância ex é que instancia um objeto in da classe interna.
public class Externa {
private int x = 7;
class Interna {
public void imprimeExterna() {
System.out.println("x vale " + x);
}
}
public static void main(String[] args){
Externa ex = new Externa();
Externa.Interna in = ex.new Interna();
in.imprimeExterna();
}
}

Voltando a classe Externa da página anterior, este exemplo ilustra como criar
um objeto da classe interna fora do código da instância da classe externa.
A instanciação de uma classe interna é o único cenário em Java em que se faz
necessário chamar new a partir de uma instância.
Classes Internas Anônimas
Java permite que se crie um objeto de uma classe interna sem nome, chamada
classe interna anônima.
class Externa {
public void imprime(){
System.out.println("Eu sou a classe externa");
}
}
public class TestaAnonima {
Externa ex = new Externa() {
public void imprime() {
System.out.println
("Eu sou a classe interna anônima");
}
};
public static void main(String[] args){
TestaAnonima ta = new TestaAnonima();
ta.ex.imprime();
}
}
Tratamento de exceções
Um erro para o qual pode existir um tratamento é chamado, em computação, de
exceção. Exemplos de exceções incluem divisão por zero, parâmetros de
métodos inválidos, overflow e subscrito de arrays fora dos limites.
Utilizar tratamento de exceções permite ao programador remover o código de
tratamento de erros da linha principal de execução do programa. Isso melhora a
clareza e a modificabilidade do código fonte.
public class Excecao {
public static void main(String[] args) {
System.out.println("Antes do erro");
try {
System.out.print(10 / 0);
}
catch(RuntimeException e){
System.out.println("Erro");
}
System.out.println("Depois do erro");
}
}
Exceções são objetos que pertencem a classes organizadas em uma hierarquia. A
classe que se encontra no topo desta hierarquia é a classe Throwable, que
possui duas subclasses: Exception e Error. Exception e suas subclasses
são usadas para indicar condições que podem ser recuperadas. Error e suas
subclasses indicam condições que em geral não podem ser recuperadas, causando
a terminação do programa.

Todos os objetos da classes Exception devem ser capturados ou explicitamente


relançados para um nível acima na pilha de chamadas. Isto só não é válido para
os objetos das classes RuntimeException, que definem as exceções que
podem ser lançadas durante a execução normal da máquina virtual, como divisão
por zero ou indexação fora dos limites do array.
O exemplo anterior, classe Excecao, captura uma exceção da classe
RuntimeException, o que, portanto, não é exigido pela máquina
virtual Java.

Um método pode lançar mais de uma exceção, portanto, muitas vezes é preciso
definir um bloco try/catch capaz de tratar mais de uma exceção. Neste caso,
cada cláusula catch trata uma exceção.
class Matematica {
public static void main(String[] args) {
try {
int op1 = Integer.parseInt(args[0]);
int op2 = Integer.parseInt(args[1]);
System.out.println("Soma = " + (op1 + op2));
System.out.println("Subtracao = " + (op1 - op2));
System.out.println("Produto = " + (op1 * op2));
System.out.println("Divisao = " + (op1 / op2));
} catch(ArithmeticException ae) {
System.out.println("Erro de divisao por zero");
} catch(ArrayIndexOutOfBoundsException aie) {
System.out.println("Numero de argumentos invalido");
} catch(NumberFormatException nfe) {
System.out.println("Digite apenas numeros inteiros");
}
}
}

Soma = 15 ArithmeticException, ArrayIndexOutOfBounds


Subtracao = 5 Exception e NumberFormatException são subclasses
Produto = 50 de RuntimeException e, portanto, o programador não
Divisao = 2 é obrigado a capturar estas exceções.
import java.io.*;
public class Adicao {
public static void main(String[] args) {
String s;
int num1, num2, soma;
try {
System.out.println("Entre com o 1o. numero: ");
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
s = br.readLine();
num1 = Integer.parseInt(s);
System.out.println("Entre com o 2o. numero: ");
s = br.readLine();
num2 = Integer.parseInt(s);
soma = num1 + num2;
System.out.println("Soma = " + soma);
} catch(IOException e) {
System.out.println("Erro na entrada de dados");
}
}
}
As classes do pacote java.io podem lançar exceções do tipo IOException.
O programador Java é obrigado a capturar estas exceções, usando blocos try /
catch (ou relançá-las explicitamente para o nível acima).

Não capturar ou lançar uma exceção causa um erro de compilação.

Para indicar que um método pode lançar uma exceção, Java utiliza a palavra
reservada throws, usada na declaração do método, e colocada antes da chave
de abertura do corpo do método.

A inclusão da cláusula throws à definição do do método simplesmente significa


que o método poderá lançar uma exceção, em caso de ocorrer algum problema.
A classe Adicao é reescrita a seguir, utilizando a cláusula throws, sem capturar
e tratar uma possível exceção da classe IOException.
import java.io.*;
public class Adicao {
public static void main(String[] args) throws
IOException {
String s;
int num1, num2, soma;
System.out.println("Entre com o 1o. numero: ");
InputStreamReader isr = new
InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
s = br.readLine();
num1 = Integer.parseInt(s);
System.out.println("Entre com o 2o. numero: ");
s = br.readLine();
num2 = Integer.parseInt(s);
soma = num1 + num2;
System.out.println("Soma = " + soma);
}
}
Para lançar explicitamente uma exceção, utiliza-se o operador throw. O
exemplo a seguir cria uma classe do usuário chamada NumeroPositivo, que
lança uma exceção Exception se for passado um argumento inválido.
class NumeroPositivo {
private int num;
public NumeroPositivo(int n) throws Exception {
if (n < 1)
throw new Exception("Número não positivo");
num = n;
}
}
A cláusula throws, na assinatura do método, especifica que pode ser lançada
uma exceção da classe Exception. O comando throw cria um novo objeto da
classe Exception e ainda acrescenta um argumento referente a esta exceção.
A classe TestaExcecao, definida a seguir, instancia um novo objeto da classe
NumeroPositivo, passando um valor como argumento. A exceção lançada por
NumeroPositivo será capturada pelo bloco try-catch de
TestaExcecao.
public class TestaExcecao {
public static void main(String[] args) {
try {
NumeroPositivo np = new
NumeroPositivo(Integer.parseInt(args[0]));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
O método getMessage(), da classe Exception, retorna uma
String correspondente ao argumento definido na definição do
objeto da classe Exception (ou qualquer uma das suas subclasses).

Para uma execução do tipo: java TestaExcecao 0, a saída será:

Número não positivo


Exceções do programador
Se o programador considerar que nenhuma exceção se encaixa no tipo de erro
que pretende lançar, pode criar uma nova subclasse de Exception para
representar essa exceção.

class PosiviteNumberException extends Exception {


public PosiviteNumberException(String s) {
super(s);
}
}

A classe PosiviteNumberException estende a classe Exception. O


argumento String s é passado para a superclasse.
A classe do usuário NumeroPositivo foi reescrita para lançar Posivite
NumberException ao invés de Exception. A execução de Testa
Excecao obterá o mesmo resultado visto anteriormente.
class NumeroPositivo {
private int num;
public NumeroPositivo(int n) throws
PosiviteNumberException {
if (n < 1)
throw new PosiviteNumberException
("Número não positivo");
num = n;
}
}
Existe ainda uma cláusula opcional do bloco try-catch chamada finally.
Seu propósito é conter um trecho de código que deve ser executado
independentemente de ocorrer ou não uma exceção.
O exemplo seguinte é uma adaptação da classe Matematica (pág. 117),
incluindo uma cláusula finally após o último catch. Para uma execução do
tipo java Matematica 3 0 a saída é:
Soma = 3
Subtracao = 3
Produto = 0
Erro de divisao por zero
Obrigado por usar a calculadora
class Matematica {
public static void main(String[] args) {
try {
int op1 = Integer.parseInt(args[0]);
int op2 = Integer.parseInt(args[1]);
System.out.println("Soma = " + (op1 + op2));
System.out.println("Subtracao = " + (op1 - op2));
System.out.println("Produto = " + (op1 * op2));
System.out.println("Divisao = " + (op1 / op2));
} catch (ArithmeticException e) {
System.out.println("Erro de divisao por zero");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println
("Numero de argumentos invalido");
} catch (NumberFormatException e) {
System.out.println
("Digite apenas numeros inteiros");
} finally {
System.out.println
("Obrigado por usar a calculadora");
}
}
}
GUIs AWT e Swing
Java possui dois pacotes para manipulação de componentes GUI. O pacote
java.awt (Abstract Windowing Toolkit) está diretamente associado com
as capacidades de GUI da plataforma local. O pacote javax.swing surgiu
na versão 1.2 (Java 2) e seus componentes GUI são chamados Java puros,
por apresentarem o mesmo look&feel em qualquer plataforma.

Frame é o componente do pacote AWT responsável pela criação de janelas


no ambiente gráfico utilizado. Este componente gera uma janela com barra de
título, bordas e pode ter outros componentes em seu interior, como caixas de
texto, botões, caixas de rolamento, etc.

Ao se utilizar o pacote swing, usamos o componente JFrame, que herda os


atributos e comportamentos de Frame. O exemplo a seguir demonstra a
criação de uma janela por intermédio da classe JFrame do pacote
javax.swing.
import java.awt.*;
import javax.swing.*;
public class Janela extends JFrame {
public Janela() { //método construtor da classe
setTitle(“Uma janela qualquer”);
setSize(400,50);
setLocation(150,150);
setResizable(false);
getContentPane().setBackground(Color.red);
}
public static void main(String args[]) {
Janela j = new Janela();
j.show(); //Exibe a Janela
j.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
}
}
Uma janela da classe JFrame ou qualquer subclasse só é exibida na tela
quando o método show é invocado. Além disso, o tamanho de uma janela
deve ser definido através do método setSize, herdado da classe
java.awt.Component.
A posição da janela é especificada com o método setLocation, também
do pacote Component.
A cor de fundo é atribuída através do método setBackground.
O método setResizable determina se a janela pode ou não ser
redimensionada.

O método main do exemplo define uma ou mais instruções responsáveis pelo


fechamento da janela. Isto é necessário para encerrar a janela DOS ao término
da execução do aplicativo. O método setDefaultCloseOperation da
classe JFrame é responsável por esta tarefa.
Componente JLabel
Os rótulos são definidos com a classe JLabel (uma subclasse de
java.awt.Component) e permitem exibir uma única linha de texto,
com ou sem um arquivo de imagem anexado.

É possível controlar várias propriedades dos rótulos, incluindo alinhamento,


tipo de letra, tamanho e cor.

O próximo exemplo ilustra a


utilização de rótulos,
incluindo um arquivo de
imagem, no frame conforme
apresentado ao lado.

ToolTipText (dica de ferramenta)


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestaRotulo extends JFrame {
private JLabel Rot1,Rot2;
public TestaRotulo() {
super("Teste de JLabel");//para setTitle()
Container C = getContentPane();
C.setLayout(new FlowLayout());
Rot1 = new JLabel(" CES/JF sem logo");
Rot1.setToolTipText("Rótulo 1");
C.add(Rot1);
Icon Ces = new ImageIcon("c:\\ceslogo.gif");
Rot2 = new JLabel(" CES/JF com logo");
Rot2.setIcon(Ces);
Rot2.setHorizontalTextPosition
(SwingConstants.CENTER);
Rot2.setVerticalTextPosition
(SwingConstants.BOTTOM);
Rot2.setToolTipText("Rótulo 2");
C.add(Rot2);
setSize(200,200);
show();
}
public static void main(String args[]) {
TestaRotulo T = new TestaRotulo();
T.setDefaultCloseOperation(JFrame.
EXIT_ON_CLOSE);
}
}

A classe TestaRotulo instancia dois componentes JLabel. O comando


super, por herança, invoca o método setTitle de JTable. Lembre-se
que TestaRotulo é uma subclasse de JTable.

O método setLayout da classe Container define o tipo do gerenciador


de leiaute para a interface com o usuário do aplicativo Java. Se você vai usar
mais de um componente gráfico em um Container, deverá usar também
um gerenciador de leiaute para conter todos os componentes.

FlowLayout é o gerenciador mais simples e que coloca os componentes


GUI anexados da esquerda para a direita até o limite do Container.
A classe ImageIcon do pacote javax.swing permite definir um objeto
gráfico a ser visualizado em componentes swing. Os arquivos de imagens
suportados são GIF, JPEG e PNG. É importante não esquecer de especificar o
caminho completo do arquivo de imagem na árvore de diretório. Caso
contrário, o interpretador Java irá apresentar o frame sem a imagem (e não
acusará nenhuma mensagem de erro!).

Os métodos setHorizontalTextPosition e
setVerticalTextPosition do objeto Jlabel permitem especificar o
alinhamento do arquivo gráfico em relação ao texto do rótulo. Respectivamente,
controlam o alinhamento horizontal e vertical do ícone. O argumento
SwingConstants possui as opções LEFT, RIGHT e CENTER (horizontal) e
TOP e BOTTOM (vertical).
O método setToolTipText é herdado pela classe Jlabel da classe
JComponent e é utilizado para especificar um componente GUI com uma
dica de ferramenta.
Um objeto da classe ImageIcon é um objeto Icon, uma
vez que a classe ImageIcon implementa a classe Icon.
Tratamento de eventos
As GUIs são baseadas em eventos, tais como mover o mouse, clicar um
botão, selecionar um item de um menu, fechar uma janela, etc. Informações
de eventos são armazenados em objetos de classes que estendem AWTEvent.
Importante: Para processar um evento é necessário registrar um ouvinte de
eventos e implementar um tratador de eventos.

Um objeto ouvinte de eventos detecta um determinado tipo de evento, como


um clique do mouse em um programa. Um tratador de eventos é um método
chamado em resposta ao evento detectado pelo ouvinte de eventos.

O ouvinte de eventos é um objeto de uma classe que implementa uma ou


mais interfaces listener de eventos dos pacotes java.awt.event e
javax.swing.event. Lembre-se: para cada evento “ouvido” deve haver
um método tratador de eventos para “tratá-lo”.
Um evento com botões (Jbutton)
import java.awt.*; Cria dois
import java.awt.event.*; botões,
import javax.swing.*; Cruzeiro e
public class Classico extends JFrame{
private JButton Cruzeiro, Atletico; Atlético
public Classico() {
super("Classico mineiro");
Instancia
Container C = getContentPane();
C.setLayout(new FlowLayout()); os botões,
Cruzeiro = new JButton("Cruzeiro"); definindo
C.add(Cruzeiro); os rótulos
Atletico = new JButton("Atletico");
C.add(Atletico);
TrataBotao B = new TrataBotao();
Cruzeiro.addActionListener(B); Instancia a
Atletico.addActionListener(B); classe interna
setSize(250,100); para tratamento
show(); de eventos dos
} botões
public static void main(String args[]) {
Classico clas = new Classico();
clas.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
}
//classe interna para tratamento de evento de botão:
private class TrataBotao implements ActionListener {
//método para tratamento de evento de botão:
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"O melhor de Minas: "+e.getActionCommand());
} //Fim do método actionPerformed
} //Fim da classe interna TrataBotao
} //Fim da classe Classico

Este exemplo apresenta o objeto botão, um componente gráfico em que o


usuário clica sobre o objeto para acionar uma ação específica. Um Jbutton
gera um ActionEvent que deve ser tratado pelo método actionPerfomed
a partir da classe interna que implementa ActionListener.
Este exemplo usa um tipo de botão
chamado botão de comando, que gera
um ActionEvent quando o usuário
clica no botão com o mouse. Neste
exemplo, o tratamento de eventos é feito
na classe interna TrataBotao.

O método actionPerformed define uma caixa de diálogo de mensagem


contendo o rótulo do botão que foi pressionado pelo usuário. O rótulo é obtido
através do método getActionCommand.

Cada tipo de evento tem uma interface listener de eventos


correspondente. Assim, ActionEvent é tratado por
ActionListener; MouseEvent, por MouseListener;
KeyEvent, por KeyListener, e assim por diante.
Eventos com caixas de texto
O exemplo a seguir, uma calculadora com as quatro operações aritméticas,
ilustra a inclusão de caixas de texto JTextField e botões JButton em
uma janela Jframe, com os respectivos tratamento de eventos.

Caixas de texto Botões


(JTextField) (JButton)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Calcula extends JFrame implements ActionListener
{
JLabel L1,L2,L3; //Cria 3 rótulos
JButton B1,B2,B3,B4,B5; //Cria 5 botões
JTextField T1,T2,T3; //Cria 3 caixas de texto
public static void main(String args[]){
Calcula calc = new Calcula();
calc.show();
calc.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public Calcula()
{
setTitle("Calculadora");
setSize(350,150);
setLocation(50,50);
getContentPane().setLayout(new GridLayout(3,4));
L1 = new JLabel("Operando1");
L2 = new JLabel("Operando2");
L3 = new JLabel("Resultado");
B1 = new JButton("+");
B1.addActionListener(this);
B2 = new JButton("-");
B2.addActionListener(this); Associa ouvintes
B3 = new JButton("x");
B3.addActionListener(this);
de eventos para
B4 = new JButton("/"); cada um dos
B4.addActionListener(this); botões criados
B5 = new JButton("Limpar");
B5.addActionListener(this);
T1 = new JTextField();
T2 = new JTextField(); Torna a caixa de texto T3
T3 = new JTextField(); não-editável pelo usuário
T3.setEditable(false);
getContentPane().add(L1);
getContentPane().add(T1);
getContentPane().add(B1);
getContentPane().add(B2); Aloca os objetos de
getContentPane().add(L2); rótulos, botões e caixas
getContentPane().add(T2);
getContentPane().add(B3);
de texto ao gerenciador
getContentPane().add(B4); de leiaute.
getContentPane().add(L3);
getContentPane().add(T3);
getContentPane().add(B5);
}

Este aplicativo utiliza um novo tipo de gerenciador de leiaute, chamado


GridLayout. Este gerenciador especifica, como argumentos, o número de
linhas e o de colunas para o leiaute. As suas posições vão sendo alocadas
sempre de cima para baixo e da esquerda para a direita.
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==B5) {
T1.setText("");
T2.setText(""); Limpa as caixas de texto
T3.setText("");
return;
}
float op1=0,op2=0,res=0;
try {
op1 = Float.parseFloat(T1.getText());
op2 = Float.parseFloat(T2.getText());}
catch(NumberFormatException erro) {
T3.setText("Erro!!");
return;}
if(e.getSource() == B1) res = op1 + op2;
if(e.getSource() == B2) res = op1 - op2;
if(e.getSource() == B3) res = op1 * op2;
if(e.getSource() == B4) res = op1 / op2;
T3.setText(""+res);
}
}
A cláusula this passada como argumento para o método
addActionListener para cada um dos botões criados significa que o
ouvinte de eventos está sendo associado ao próprio botão.

O método tratador de eventos actionPerformed deve tratar todos os


eventos associados a ouvintes no método calcula. Assim, se o evento
disparado for associado ao botão B5, as caixas de texto devem ter seus valores
limpados. O método setText de JTextField foi utilizado para este
propósito.

Os valores digitados nas caixas de texto devem ser convertidos em campos


numéricos para sem processados. O método getText de JTextField
obtém o valor atual da caixa de texto e o método parseFloat converte
para valores do tipo básico float.

Uma cláusula try-catch foi empregada para impedir que o


programa seja interrompido caso o usuário informe um valor não
numérico para os campos operando1 e operando2.
Listas de Seleção JList
As listas de seleção são objetos swing que
possibilitam a escolha de um ou vários valores
armazenados em uma lista de opções. Esta lista é
manipulada a partir da classe JList. O exemplo
seguinte ilustra a utilização desta classe.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Quitanda extends JFrame implements
ListSelectionListener
{
JTextField tf;
JList lista;
DefaultListModel dlm;
double[] preco = {0.8, 4.0, 3.5, 5.0, 0.7};
public static void main(String args[]){
Quitanda q = new Quitanda();
q.show();
q.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Quitanda() {
setLocation(300,100);
setTitle("Quitanda do Prof. Wander");
setSize(250,70);
tf = new JTextField();
tf.setEditable(false);
dlm = new DefaultListModel();
dlm.addElement("Banana"); Os itens devem ser inseridos
dlm.addElement("Pera");
dlm.addElement("Maçã"); em um objeto da classe
dlm.addElement("Uva"); DefaultListModel
dlm.addElement("Laranja");
lista = new JList(dlm);
lista.addListSelectionListener(this);
JScrollPane painel = new JScrollPane(lista);
getContentPane().setLayout(new GridLayout(2,1));
getContentPane().add(painel);
getContentPane().add(tf);
}
public void valueChanged(ListSelectionEvent e){
tf.setText("Fruta: " + lista.getSelectedValue() +
" - Preço: R$ " + preco[lista.getSelectedIndex()]);
}
}

O pacote javax.swing.event é necessário para a manipulação de eventos


de JList. Cada vez que o usuário escolhe um item da lista é gerado um evento
a ser tratado pelo método valueChanged. É também necessário implementar
a interface ListSelectionListener para que as opções de JList
possam ser reconhecidas à medida que o usuário seleciona um item da lista.

Os itens a serem colocados em um JList devem antes ser inseridos em


objeto DefaultListModel para depois serem associados a uma lista
JList. O método addListSelectionListener deve ser invocado
para que a opção escolhida seja reconhecida no momento da ação do usuário.

O método getSelectedValue() retorna o texto do elemento selecionado na


lista. O método getSelectedIndex() retorna um número inteiro corres-
pondente ao índice do elemento selecionado.
Caixas de seleção JComboBox
As caixas de seleção JComboBox permitem que o
usuário selecione apenas um único item de sua lista,
e é uma opção ao componente gráfico JList.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Quitanda extends JFrame implements ItemListener
{
JTextField tf;
JComboBox cb;
double[] preco = {0.8, 4.0, 3.5, 5.0, 0.7};

public static void main(String args[])


{
Quitanda q = new Quitanda();
q.show();
q.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Quitanda() {
setLocation(300,100);
setTitle("Quitanda do Prof. Wander");
setSize(250,100);
tf = new JTextField();
tf.setEditable(false);
String frutas[] = {"Banana","Pera","Maçã","Uva","Laranja"};
cb = new JComboBox(frutas);
cb.addItemListener(this);
getContentPane().setLayout(new GridLayout(2,1));
getContentPane().add(cb);
getContentPane().add(tf);
} //fim do método Quitanda
public void itemStateChanged(ItemEvent e) {
tf.setText("Fruta: " + cb.getSelectedItem() +
" - Preço: R$ " + preco[cb.getSelectedIndex()]);
} //fim do método itemStateChanged
}

A interface ItemListener é responsável por reconhecer eventos relacionados


ao componente JComboBox.
Na inicialização do objeto cb, sua lista passa a conter as Strings
armazenadas em um array de itens: cb = new JComboBox(frutas);
O método addItemListener registra o objeto cb para que as mudanças
de seleção sejam reconhecidas e tratadas pelo método
itemStateChanged.
O método getSelectedItem retorna o conteúdo do texto selecionado.
O método getSelectedIndex retorna um valor inteiro contendo o índice
da opção selecionada.
Caixas de Opção JCheckBox
As caixas de opção JCheckBox são objetos swing que permitem representar
opções que podem ser ativadas e desativadas com um simples clique do mouse.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Estilo extends JFrame implements ItemListener
{
JLabel jl;
JCheckBox cb1,cb2; // cria dois objetos JCheckBox
static int negrito=0,italico=0;
public static void main(String args[]) {
Estilo est = new Estilo();
est.show();
est.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} //fim do método main
Estilo()
Cria uma cor com os
{
getContentPane().setBackground valores RGB
(newColor(180,180,180)); 180, 180, 180
setTitle("Estilo de letras");
setSize(300,70); Cria um rótulo
getContentPane().setLayout usando a fonte
(newFlowLayout(FlowLayout.CENTER)); Arial, corpo 20
jl = new JLabel("Tupi ");
jl.setFont(new Font("Arial",Font.PLAIN,20));
jl.setForeground(Color.black);
cb1 = new JCheckBox("Negrito");
cb1.setBackground(new Color(180,180,180));
cb1.addItemListener(this);
cb2 = new JCheckBox("Italico");
cb2.setBackground(new Color(180,180,180));
cb2.addItemListener(this);
getContentPane().add(jl);
getContentPane().add(cb1);
getContentPane().add(cb2);
}
public void itemStateChanged(ItemEvent e) {
if(e.getSource()==cb1) {
if(e.getStateChange()==ItemEvent.SELECTED)
negrito=Font.BOLD;
else
negrito=Font.PLAIN;
}
if(e.getSource()==cb2) {
if(e.getStateChange()==ItemEvent.SELECTED)
italico=Font.ITALIC;
else
italico=Font.PLAIN;
}
jl.setFont(new Font("Arial",negrito+italico,20));
} //fim do método itemStateChanged
}

Ao se utilizar o padrão RGB (red-green-blue) para definir uma nova cor para
um objeto swing, os valores numéricos para estas três tonalidades devem variar
entre 0 e 255.
Para que a seleção seja reconhecida pelo método itemStateChanged, é
necessário invocar o método addItemListener para cada um dos objetos
JCheckBox instanciados. O método addItemListener será executado
sempre que o usuário clicar em um dos botões JCheckBox.

A comparação e.getStateChange()==ItemEvent.SELECTED é
utilizada para verificar se o componente JCheckBox está marcado ou não.
As propriedades SELECTED e DESELECTED indicam que o objeto está,
respectivamente, marcado e desmarcado.

As constantes Font.PLAIN, Font.BOLD e Font.ITALIC são previamente


definidas em Java e possuem como valor 0, 1 e 2, respectivamente e devem ser
tratados como int. A combinação de seus valores gera estilos diferentes de
letras para a instância jl de Jlabel em jl.setFont(new Font
("Arial",negrito + italico,20));. O argumento 20 significa que
a fonte será exibida com 20 pontos de altura (ponto é uma unidade de medida
comum em artes gráficas. Uma polegada possui 72 pontos).
Painéis e botões de rádio
Os painéis JPanel são utilizados quando
mais de um tipo de leiaute precisa ser
inserido em uma janela. Desta forma, por
exemplo, um painel pode ser
FlowLayout e o outro GridLayout.
Os botões de rádio JRadioButton permitem que uma entre várias opções
seja escolhida pelo usuário. Os botões de rádio devem sempre ser agrupados em
um ButtonGroup para cada conjunto de botões a serem inseridos no JFrame.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Desconto extends JFrame implements ItemListener {
JLabel l1,l2;
float n=0,res=0;
JTextField tf1,tf2;
JPanel p1,p2; //cria dois painéis
JRadioButton rb1,rb2,rb3; //cria três botões de rádio
ButtonGroup rg; //cria um conjunto de botões
public static void main(String args[]) {
JFrame d = new Desconto();
d.show();
d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Desconto() {
setTitle("Cálculo do Desconto");
setSize(350,120);
getContentPane().setLayout(new
FlowLayout(FlowLayout.CENTER));
l1 = new JLabel("Digite o preço do produto");
l1.setForeground(Color.red);
l2 = new JLabel("Valor do desconto: ");
l2.setForeground(Color.red);
tf1 = new JTextField(5); //campo de texto p/preço do produto
tf2 = new JTextField(5); //campo de texto p/valor do desconto
tf2.setEditable(false);
p1 = new JPanel();
p2 = new JPanel();
rb1 = new JRadioButton("10%");
rb2 = new JRadioButton("20%");
rb3 = new JRadioButton("30%");
rg = new ButtonGroup();
rg.add(rb1); //adiciona rb1 ao grupo de botões de rádio
rg.add(rb2); //adiciona rb2 ao grupo de botões de rádio
rg.add(rb3); //adiciona rb3 ao grupo de botões de rádio
rb1.addItemListener(this); //registra o evento do botão rb1
rb2.addItemListener(this); //registra o evento do botão rb2
rb3.addItemListener(this); //registra o evento do botão rb3
p1.setLayout(new FlowLayout(FlowLayout.CENTER));
p2.setLayout(new GridLayout(2,3));
p1.add(l1); //adiciona o rótulo l1 ao painel p1
p1.add(tf1); //adiciona o campo de texto tf1 ao painel p1
p2.add(rb1); //adiciona o botão de rádio rb1 ao painel p2
p2.add(rb2); //adiciona o botão de rádio rb2 ao painel p2
p2.add(rb3); //adiciona o botão de rádio rb3 ao painel p2
p2.add(l2); //adiciona o rótulo l2 ao painel p2
p2.add(tf2); //adiciona o campo de texto tf2 ao painel p2
getContentPane().add(p1); //adiciona o painel p1 ao frame
getContentPane().add(p2); //adiciona o painel p2 ao frame
}
public void itemStateChanged(ItemEvent e) {
if (tf1.getText().length()==0) return;
try {
n = Float.parseFloat(tf1.getText());
if (e.getSource()==rb1) res = (n * 10)/100;
if (e.getSource()==rb2) res = (n * 20)/100;
if (e.getSource()==rb3) res = (n * 30)/100;
}
catch(NumberFormatException erro) {
tf2.setText("Erro");
return; }
tf2.setText(""+res);
} //fim do método itemStateChanged
}
O exemplo declara dois painéis JPanel p1 e p2 que podem ser encarados da
mesma forma que as janelas JFrame, pois possuem as mesmas propriedades:
cor de fundo, leiaute, objetos que contêm, etc. Depois de definidas as
propriedades de um painel, ele é inserido em uma janela. Assim, uma janela
pode conter vários painéis, cada qual com a sua própria formatação e leiaute.

O painel p1 é definido como FlowLayout e contém um rótulo e um campo


de texto. O painel p2 é definido como GridLayout contendo 2 linhas e 3
colunas e contém, além de um campo de texto e um rótulo, o agrupamento de
botões de rádio.
Barras de rolagem JScrollBar
As barras de rolagem JScrollBar permitem
variar um valor numérico dentro de uma faixa
estabelecida por um mínimo e um máximo.

A sintaxe para criar uma barra de rolagem utilizando JScrollBar é:


JScrollBar(orientação,valor inicial,intervalo do meio,
valor mínimo,valor máximo)
A orientação é um valor inteiro que define se a barra de rolagem é horizontal (0)
ou vertical (1). A orientação também pode ser definida pelas constantes
JScrollBar.HORIZONTAL e JScrollBar.VERTICAL.
O intervalo do meio é um valor do tipo inteiro que define o incremento ou
decremento do valor da barra de rolagem quando o usuário clicar nessa área.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.DecimalFormat;
public class Conversao extends Jframe
implements AdjustmentListener {
JScrollBar sb1;
JLabel l1,l2;
DecimalFormat df;
public static void main(String args[]) {
JFrame c = new Conversao();
c.show();
c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Conversao()
{
setSize(250,100);
setTitle("Conversão de Medidas");
getContentPane().setLayout(new GridLayout(3,1));
sb1 = new JScrollBar(JScrollBar.HORIZONTAL,0,5,0,105);
sb1.addAdjustmentListener(this);
l1 = new JLabel(”Centímetros",JLabel.CENTER);
l2 = new JLabel(”Polegadas",JLabel.CENTER);
getContentPane().add(sb1);
getContentPane().add(l1);
getContentPane().add(l2);
}
public void adjustmentValueChanged(AdjustmentEvent e) {
l1.setText(sb1.getValue() + " Centímetros");
DecimalFormat nf;
df = new DecimalFormat(“0.000”);
double pol = sb1.getValue() / 2.54;
l2.setText(df.format(pol) +" Polegadas");
}
}

A interface AdjustmentListener é utilizada para reconhecer a interação do


usuário com um objeto JScrollBar.
Os argumentos JScrollBar.HORIZONTAL,0,5,0,105 definem uma
barra de rolagem horizontal, com valor inicial 0, com valor de incremento e
decremento para o intervalo do meio 5, com valor mínimo 0 e valor máximo
105. Na realidade, o valor máximo exibido será 100, porém este argumento deve
receber o valor máximo acrescido do intervalo do meio.
O método addAdjustmentListener registra a barra de rolagem para que
o evento seja gerado por ela.
Áreas de texto JTextArea
As áreas de texto JTextArea já foram apresentadas anteriormente. Aqui são
vistas algumas características deste componente Swing, cuja sintaxe é
JTextArea(texto inicial, número de linhas iniciais,
dimensão).

texto inicial deve ser um objeto String e este argumento é opcional.


número de linhas
iniciais define o nº de
linhas que a área de texto
terá, sem o uso de uma
barra de rolagem, que pode
ser definida através do com-
ponente JScrollPane.
dimensão deve ser um valor inteiro que especifica o número de caracteres
W (o caracter mais largo do alfabeto) que cabem em uma linha na área de
texto. Em razão desta definição, em geral cabem bem mais caracteres do que o
número que for introduzido como argumento.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CopiaTexto extends JFrame implements ActionListener {
JTextArea ta1,ta2;
JButton b1,b2;
public static void main(String args[]) {
JFrame cp = new CopiaTexto();
cp.show();
cp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
CopiaTexto() {
setSize(480,280);
setTitle("Copia Texto");
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER));
b1 = new JButton("Copia Tudo");
b1.addActionListener(this);
b2 = new JButton("Copia Seleção");
b2.addActionListener(this);
ta1 = new JTextArea(5,40);
ta2 = new JTextArea(5,40);
JScrollPane p1 = new JScrollPane(ta1);
JScrollPane p2 = new JScrollPane(ta2);
getContentPane().add(p1);
getContentPane().add(b1);
getContentPane().add(b2);
getContentPane().add(p2);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource()==b1) //copia o conteúdo de ta1 em ta2
ta2.setText(ta1.getText());
if (e.getSource()==b2) //copia a seleção de ta1 em ta2
ta2.setText(ta1.getSelectedText());
}
}

Os métodos getText e getSelectedText da classe JTextArea obtêm,


respectivamente, o texto do componente e o texto selecionado do
componente.
Swing: menus
O primeiro passo para se criar um menu em Java é definir uma barra de menus
JMenuBar, que deverá conter o conjunto de menus que aparece na parte
superior da janela gráfica. Além disso, é necessário definir a barra de menus
padrão da janela, utilizando o método setJMenuBar.

Em seguida, deve-se criar os menus JMenu a serem inseridos na barra de menus


através do método <nome da barra de menus>.add(<nome do
menu>).
O passo seguinte é criar um novo item de menu JMenuItem e incluí-lo no
seu menu através do método <nome do menu>.add(<nome do
item>).
Menu
Barra de
Itens do Menus
Menu
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Menus extends JFrame implements ActionListener {
JMenuBar mb;
JTextField tf;
JMenu Cadastro, Relatorio;
JMenuItem Ccliente, Cfornec, Csair, Rcliente, Rfornec;
public static void main(String args[]) {
JFrame m = new Menus();
m.show();
m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Menus() {
setTitle("Exemplo com Menus");
setSize(270,130);
setLocation(50,50);
tf = new JTextField();
mb = new JMenuBar(); //cria a barra de menus
Cadastro = new JMenu("Cadastro"); //cria um novo menu
Relatorio = new JMenu("Relatórios"); //cria um novo menu
Ccliente = new JMenuItem ("Cliente"); //cria um novo item
Ccliente.addActionListener(this); //registra o evento
Cfornec = new JMenuItem ("Fornecedor"); //cria um novo item
Cfornec.addActionListener(this); //registra o evento
Csair = new JMenuItem ("Sair do sistema"); //cria um novo item
Csair.addActionListener(this); //registra o evento
Cadastro.add(Ccliente); //adiciona o item ao menu
Cadastro.add(Cfornec); //adiciona o item ao menu
Cadastro.add(Csair);
Rcliente = new JMenuItem ("Relação de Clientes");
Rcliente.addActionListener(this);
Rfornec = new JMenuItem ("Relação de Fornecedores");
Rfornec.addActionListener(this);
Relatorio.add(Rcliente); //adiciona o item ao menu
Relatorio.add(Rfornec); //adiciona o item ao menu
mb.add(Cadastro); //adiciona o menu à barra
mb.add(Relatorio); //adiciona o menu à barra
setJMenuBar(mb); //define a barra de menus como padrão
getContentPane().add(tf);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Ccliente)
tf.setText("Escolhido o item Cliente");
if (e.getSource() == Cfornec)
tf.setText("Escolhido o item Fornecedor");
if (e.getSource() == Rcliente)
tf.setText("Escolhido o item Relação de Clientes");
if (e.getSource() == Rfornec)
tf.setText("Escolhido o item Relação de Fornecedores");
if (e.getSource() == Csair)
System.exit(0);
}
}
O exemplo a seguir apresenta um menu
com um aspecto mais sofisticado,
utilizando subitens, ícones, barra
divisória e teclas de atalho para acessar
os itens do menu.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Profissa extends JFrame implements ActionListener
{
JMenuBar mb;
JMenu Arquivo, Save;
JMenuItem Novo, Abrir, Sair, Salvar, SalvarComo, SalvarTudo;
public static void main(String args[])
{
JFrame p = new Profissa();
p.show();
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public Profissa() {
setTitle("Menu Profissional");
setSize(250,150);
mb = new JMenuBar(); //cria a barra de menus
Arquivo = new JMenu("Arquivo"); //cria um novo menu
Arquivo.setMnemonic(KeyEvent.VK_A);
Arquivo.addActionListener(this);
Save = new JMenu("Save"); //cria um novo menu
Novo = new JMenuItem ("Novo",new ImageIcon("icon2.gif"));
Novo.addActionListener(this);
Novo.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_N, ActionEvent.ALT_MASK));
Novo.setMnemonic(KeyEvent.VK_N);
Abrir = new JMenuItem ("Abrir",new ImageIcon("PASTA2.gif"));
Abrir.addActionListener(this);
Abrir.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_A, ActionEvent.ALT_MASK));
Abrir.setMnemonic(KeyEvent.VK_B);
Salvar = new JMenuItem ("Salvar",new ImageIcon("disk_cat.gif"));
Salvar.addActionListener(this);
Salvar.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
Salvar.setMnemonic(KeyEvent.VK_S);
SalvarComo = new JMenuItem ("Salvar Como");
SalvarComo.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
SalvarComo.addActionListener(this);
SalvarComo.setMnemonic(KeyEvent.VK_C);
SalvarTudo = new JMenuItem ("Salvar Tudo");
SalvarTudo.addActionListener(this);
SalvarTudo.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_T, ActionEvent.CTRL_MASK));
SalvarTudo.setMnemonic(KeyEvent.VK_T);
Sair = new JMenuItem ("Sair",new ImageIcon("DOOR_EXI.gif"));
Sair.addActionListener(this);
Sair.setAccelerator(KeyStroke.getKeyStroke
(KeyEvent.VK_X, ActionEvent.ALT_MASK));
Sair.setMnemonic(KeyEvent.VK_A);
Save.add(Salvar); //adiciona o item ao menu
Save.add(SalvarComo); //adiciona o item ao menu
Save.add(SalvarTudo); //adiciona o item ao menu
Arquivo.add(Novo); //adiciona o item ao menu
Arquivo.add(Abrir); //adiciona o item ao menu
Arquivo.add(Save); //adiciona o item ao menu
Arquivo.addSeparator(); //adiciona uma barra divisória
Arquivo.add(Sair); //adiciona o item ao menu
mb.add(Arquivo); //adiciona o menu à barra
setJMenuBar(mb); //define a barra de menus como padrão
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Novo)
JOptionPane.showMessageDialog(null,"menu Novo.",
"Usando menus",JOptionPane.INFORMATION_MESSAGE);
if (e.getSource() == Abrir)
JOptionPane.showMessageDialog(null,"menu Abrir.",
"Usando menus",JOptionPane.INFORMATION_MESSAGE);
if (e.getSource() == Salvar)
JOptionPane.showMessageDialog(null,"Sub-menu Salvar.",
"Usando menus",JOptionPane.INFORMATION_MESSAGE);
if (e.getSource() == SalvarComo)
JOptionPane.showMessageDialog(null,"Sub-menu Salvar Como.",
"Usando menus",JOptionPane.INFORMATION_MESSAGE);
if (e.getSource() == SalvarTudo)
JOptionPane.showMessageDialog(null,"Sub-menu Salvar Tudo.",
"Usando menus",JOptionPane.INFORMATION_MESSAGE);
if (e.getSource() == Sair)
System.exit(0);
}
}

Arquivo.setMnemonic(KeyEvent.VK_A) cria um sublinhado embaixo


da letra especificada, neste caso, a letra A. Assim, os itens do menu Arquivo
podem ser acessados via teclado, usando a combinação ALT + A.
O método setAccelerator é utilizado para criar um atalho para um item de
menu. Duas constantes devem ser passadas para este método. Por exemplo, as
constantes KeyEvent.VK_N e ActionEvent.ALT_MASK definem o atalho
como ALT + N.

O método addSeparator() cria uma barra divisória no menu.


Outros objetos gráficos também podem ser inseridos em nenus, tais como
botões de rádio JRadioButton ou caixas de marcação JCheckBox. Para
inseri-los em um menu, basta utilizar o método add.
Eventos do mouse
As classes receptoras de eventos relacionados ao uso do mouse em Java são
MouseListener e MouseMotionListener.
MouseListener refere-se aos eventos gerados pelo mouse quando é clicado,
entra na área de um componente, sai da área de um componente, etc.
MouseMotionListener refere-se a eventos do mouse gerados pela sua
movimentação sobre um componente.
Os métodos para registrar os objetos usados em uma aplicação swing, no que
se refere ao uso dos eventos do mouse são addMouseListener() e
addMouseMotionListener().
Ao ser gerado um evento do mouse, é necessário declarar os respectivos
métodos para tratamento do evento. Os métodos a serem declarados para um
evento do tipo MouseEvent gerado pela classe MouseListener são
mousePressed, mouseClicked, mouseEntered, mouseExited e
mouseReleased. Observe que é obrigatório declarar todos estes métodos,
mesmo que apenas um venha a ser realmente utilizado.
Existem ainda métodos que permitem verificar as características do evento do
mouse. Por exemplo, é possível detectar se foi dado um clique ou um duplo
clique no mouse. Veja alguns métodos associados aos eventos do mouse:
int getClickCout() – retorna o número de vezes que o mouse foi clicado;
int getX() – retorna a posição X do ponteiro do mouse sobre o componente
swing;
int getY() – retorna a posição Y do ponteiro do mouse;
boolean isAltDown() – retorna true se a tecla ALT foi pressionada em
conjunto com o mouse;
boolean isControlDown() – retorna true se a tecla CRTL foi pressiona-
da em conjunto com o mouse;
boolean isShiftDown() – retorna true se a tecla SHIFT foi pressionada
em conjunto com o mouse;
O exemplo seguinte, EventoMouse, ilustra uma aplicação básica de tratamento
de eventos do mouse.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class EventoMouse extends JFrame implements MouseListener {
Container C1;
JButton B1;
JTextField T1;
public static void main(String args[]) {
JFrame Janela = new EventoMouse();
Janela.show();
Janela.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public EventoMouse() {
setTitle("Trata evento do mouse");
setSize(250,100);
C1 = getContentPane();
C1.setLayout(new FlowLayout());
B1 = new JButton("Galor forte e vingador");
B1.addMouseListener(this);
T1 = new JTextField(20);
C1.add(B1);
C1.add(T1);
}
public void mousePressed(MouseEvent e) {
T1.setText("O botão do mouse foi pressionado");
}
public void mouseClicked(MouseEvent e) {
T1.setText("O botão do mouse foi solto");
}
public void mouseReleased(MouseEvent e) {
T1.setText("O ponteiro do mouse foi arrastado");
}
public void mouseEntered(MouseEvent e) {
T1.setBackground(Color.black);
T1.setForeground(Color.white);
T1.setText("O ponteiro do mouse entrou na área");
}
public void mouseExited(MouseEvent e) {
T1.setBackground(Color.gray);
T1.setForeground(Color.black);
T1.setText("O ponteiro do mouse saiu da área");
}
}

A figura ao lado ilustra uma saída


para a aplicação EventoMouse.

Como já foi dito, é necessário declarar todos os métodos para tratamento de


eventos do mouse, mesmo que apenas um venha a ser efetivamente usado.
Classes adaptadoras
Algumas das interfaces ouvintes de eventos de Java, a exemplo de
MouseListener, exigem do usuário a implementação de vários métodos, o
que nem sempre é desejável.
Para solucionar este inconveniente, os pacotes java.awt.event e java.
swing.event fornecem classes adaptadoras de ouvintes de eventos. Uma
classe adaptadora implementa uma interface e fornece uma implementação-
padrão, com o corpo do método vazio, para cada um dos métodos.
Por exemplo, a classe adaptadora MouseAdapter implementa a interface
MouseListener e a classe adaptadora MouseMotionAdapter implementa
a interface MouseMotionListener.