Curso Técnico em Informática
Programação Orientada a Objetos II
Robson Braga de Andrade Presidente da Confederação Nacional da Indústria
Rafael Lucchesi Diretor do Departamento Nacional do SENAI
Regina Maria de Fátima Torres Diretora de Operações do Departamento Nacional do SENAI
Alcantaro Corrêa Presidente da Federação da Indústria do Estado de Santa Catarina
Sérgio Roberto Arruda Diretor Regional do SENAI/SC
Antônio José Carradore Diretor de Educação e Tecnologia do SENAI/SC
Marco Antônio Dociatti Diretor de Desenvolvimento Organizacional do SENAI/SC
Confederação Nacional da Indústria Serviço Nacional de Aprendizagem Industrial
Curso Técnico em Informática
Programação Orientada a Objetos II Diogo Vinícius Winck
Florianópolis/SC 2011
É proibida a reprodução total ou parcial deste material por qualquer meio ou sistema sem o prévio consentimento do editor.
Autor Diogo Vinícius Winck
Fotografias Banco de Imagens SENAI/SC http://www.sxc.hu/ http://office.microsoft.com/en-us/ images/ http://www.morguefile.com/ http://www.bancodemidia.cni.org.br/
SENAI/SC — Serviço Nacional de Aprendizagem Industrial Rodovia Admar Gonzaga, 2.765 - Itacorubi - Florianópolis/SC CEP: 88034-001 Fone: (48) 0800 48 12 12 www.sc.senai.br
Prefácio Você faz parte da maior instituição de educação profissional do estado. Uma rede de Educação e Tecnologia, formada por 35 unidades conectadas e estrategicamente instaladas em todas as regiões de Santa Catarina. No SENAI, o conhecimento a mais é realidade. A proximidade com as necessidades da indústria, a infraestrutura de primeira linha e as aulas teóricas, e realmente práticas, são a essência de um modelo de Educação por Competências que possibilita ao aluno adquirir conhecimentos, desenvolver habilidade e garantir seu espaço no mercado de trabalho. Com acesso livre a uma eficiente estrutura laboratorial, com o que existe de mais moderno no mundo da tecnologia, você está construindo o seu futuro profissional em uma instituição que, desde 1954, se preocupa em oferecer um modelo de educação atual e de qualidade. Estruturado com o objetivo de atualizar constantemente os métodos de ensino-aprendizagem da instituição, o Programa Educação em Movimento promove a discussão, a revisão e o aprimoramento dos processos de educação do SENAI. Buscando manter o alinhamento com as necessidades do mercado, ampliar as possibilidades do processo educacional, oferecer recursos didáticos de excelência e consolidar o modelo de Educação por Competências, em todos os seus cursos. É nesse contexto que este livro foi produzido e chega às suas mãos. Todos os materiais didáticos do SENAI Santa Catarina são produções colaborativas dos professores mais qualificados e experientes, e contam com ambiente virtual, mini-aulas e apresentações, muitas com animações, tornando a aula mais interativa e atraente. Mais de 1,6 milhões de alunos já escolheram o SENAI. Você faz parte deste universo. Seja bem-vindo e aproveite por completo a Indústria do Conhecimento.
Sumário Conteúdo Formativo Apresentação
9
38
Seção 6 - Estudo de caso: sistema de cliente
41
Seção 7 - Javabeans
Java Básico
43
Seção 1 - String
45
Seção 2 - Array
Seção 1 - O que é Java?
47
Seção 3 - Construtor
16
Seção 2 - Tipos de distribuições JAVA
48
Seção 4 - Final e static
50
Seção 5 - Estudo de caso: relação de clientes
52
Seção 6 - Tratamento de exceções
16
Seção 3 - Alô SENAI!
19
Seção 4 - O que aconteceu?
19
Seção 5 - Variável
21
Seção 6 - Tipos primitivos de dados
54
Seção 7 - Estudo de caso: objetos de calcular
22
Seção 7 - Promoção e casting
57
Seção 8 - Utilizando pacotes
25
Seção 8 - Operadores aritméticos
25
Seção 9 - Controle de fluxo
29
Seção 10 - Escopo de variável
30
Seção 11 - Usando a documentação do Java
Revendo a Orientação a Objetos Seção 1 - Orientação a objetos: classes, objetos e instâncias Seção 2 - Atributos, métodos, interface, estados e comportamento
Seção 1 - Visão geral
86 Unidade de estudo 7
13
32 Unidade de estudo 2
83
Avançando no Java
12 Unidade de estudo 1
33
Collections
11 42 Unidade de estudo 3
33
82 Unidade de estudo 6
58 Unidade de estudo 4 AWT e Swing 59
Seção 1 - Visão geral
59
Seção 2 - Alô SENAI!
63
Seção 3 - Containers e gerenciadores de layout
64
Seção 4 - Eventos
64
Seção 5 - Estudo de caso: objetos de calcular
JDBC 87
Seção 1 - Visão geral
88
Seção 2 - Interfaces do JDBC
94 Unidade de estudo 8 Apêndice 1 Preparando o Ambiente de Trabalho 95
Seção 1 - Instalando JDK e NetBeans
97
Seção 2 - Instalando o PostgresSQL
100 Unidade de estudo 9 Apêndice 2 - Padrões de Codificação 101 Seção 1 - Classes, interfaces e pacotes
68 Unidade de estudo 5 Arquivos
69
Seção 1 - Visão geral
34
Seção 3 - Os três pilares da orientação a objetos
69
Seção 2 - Manipulando arquivos
34
Seção 4 - Estudo de caso: Tamagotchi com personalidade
76
Seção 3 - Estudo de caso: editor de texto
37
Seção 5 - Visibilidade
102 Seção 2 - Nomeando atributos e variáveis 103 Seção 3 - Métodos 103 Seção 4 - Endentação, comentários, blocos de código, espaços e linhas brancas
Finalizando
104
Referências
106
8
CURSOS TÉCNICOS SENAI
Conteúdo Formativo Carga horária da dedicação Carga horária: 150 horas
Competências Analisar e implementar os recursos avançados da programação orientada a objetos para solução de problemas computacionais.
Conhecimentos ▪▪ Orientação a objetos: classes, objetos e instâncias. ▪▪ Comentários. ▪▪ Composição, agregação. ▪▪ Construtores. ▪▪ Encapsulamento. ▪▪ Herança. ▪▪ Interface de desenvolvimento (IDE). ▪▪ Interfaces gráficas. ▪▪ Métodos e atributos. ▪▪ Padrões de desenvolvimento (frameworks). ▪▪ Padronização de código. ▪▪ Polimorfismo. ▪▪ Reutilização de códigos. ▪▪ APIs. ▪▪ Sobrecarga e sobrescrita de métodos e construtores.
Habilidades ▪▪ Aplicar os conceitos de orientação a objetos. ▪▪ Utilizar interfaces de desenvolvimento (IDE) de sistemas orientado a objetos. ▪▪ Utilizar os padrões de projeto em aplicações computacionais. ▪▪ Desenvolver aplicações para desktop.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
9
Atitudes ▪▪ Organização e zelo na utilização de equipamentos. ▪▪ Foco no conteúdo trabalhado. ▪▪ Acesso a sítios relacionados ao tema trabalhado. ▪▪ Organização e limpeza dos ambientes coletivos. ▪▪ Dedicação e empenho nas atividades curriculares e extracurriculares. ▪▪ Capacidade de abstração. ▪▪ Trabalho em equipe. ▪▪ Apresentação de novas soluções para situações problemas. ▪▪ Cumprimento de prazos. ▪▪ Análise crítica de suas produções.
10
CURSOS TÉCNICOS SENAI
Apresentação Bem-vindo à disciplina de Programação Orientada a Objeto II. Este material foi elaborado para facilitar o seu aperfeiçoamento neste importante paradigma de desenvolvimento de software. A Programação Orientada a Objetos tornou-se um padrão amplamente utilizado, principalmente por limitar a complexidade e permitir soluções elegantes para problemas complexos, características que você verificará no decorrer desta unidade curricular. O grande objetivo deste material é apresentar os conceitos de orientação a objetos na prática. Para isto, serão explorados detalhes da linguagem de programação Java. Esta linguagem consolidou-se e continua expandido o seu uso nos mais diversos projetos. Pela frente há grandes desafios que contribuirão no seu desenvolvimento profissional, e este material o ajudará nesta tarefa, portanto, dedique-se e supere-os! Agora é com você. Bons Estudos!
Diogo Vinícius Winck Bacharel em Ciências da Computação pela Universidade do Estado de Santa Catarina (UDESC), especialista em Redes de Computador e mestre em Ciências da Computação pela Universidade Federal de Santa Catarina (UFSC). Atua como líder técnico do time de Framework na TOTVS (Linha de Produtos Datasul), é Professor Universitário no SENAI Joinville. Em conjunto com Vicente Goetten, foi o autor do livro AspectJ - Programação Orientada a Aspectos com Java -, publicado pela editora Novatec. Atualmente, pesquisa e aplica metodologias ágeis e Lean Software em projetos WEB/RIA, na criação de frameworks e no desenvolvimento de ferramentas.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
11
Unidade de estudo 1 Seções de estudo Seção 1 - O que é Java? Seção 2 - Tipos de distribuições JAVA Seção 3 - Alô Senai! Seção 4 - O que aconteceu? Seção 5 - Variáveis Seção 6 - Tipos primitivos de dados Seção 7 - Casting e promoção Seção 8 - Operadores aritméticos Seção 9 - Controle de fluxo Seção 10 - Escopo de variável Seção 11 - Usando a documentação do Java
Java Básico SEÇÃO 1
O que é Java Em 1995, a Sun lançou uma linguagem de programação chamada Java. Ela foi fruto de um projeto iniciado em 1992 que não deu certo comercialmente. O sucesso inicial aconteceu com os applets, que eram brinquedos para web que, naquela época, era estática. Em 2009, a Sun foi adquirida pela Oracle. O Java se consolidou e, hoje, está presente nas mais variadas empresas, como IBM, Oracle e NASA. Mas por que esse sucesso? Porque o Java consegue lidar bem com problemas comuns das demais linguagens: portabilidade, gerenciamento de memória, custo de ferramenta. Além disso, atualmente, é possível encontrar configurações para o uso dessa linguagem, por exemplo: em servidores web, desktops ou dispositivos móveis. Afinal de contas, o que é o Java? O Java é:
▪▪ um framework/ambiente de execução presente em browsers, mainframes, sistemas operacionais (SO’s), celulares, palmtops, cartões inteligentes, eletrodomésticos.
▪▪ uma linguagem orientada a objetos;
▪▪ Javadoc: ferramenta para geração da documentação em HTML. ▪▪ Tecnologias de Deployment: Java Web Start e plug-ins para distri-
▪▪ uma coleção de APIs (classes,
componentes, frameworks) para o desenvolvimento de aplicações, distribuída gratuitamente por meio do site e neutra de plataforma;
O Java é uma linguagem de alto-nível que pode ser caracterizada como: simples, orientada a objetos, distribuída;
▪▪ multithreaded, dinâmica, portável; ▪▪ independente de arquitetura; ▪▪ de alto desempenho, robusta e segura. A plataforma Java é composta por:
▪▪ JVM: Java Virtual Machine ou Máquina Virtual Java, que é responsável pela execução dos programas. ▪▪ JRE: Java Runtime Environment ou Ambiente de Execução a Java, que é o pacote necessário para executar programas Java, composto pelas bibliotecas e JVM. ▪▪ JDK: Java Development Kit ou Kit de Desenvolvimento Java, que é o kit necessário para desenvolver aplicações, contendo a JRE e ferramentas, como, por exemplo, o compilador Java. Também compõem a plataforma, recursos como:
▪▪ NetBeans: ambiente de desenvolvimento de código aberto para aplicações JSE, JME e JEE.
buição de aplicações.
▪▪ User Interface Tookits: Java Foundation Classes, formado por Swing e
Java 2D(Awt).
▪▪ Integration Libraries: bibliotecas de integração, tais como, Java IDL, JDBC, JNDI, Java RMI e Java RMI-IIOP.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
13
Figura 1: Visão geral da plataforma Java Fonte: Adaptada de Oracle (2011)
As APIs (Application Programming Interface ou Interface de Programação de Aplicativos) Java mais conhecidas do JSE são:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
java.io – manipulação de arquivos; java.lang – classes básicas do Java; java.net – infraestrutura de software para rede; java.nio – definição de buffers; java.security – classes para segurança; java.text – textos, datas, números, mensagens; java.util – utilitários, coleções, datas etc; java.util.concurrent – programação concorrente.
A estrutura da linguagem é mantida por um processo chamado JCP (Java Community Process). Existem outras implementações dos padrões definidos pelo JCP, além da disponibilizada pelo Oracle, como: O JCP é um processo no qual, as partes interessadas na definição da plataforma Java ou de novas funcionalidades podem se envolver, respondendo aos JSRs (Java Specification Requests), sugerindo, por exemplo, melhorias.
Outra característica foi o desenvolvimento de uma cultura de partilha de informações – existem muitos grupos de usuários onde se compartilham informações. Além disso, são publicados, diariamente, na internet informações, artigos e tutorias.
14
CURSOS TÉCNICOS SENAI
Neutralidade de plataforma indica que qualquer programa desenvolvido pode executar sem modificações em diferentes plataformas de computação (exemplo: Linux, Windows etc.). Esta capacidade deve-se ao fato de que os programas são compilados para o um formato chamado bytecode. Este é utilizado pela máquina virtual Java, que interpreta as instruções. A figura a seguir, ilustra o funcionamento da linguagem.
Figura 2: Funcionamento e Distribuição do Java
Durante a execução, a API e a JVM (Java Virtual Machine ou Máquina Virtual Java) “isolam” o programa Java do sistema operacional, esta relação pode ser observado na figura a seguir.
A máquina virtual corresponde a um computador abstrato e, por conta desse modelo, é possível a sua construção por meio de hardware. Quando uma aplicação Java é executada em uma máquina comum, faz-se necessário uma implementação concreta dessa abstração e isso se torna disponível por meio da instalação e configuração do JRE. Durante a execução, cada aplicação Java (o bytecode) executa dentro da sua própria instância da JVM, permitindo um alto grau de isolamento e segurança. O código compilado no Java é portável entre versões diferentes da JVM, por isso, o desenvolvedor não precisa preocupar-se com detalhes da JVM no ambiente de execução. Uma instância (runtime) é criada quando a aplicação inicia e destruída quando a aplicação termina, isso implica, por exemplo, que três aplicações ao mesmo tempo, demandam três JVMs. As etapas de execução de um programa Java são: 1. Class Loader: esta é primeira atividade executada pela JVM, sendo responsável por carregar as classes necessárias para rodar a aplicação. A sequência da carga é: a. carrega as classes nativas do JRE – Java Runtime Environment (Ambiente de Execução Java em uma tradução livre). b. são carregadas as extensões do JRE, disponíveis, por exemplo, em $JAVA_HOME/jre/lib/ ext c. são carregadas as classes do sistema local, a ordem definida na variável de classpath define a precedência.
Figura 3: Execução de um programa Java
d. são carregadas as classes do sistema remotas, disponíveis, por exemplo, em um servidor.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
15
2. Bytecode Verifier: nesta etapa os Classes Javas (bytecodes) carregadas da dinamicamente/ intranet/internet são verificadas antes de serem executadas, pois o Class Loader considera as classes remotas potencialmente inseguras. Verifica-se, por exemplo, se o formato do arquivo recebido está correto ou se não há violações de segurança. 3. Execução: o programa é executado. 4. Garbage Collection: esta é a coleta de lixo. Durante a execução de um programa objetos são alocados. Quando estes deixam de ser necessários, precisam ser eliminados da memória, disponibilizando espaço que era utilizado por ele. Em linguagens como C++ e Pascal, o programador deve realizar essa tarefa. No Java, a responsabilidade está delegada ao Garbage Collector (coletor de lixo). Ele deve identificar, marcar e eliminar da memória objetos que não são mais referenciados de maneira válida.
▪▪ Java Standard Edition (JSE): voltada para desenvolvimento de aplicações cliente e composta pelas APIs básicas do Java. Disponibiliza, por exemplo, APIs para desenvolvimento de telas. ▪▪ Java Enterprise Edition (JEE): permite melhor componentização das aplicações. É utilizada para desenvolvimento de aplicações empresariais, como, por exemplo, comércio eletrônico. ▪▪ Java Micro Edition (JME): projetado para atender às necessidades de desenvolvimento para aplicativos móveis, como celulares. ▪▪ Java Card: fornece um ambiente seguro para que aplicações rodem
em smart cards e outros dispositivos com grande limitação de memória e de capacidade de processamento. Isso possibilita o uso de ferramentas de mercado para a criação das aplicações e as aplicações desenvolvidas podem ser executadas com segurança em cartões de diferentes fornecedores.
▪▪ Java TV: refere-se à JSR-927, que trata da especificação para TV digital.
SEÇÃO 3 Alô Senai!
A realização desta seção, e das próximas, depende de preparação do ambiente de trabalho, segundo a unidade de estudo 8 (Apêndice 1). A melhor forma de iniciar o entendimento, ou a relembrar como funciona uma linguagem, é por meio de exemplos simples. Nesta seção, será elaborado um primeiro programa: Alô Senai!, que irá imprimir uma linha simples no console: “Alô Senai!”. A realização dessa tarefa será feita no Netbeans. Estando ele aberto, deve-se criar um novo projeto chamado JavaBasico. Na figura a seguir, são detalhados os passos para fazer isso.
SEÇÃO 2
Tipos de distribuições JAVA A partir de 2009, a tecnologia Java passou por um amplo processo segmentação de sua atuação, principalmente, após a aquisição da Sun pela Oracle. Várias plataformas foram derivadas para necessidades específicas. Destacam-se algumas:
Figura 4: Novo projeto no NetBeans
16
CURSOS TÉCNICOS SENAI
Podem-se observar alguns pontos importantes no arquivo apresentando. Na figura 5, esses pontos são detalhados.
Figura 5: Exemplo de arquivo Java
O próximo passo é adicionar ao main, o seguinte trecho de código de modo, então o projeto ficará como na figura 6.
System.out.println(“Alo Senai!”);
Figura 6: Código fonte do programa AloSenai
PROGRAMAÇÃO ORIENTADA A OBJETOS II
17
Alguns pontos sobre este exemplo merecem destaque.
▪▪ O método main indica que a classe é um ponto de entrada de aplicação.
▪▪ public é um modificador de acesso (será visto na seção de Orientação a objetos). ▪▪ static é um modificador que indica que o método pertence a classe e não a uma instância.
▪▪ System é uma classe padrão e possui vários métodos úteis sobre a plataforma que está sendo executada, como E/S.
▪▪ // e /* */ são comentários. ▪▪ void é o valor de retorno do método. Quando um método não
retorna nenhum valor, uma espécie de valor vazio tem que ser especificado.
▪▪ String args [ ] é um vetor de strings que é formado quando são passados ou não argumentos por meio da linha de comando. ▪▪ System.out.println apresentada no console, a mensagem passada como parâmetro e entre aspas. Se for utilizado o System.out.print não será feita a quebra de linha no final da mensagem. O Netbeans torna a execução dos projetos criados de maneira bem simples. Na figura a seguir, pode-se observar como executar esse primeiro exemplo. Pode-se também ver o resultado da execução. Confira.
Figura 7: Resultado da execução
Alguns erros podem acontecer na execução, por descuido do desenvolvedor. É importante considerar algumas características da linguagem Java:
▪▪ ela diferencia letras maiúsculas de minúsculas (case-sensitive). Se o desenvolvedor escrever SYSTEM ao invés de System um erro será acusado;
▪▪ as linhas de comando finalizam com ; (ponto-e-vírgula); ▪▪ todo sinal de ‘abre chaves’ deve possuir um sinal de ‘fecha chaves’
correspondente.
18
CURSOS TÉCNICOS SENAI
SEÇÃO 4
O que aconteceu? Quando foi acionado o botão executar projeto, o NetBeans compilou o código Java, gerando um ByteCode. Além disto, iniciou a máquina virtual Java (JVM), indicando para ela onde estava o código recém gerado. A Máquina Virtual Java procurou no ByteCode por um método main. Este é utilizado como ponto de entrada das aplicações Java Desktop. Um esquema dessa execução já foi detalhado na figura 3. Durante a execução, a JVM identificou a chamada para o método println, presente no atributo out da classe System. O método println imprime, na saída padrão, a String passada por parâmetro. Nesse exemplo, a saída padrão era o console de execução e a String passada era “Alô Senai!”. Altere o exemplo adicionando ‘\n’ ao final de mensagem. Ele é um caractere especial de saída que informa ao sistema se a saída em tela terá alguma característica diferente, nesse caso será uma quebra de linha. Confira alguns caracteres especiais de saída que podem ser testados: \n \t \r \\ \ “
nova linha; tabulação; retorno do carro (impressora); barra inversa; aspas duplas.
Essa mesma operação poderia ser feita por meio do console do sistema operacional. Portanto, seria preciso utilizar o comando javac para compilar o programa. E o comando java instanciar a máquina virtual e executar o bytecode. No ambiente, o Windows ficaria da seguinte maneira:
C:\\javac AloSenai.java C:\\java AloSenai
SEÇÃO 5 Variável
Uma variável é uma região de memória capaz de reter e representar um valor ou expressão. Ela possui um identificador e um tipo de dado. O identificador é o nome dado a uma variável, método, atributo, interface ou classe. Na linguagem Java, as variáveis são fortemente tipadas. Isso indica que toda declaração de uma variável deve explicitar o tipo de dado que a variável poderá tratar.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
19
O tipo de dado especifica as operações que uma variável pode executar, os valores que pode conter, por exemplo, uma variável para armazenar a idade de um aluno pode ser do tipo inteira. Sendo inteira, ela armazena apenas números inteiros. A forma geral de declaração de variável é: tipoVariável identificadorVariável;
O desenvolvedor, que deseja declarar uma variável para armazenar os juros de um empréstimo, poderia fazer da seguinte forma: double juros;
São permitidas algumas variações. Veja: double juros = 0.05; //declaração com atribuição do valor double vlParcela, vlEmprestimo; //declaração de múltiplas variáveis
Na figura 8, é um exemplo de onde o desenvolvedor gostaria de calcular o valor de um empréstimo, utilizando juros simples, e exibir, no console, o resultado.
Figura 8: Cálculo da parcela de um empréstimo
20
CURSOS TÉCNICOS SENAI
O Java impõe regras na criação de identificadores (nome de variáveis). São elas:
▪▪ deve-se ter atenção quanto ao uso de letras maiúsculas e minúsculas; ▪▪ deve-se iniciar com: uma letra, o sinal de cifrão “$” ou com um
sinal de sublinhado “-“;
▪▪ pode-se utilizar caracteres Unicode e ter qualquer tamanho. Não
deve conter espaços;
▪▪ Não se deve utilizar as palavras reservadas, contidas na tabela a seguir. Tabela 1: Palavras reservadas do Java
▪▪ byte – representa um valor inteiro. Seu tamanho é 1 byte. Pode armazenar os valores de -128 a 127. O valor padrão para o byte é 0. Exemplo: byte semana = 0; ▪▪ short – representa um valor inteiro com 2 bytes de tamanho. Pode armazenar os valores de -32.768 a 32.768. O valor padrão para o short é 0. Exemplo: short dia = 0;
abstract
continue
for
New
switch
assert
default
goto
package
synchronized
boolean
do
if
private
this
break
double
implements
protected
throw
▪▪ int – representa um valor inteiro com 4 bytes de tamanho. Pode armazenar os valores de -2.147.483.648 a 2.147.483.647. O valor padrão para o int é 0. Exemplo: int idade = 30;
byte
else
import
public
throws
▪▪ long – representa um valor
case
enum
instanceof
return
transient
catch
extends
int
short
try
char
final
interface
static
void
class
finally
long
strictfp
volatile
const
float
native
super
while
Além dessas regras, existe uma convenção amplamente aceita pelos desenvolvedores da comunidade Java, que pode ser observada na unidade de estudo 9 (apêndice 2).
SEÇÃO 6
Tipos primitivos de dados Existem oito tipos de dados primitivos. Eles são chamados de primitivos, pois correspondem diretamente a regiões de memória e não ponteiros para objetos na memória. Confira:
▪▪ boolean – representa um valor lógico. Pode armazenar os valores
true ou false. O valor padrão para o boolean é false. Exemplo: boolean cancelou = false;
▪▪ char – representa qualquer caractere (Unicode) entre aspas simples.
Seu tamanho é 2 bytes. Pode armazenar valores entre ‘\u0000’ a ‘\ uFFFF’. O valor padrão para o char é ‘\u0000’. Exemplo: char sexo = ‘M’;
inteiro com 8 bytes de tamanho. Pode armazenar os valores de -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807. O valor padrão para o long é 0L. Exemplo: long inteiroGrande = 9.223.372.036.854.775.807L;
▪▪ float – representa um valor real com 4 bytes de tamanho, definido segundo a norma IEEE754. Pode armazenar valores entre 1.40129846432481707e-45 a 3.40282346638528860e+38. O valor padrão para o float é 0.0f. Exemplo: float pi = 3.14f; ▪▪ double – representa um valor
real com 8 bytes de tamanho, definido segundo a norma IEEE754. Pode armazenar valores entre 4.94065645841246544e-324 a 1.79769313486231570e+308. O valor padrão para o double é 0.0d. Exemplo: double estrelas = 1e40; double preco = 119.99; Nenhuma variável pode ser usada antes de ser inicializada. Mais exemplos de uso de variáveis podem ser observados na figura 9.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
21
Os tipos primitivos, por não serem objetos, não possuem operações que permitam realizar manipulações elaboradas, como, por exemplo, conversão para Strings. Essa deficiência foi suprida pela criação dos objetos Wrappers. Os objetos Wrapper correspondem ao objeto do tipo primitivo. Para cada tipo primitivo existe um wrapper. Confira na tabela a seguir. Tabela 2: Objetos Wrappers
Tipo primitivo Classe wrapper
Métodos de conversão String -> tipo
boolean
Boolean
Boolean.parseBoolean (String vl)
byte
Byte
Byte.parseBype(String vl)
char
Character
String.charAt(int pos)
double
Double
Double.parseDouble(String vl)
float
Float
Float.partFloat(String vl)
int
Integer
Integer.parseInt(String vl)
long
Long
Long.parseLong(String vl)
short
Short
Short.parseShort(String vl)
Os objetos wapper disponibilizam operações, como:
▪▪ ValueOf(): retorna o objeto wrapper criado; ▪▪ parseInt(), parseDouble() ou parseX() – de acordo com o wrapper
em questão: retorna o tipo primitivo nomeado;
▪▪ toString(): retorna a String com o valor do tipo primitivo encapsula-
do no objeto.
Figura 9: Exemplos de declaração e uso de variáveis
22
CURSOS TÉCNICOS SENAI
SEÇÃO 7
Promoção e casting Na seção anterior, pôde-se observar que cada tipo de variável possui um tamanho e um formato: algumas suportam caractere, outras suportam números inteiros ou reais. Por conta destas diferenças, deve-se tomar um pouco de cuidado ao atribuir variáveis de tipos diferentes. Quando se atribui uma variável, com tipos de dados mais restritos, para outra com tipo de dado mais amplo, isso é chamado de promoção. Nesses casos, não há preocupações: a JVM faz conversão automática. Por exemplo, atribuir, uma variável do tipo short (menor) para outra variável do tipo int (maior): não há problema! Alguns exemplos de promoção podem ser observados a seguir: byte short int long float double
var0 = 10; var1 = var0; var2 = var1; var3 = var2; var4 = var3; var5 = var4;
Há dois casos especiais: float, mesmo sendo menor em tamanho na memória que o long, pode receber valores de long, por conta do padrão que ele utiliza para armazenar. O segundo caso é o da promoção de char, que só pode ser feita para int (e superiores). Uma característica da promoção é que não há risco de perda de precisão, e, por isso, a JVM faz automaticamente. Entretanto, há casos onde é necessário igualar valores, mesmo que haja risco de perda de precisão. Nesses casos, a JVM não pode decidir pelo desenvolvedor e é necessário realizar um cast, caso ilustrado na figura 10. Pode-se, também, observar a mensagem dada pelo compilador.
Figura 10: Problemas de conversão
A mensagem de erro por incompatibilidade entre tipos de classes é apresentada da seguinte maneira:
Exception in thread “main” java.lang.RuntimeException: Uncompilable source code - possible loss of precision required: int found: double at Arredondamento.main(Arredondamento.java:13)
Nesse caso, e em situações similares, faz-se necessário, realizar um casting, indicando, explicitamente para a JVM, a conversão que deve ser feita. O tipo desejado é colocado entre parênteses e usado como um prefixo para a expressão que deve ser modificada. Na figura 11, pode-se observar o exemplo anterior corrigido de modo a utilizar o cast. Observe o formato padrão do casting.
tipoDado variavelDestino = (tipoDado) variavelOrigem;
PROGRAMAÇÃO ORIENTADA A OBJETOS II
23
Figura 11: Conversão utilizando cast
Na tabela a seguir, podem ser observados todos os possíveis casos de casts/promoções, presentes na linguagem Java. Nos casos em que aparece promo, significa que a conversão é automática. Nos demais, é apresentado o cast que deve ser utilizado. Tabela 3: Tabela de conversão
PARA
byte
short
char
int
long
float
double
byte
----
promo
(char)
promo
promo
promo
promo
short
(byte)
---
(char)
promo
promo
promo
promo
char
(byte)
(short)
---
promo
promo
promo
promo
int
(byte)
(short)
(char)
---
promo
promo
promo
long
(byte)
(short)
(char)
(int)
---
promo
promo
float
(byte)
(short)
(char)
(int)
(long)
----
promo
double
(byte)
(short)
(char)
(int)
(long)
(float)
----
DE
Fonte: adaptado de Caelum (2010)
24
CURSOS TÉCNICOS SENAI
SEÇÃO 8
Operadores aritméticos Você sabe quais são os operadores aritméticos disponibilizados pelo Java? Não? Então confira: Adição ‘+’. Exemplo: total = a + b; Subtração ‘– ‘. Exemplo: total = a – b; Multiplicação ‘*’. Exemplo: total = a * b; Divisão ‘/’. Exemplo: total = a / b; Módulo (resto de divisão inteira) ‘%’. Exemplo: total = a % b; Este operador pode ser usado, somente, quando ambos operandos são inteiros.
SEÇÃO 9
Controle de fluxo Agora que você já sabe quais são os operadores aritméticos, confira algumas informações sobre o controle de fluxo. O entendimento sobre a estrutura de execução de programas em Java está ligado à compreensão do conceito de bloco de código. Blocos de código delimitam conjuntos de comando, possibilitando tratar escopo de variáveis, sincronia entre processos e controlar exceções. Um bloco é delimitado por chaves { }.Observe um trecho de código, onde há dois blocos de código:
if( condição booleana ) { //código do if } else{ /* código do else. Importante observar que o bloco do else pode ser suprimido */ }
Os dois blocos de códigos do trecho apresentado, são:
▪▪ o primeiro vinculado ao if. ▪▪ o segundo vinculado ao else. O Java disponibiliza as seguintes estruturas de controle de fluxo:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪
if-els; while; do-while; for; switch. PROGRAMAÇÃO ORIENTADA A OBJETOS II
25
If-else é a estrutura de testes. Dependendo da satisfação da condição declarada, executa um determinado bloco de código, senão, caso exista, é executado o bloco complementar. A sintaxe geral do if-else pode ser observada no quadro 1.10. Uma condição booleana é uma expressão que utiliza um conjunto de operadores relacionais (tabela 4) e/ou operadores lógicos (tabela 5). O seu resultado é um valor booleano. Os operadores relacionais são: Tabela 4: Operadores relacionais
Operador
Símbolo
Exemplo
Resultado
maior
>
A>B
Verdadeiro se A maior que B, senão, falso
menor
<
A
Verdadeiro se A menor que B, senão, falso
maior ou igual
>=
A >= B
Verdadeiro se A maior ou igual a B, senão, falso
menor ou igual
<=
A <= B
Verdadeiro se A menor ou igual a B, senão, falso
igual
==
A == B
Verdadeiro se A igual B, senão, falso
diferente
!=
A != B
Verdadeiro se A diferente B, senão, falso
Tabela 5: Operadores lógicos
Operador
Símbolo
Exemplo
Resultado
E
&&
A && B
Verdadeiro se A e B forem verdadeiros, senão, falso.
OU
||
A || B
Verdadeiro A, B ou A e B forem verdadeiros, senão, falso
Negação
!
!A
Verdadeiro se A for falso, senão, falso
Na figura a seguir, pode-se ver um programa que avalia se um cliente pode entrar em um determinado show.
Figura 12: Exemplos de If-else
26
CURSOS TÉCNICOS SENAI
O uso de vários operadores é mediado, segundo regras de precedência. Essas regras podem ser observadas na tabela 6. Tabela 6: Operadores lógicos
Operador pós-fixado unário multiplicação adição/subtração descolamento relacional igualdade bitwise AND bitwise exclusive OR bitwise inclusive OR lógico AND lógico OR ternário atribuição
Precedência expr++ expr-++expr --expr +expr -expr ~ ! */% +<< >> >>> < > <= >= instanceof == != & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= >>>=
Maior precedência
Menor precedência
O while é a estrutura de repetição, desviando o fluxo de um programa, de modo que repita um bloco de código, enquanto uma determinada condição booleana for verdadeira. A sintaxe geral do if-else pode ser observada a seguir.
while( condição booleana ) { //código }
Observe na figura a seguir, um programa que calcula os números da série de Fibonacchi menores que 100, sendo eles: { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 e 89}.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
27
Figura 13: Exemplo de while – série de Fibonacci
Outra estrutura de repetição amplamente utilizada é o for. Essa estrutura deve ser usada, quando se deseja controlar a quantidade de vezes que serão executados um determinado bloco de código. O fluxo de um programa é desviado, de modo que repita um bloco de código, enquanto uma determinada condição booleana for verdadeira. A sintaxe geral do for pode ser observada a seguir.
for(inicialização, condição booleana, incremeto ) { //código }
Na figura 14, pode-se observar um programa que calcula os 10 primeiros números da série de Fibonacchi, dessa vez, utilizando um for.
28
CURSOS TÉCNICOS SENAI
Figura 14: Exemplo de for – série de Fibonacci
A linguagem Java permite controlar o fluxo de execução dos laços de repetição, utilizando as palavras-chave:
▪▪ break – interrompe a execução do laço, o fluxo continuará executando o próximo comando, após a estrutura. O break não consegue sair de todas as estruturas encadeadas, sendo necessário o uso de múltiplos breaks nesses casos; ▪▪ continue – faz com que seja interrompida a execução do bloco de
código, passando para próximo ciclo do laço. A estrutura de repetição continua sendo executada a partir do seu início.
SEÇÃO 10
Escopo de variável O escopo de uma variável é o alcance que uma variável possui, permitindo o seu acesso ou mesmo a sua existência. O escopo é definido pelos blocos de código, onde essa variável foi declarada, existe e pode ser acessada. Na figura 15, pode-se observar um exemplo de um problema relacionado a escopo. Nesse trecho de código é declarada uma variável em um bloco de código e o desenvolvedor tenta acessá-la em outro, ocasionando o problema. Duas variáveis são criadas: contaLacoInterno e contaLacoExterno.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
29
A variável contaLacoExterno possui o escopo mais amplo, sendo declarada no main. Ela pode ser utilizada em qualquer lugar no método após a sua criação.A variável contaLacoInterno possui seu escopo restrito ao bloco de código do while. Após o fechamento desse bloco, ela deixa de existir, sendo eliminada pelo Garbage Collector. Tentativas de acesso à ela, geram um erro de compilação.
Figura 15: Escopo de variável
SEÇÃO 11
Usando a documentação do Java A documentação da linguagem, ferramentas e API podem ser acessadas online no site da Oracle ou pode ser feito um download separado do SDK. Ela é composta por uma coleção de arquivos HTML, com as classes e métodos da linguagem Java. A documentação é hierárquica, de forma que a página inicial lista todos os pacotes como hyperlinks. Na figura 16, pode-se observar um exemplo de documento. Todo projeto pode ter sua documentação, gerada, automaticamente, nesse formato, por meio do uso da ferramenta javadoc. As páginas são estruturadas nos seguintes tópicos:
▪▪ ▪▪ ▪▪ ▪▪
30
CURSOS TÉCNICOS SENAI
a hierarquia da classe; uma descrição da classe e seu propósito geral; uma lista de variáveis associadas; uma lista de construtores;
▪▪ uma lista de métodos; ▪▪ uma lista detalhada de variáveis, com descrições do propósito e uso
de cada variável;
▪▪ uma lista detalhada de construtores, com descrições. ▪▪ uma lista detalhada de métodos, com descrições.
Figura 16: Exemplo de documentação
Nessa primeira unidade de estudos, você conheceu um pouco sobre Java, na próxima unidade, você irá revisar os conceitos de orientação a objetos e conhecer um estudo de caso. Prepare-se, vem muita coisa interessante pela frente!
PROGRAMAÇÃO ORIENTADA A OBJETOS II
31
Unidade de estudo 2 Seções de estudo Seção 1 – Orientação a objetos: classes, objetos e instâncias Seção 2 – Atributos, métodos, interface, estados e comportamento Seção 3 – Os três pilares da orientação a objetos Seção 4 – Estudo de caso: Tamagotchi com personalidade Seção 5 – Visibilidade Seção 6 – Estudo de caso: sistema de cliente Seção 7 – Javabeans
Revendo a orientação a objetos SEÇÃO 1
Orientação a objetos: classes, objetos e instâncias Aplicar o paradigma de desenvolvimento orientado a objeto exige o pleno conhecimento dos conceitos que envolvem a orientação a objetos (OO), por isso, é importante revisar os conceitos que a compõem. O termo orientação a objetos remete à tentativa de simular nos computadores, aquilo que o desenvolvedor percebe no mundo real. Procura-se trazer para o desenvolvimento da solução, os elementos presentes no problema, que se procura resolver na forma de abstrações. Uma abstração é uma simplificação concentrada nas características relevantes do elemento avaliado. Pode-se simplificar o esforço presente no Paradigma Orientado a Objeto (POO), no esforço realizado pelo desenvolvedor na procura por identificar as características de um problema, decompondo a solução em um conjunto de objetos definidos por classes. Um objeto é uma construção de software, que encapsula estado e comportamento, permitindo que se modele software em termos reais e abstratos. Podem ser de vários tipos, como entidades físicas: nota-fiscal, cliente, aluno etc.; abstratas: listas, pilhas, vetores, conexões etc. Não seria produtivo durante o desenvolvimento, codificar cada objeto isoladamente. Imagine, o desenvolvedor precisa criar um código para cada aluno de uma escola, ou funcionário de uma empresa. Por conta disso, os objetos são agrupados pelos seus métodos e atributos comuns, formando uma classe de objetos. As classes implementam as responsabilidades de um sistema. Nelas são definidos atributos e métodos. Elas são como formas, utilizadas para modelar os biscoitos. São utilizadas para definir a forma inicial, mas a partir do momento em que os biscoitos são retirados, passam a se diferenciar uns dos outros. Cada solução teria a necessidade de classes diferentes, por exemplo:
▪▪ um sistema de gerenciamento escolar teria classes como: Aluno, Professor, Contrato, Sala etc.; ▪▪ tratando-se de um sistema para controle de locadoras poderiam exis-
tir as classes: Cliente, Filme, Mídia etc.;
▪▪ no caso de um sistema de controle empresarial seriam necessárias classes como Funcionário, Gerente, Cliente, Setor, Item etc.
SEÇÃO 2
Atributos, métodos, interface, estados e comportamento Os atributos são características relevantes de uma classe de objetos para a solução de um problema, sobre os quais podem ser executadas ações. O estado de um objeto é determinado pelo conjunto dos valores dos atributos. Para evitar estados inválidos ou inconsistentes e acessos indevidos, os atributos devem ser apenas manipuláveis por operações do próprio objeto. Um comportamento é uma ação executada por um objeto em resposta a alguma mensagem ou mudança de estado. Ele é acionado pela execução de algum método. Entretanto, essa relação não é explícita, já que um mesmo comportamento pode ser realizado por vários métodos. Os métodos são operações (ações) explicitamente detalhadas e codificadas nas classes. O conjunto das operações públicas de um objeto forma a lista de serviços disponibilizados. A esse serviço é dado o nome de interface do objeto. Uma interface é um contrato com o mundo exterior, informando o que um objeto pode fazer, mas não sua implementação. Uma interface não possui implementação e não pode ser instanciada.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
33
Cada classe de solução teria a necessidade atributos diferente, por exemplo:
▪▪ em um sistema de gerenciamento escolar, a classe Aluno precisaria
de atributos como: nome, endereço, telefone, número da matrícula etc.
▪▪ num sistema para controle de locadoras, a classe Filme necessitaria de atributos como: nome, gênero, ano de lançamento etc. ▪▪ no caso de um sistema de controle empresarial, a classe funcionário precisaria de atributos como: nome, endereço, setor e etc. Na figura a seguir, você pode observar um diagrama que reúne todas as informações aprendidas até agora.
O polimorfismo é a capacidade de uma mesma referência, como, por exemplo, um ponteiro para objetos, representar implementações diferentes, sendo que a implementação é selecionada por algum mecanismo automático, assim, permite-se que um único nome expresse comportamentos diferentes, possibilitando a utilização de um mesmo nome de método em mais de uma classe e, ainda, assuma implementações diferentes em cada classe.
SEÇÃO 4
Estudo de caso: Tamagotchi com personalidade
Figura 17: Diagrama dos conceitos da orientação a objetos Fonte: Adaptado de Winck e Goetten (2006)
Tamagotchi é um brinquedo, lançado pela empresa Bandai(1996). O seu objetivo era criar um animal de estimação virtual. Normalmente, esse brinquedo era apresentado como um chaveiro.
SEÇÃO 3
Os três pilares da orientação a objetos A orientação a objetos está apoiada em três pilares essenciais: encapculamento, herança e polimorfismo. Veja um pouco mais sobre cada um deles. O encapsulamento é uma característica desejável na implementação de sistemas OO. Ele permite conhecer o que é feito, mas ignora-se o modo como é feito. Na OO, o encapsulamento é o pacote formado pelas operações e pelo conjunto de atributos de um objeto. Ele protege a estrutura interna de cada objeto contra a utilização arbitrária, que fuja dos objetivos propostos pelo projeto da classe. A herança é um mecanismo para reuso de código que possibilita a criação de uma classe baseada em outra previamente existente. A nova classe irá receber as características da classe-base, utilizando as partes comuns e especializando os pontos onde a classe derivada necessita de um comportamento mais específico.
34
CURSOS TÉCNICOS SENAI
Figura 18: Tamagotchi
Nele, eram reproduzidos vários comportamentos de um bicho de estimação real. O proprietário era obrigado, por exemplo, a alimentar, passear, medicar, brincar com seu companheiro virtual etc., caso não fosse cuidado, adequadamente, o bichinho poderia morrer. Inspirado nos Tamagotchi, este estudo de caso simulará apenas o humor de um animal de estimação.
Observe na figura a seguir, um diagrama de classes desse estudo de caso.
Figura 19: Figura 19: Diagrama de classes
Esse exercício depende da criação de novas entidades: Animal, Humor, Alegre, Agitado, Triste e Bravo. Como o desejo é tratar apenas o humor do animal de estimação, este, quando solicitado, irá se apresentar e indicar o seu humor. Tal comportamento será implementado por meio de um método, no caso, falar(). Veja o código da classe Animal:
public class Animal { private String nome = “”; private Humor humor; Animal(String nome){ this.nome = nome; } public Humor getHumor() { return humor; } public void setHumor(Humor humor) { this.humor = humor; } public String getNome() { return nome; } public void falar(){ System.out.println(“Oi! Meu nome é “+nome); System.out.println(“Hoje eu estou “+humor.toString()); } }
A classe Animal está associada à classe personalidade, que, por sua vez, possui quatro especializações: Agitado, Alegre, Bravo e Triste. No exemplo, a classe Animal não sabe detalhes (encapsulamento) sobre as classes especializadas de humor. Essa classe sabe que ao solicitar a operação toString (sobreposição/polimorfismo) da classe humor, receberá o texto correto.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
35
Na figura 19 você pôde ver o uso dessas classes. Os códigos das demais classes você confere a seguir.
Código fonte da classe Humor public class Humor { public String toString() { return “Normal”; } }
Código fonte da classe Agitado public class Agitado extends Humor{ public String toString() { return “Agitado”; } }
Código fonte da classe Alegre public class Alegre extends Humor{ public String toString() { return “Alegre”; } }
Código fonte da classe Bravo public class Bravo extends Humor{ public String toString() { return “Bravo”; } }
Código fonte da classe Triste public class Triste extends Humor{ public String toString() { return “Triste”; } }
36
CURSOS TÉCNICOS SENAI
Figura 20: Programação dos códigos e classes
SEÇÃO 5 Visibilidade
O encapsulamento só é garantido se a classe restringir o acesso direto a seus elementos. Um bom exemplo é uma classe que representa um carro. A velocidade do carro é resultado dos métodos acelerar/frear e não da alteração direta da propriedade velocidade.Na implementação, feita no Java da orientação a objetos, foram disponibilizados quatros tipos de visibilidade ou controles de acesso:
▪▪ public (público) - permite o acesso a todos os objetos; ▪▪ protected (protegido) – garante acesso à instância, ou seja, para
aquele objeto e para todas as subclasses;
▪▪ private (privado) – garante acesso apenas para a instância. ▪▪ default (pacote) – não é uma visibilidade padrão da orientação a ob-
jetos. Está disponível no Java e permite acesso a instâncias do mesmo pacote da classe.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
37
Nenhum atributo de uma classe deve ser declarado como público, e acessado diretamente por um objeto externo, a menos que haja uma grande justificativa.
Os atributos devem possuir métodos de acesso get/set, possibilitando a sua manipulação controlada. Isto pode ser observado na classe Animal nos atributos nome e humor.
SEÇÃO 6
Estudo de caso: sistema de cliente Uma empresa necessita controlar seus clientes. O diretor comercial dessa empresa deseja ter acesso ao nome do cliente, telefone e endereço. Os clientes possuem um valor máximo para compra, se tentar comprar além do que o valor permitido, o sistema não deve impedir. Um cliente pode ser considerado especial, pois, ele não possui limite no valor de compras. Nesses casos, também, se deseja saber o nome da pessoa de contato e o telefone dela. Se um cliente estiver devendo, é importante que seja informado qual cliente está devendo. Um cliente devedor não pode fazer novas compras. Analisando o problema, modelou-se o digrama. Confira na figura a seguir.
Figura 21: Diagrama de classes para um sistema de controle de clientes
A classe Cliente possuirá os seguintes atributos: nome, telefone, endereco e limite de compras. Deve possuir um método que avalia se uma determinada compra pode ser feita. Observe o código da classe Cliente:
38
CURSOS TÉCNICOS SENAI
package org.senai.cliente; public class Cliente { private String nome; private String telefone; private String endereco; private double limiteCompras; public Cliente() { } public Cliente(String nome) { this.nome = nome; } public void setNome(String nome) { this.nome= nome; } public String getNome() { return nome; } public String getEndereco() { return endereco; } public void setEndereco(String endereço) { this.endereco = endereço; } public double getLimiteCompras() { return limiteCompras; } public void setLimiteCompras(double limiteCompras) { this.limiteCompras = limiteCompras; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public boolean liberarCompra(double value){ return value <= limiteCompras; } public String toString() { return “Cliente:”+ nome + “ Telefone=” + telefone + “ Endereço=” + endereco + “ Limite de Compras=” + limiteCompras; } }
É importante observar que todos os atributos são privados. O acesso a eles só pode ser feito via métodos get/set. A seguir você pode observar o código da classe cliente especial. Ela é uma especialização da classe Cliente e, por isso, não é necessário redefinir os atributos nome, telefone, endereço e limite de crédito.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
39
package org.senai.cliente; public class ClienteEspecial extends Cliente { private String nomeContato; private String telefoneContato; public ClienteEspecial() { super(); } public ClienteEspecial(String nome) { super(nome); } public boolean liberarCompra(double value) { return true; } public String getNomeContato() { return nomeContato; } public void setNomeContato(String nomeContato) { this.nomeContato = nomeContato; } public String getTelefoneContato() { return telefoneContato; } public void setTelefoneContato(String telefoneContato) { this.telefoneContato = telefoneContato; } public String toString() { return “Cliente Especial \tnome:”+getNome() + “ Telefone:” + getTelefone()+ “ Endereco:” + getEndereco() +” Contato: “+nomeContato+ “ Telefone Contato:”+telefoneContato + “ Limite de Compras: sem limite” ; } }
Por conta da lógica do negócio, foram redefinidas a construtora e o método liberarCompra – um cliente especial possui compras sempre liberadas. Observe, também, a criação de dois novos atributos: nomeContato e telefoneContato, e os respectivos métodos get/set. Na construtora, pode-se ver a aplicação do operador super. Aqui, ele indica que está sendo chamada a construtora da classe pai. No exemplo a seguir, pode-se observar o código da classe cliente devedor. Assim como, cliente especial, ela é uma especialização da classe Cliente e, por isso, não é necessário redefinir os atributos: nome, telefone, endereço e limite de crédito. Foram redefinidas a construtora e o método liberarCompra, por conta, da lógica de negócio e, agora, um cliente devedor não pode fazer compras.
40
CURSOS TÉCNICOS SENAI
package org.senai.cliente; public class ClienteDevedor extends Cliente { public ClienteDevedor() { } public ClienteDevedor(String nome) { super(nome); } public boolean liberarCompra(double value) { return false; } public String toString() { return “Cliente Devedor \tnome:” + getNome() + “ Telefone:” + getTelefone() + “ Endereco:” + getEndereco() + “ Limite de Compras: BLOQUEADO”;
Veja na figura o código para executar esse programa.
SEÇÃO 7 Javabeans
Javabeans são componentes de software, projetados para serem reutilizados. Eles possuem, como premissa, garantir o encapsulamento. Por isso, são classes que possuem construtores sem argumentos e as suas propriedades são acessadas externamente, apenas por meio de métodos get/set. Nos exemplos anteriores, as classes podem ser consideradas Javabeans.Cuidado para não confundir Javabeans com Enterprise Javabeans. Enterprise Javabeans é um dos componentes da plataforma Entreprise (Java Enterprise Edition), que são executados nos servidores, sendo acessados por meio do uso interfaces locais/remotas e um protocolo, como, por exemplo, RMI-IIOP. Nessa unidade de estudos você acompanhou uma breve revisão sobre a orientação a objetos, além de acompanhar dois estudos de caso: o Tamagotchi com personalidade e um sistema de cliente. Na próxima unidade, você começará a avançar no Java, então, prepare-se. Todas as informações são importantes para o seu aprendizado na área.
Figura 22: Testes das classes Cliente, ClienteEspecial e ClienteDevedor
PROGRAMAÇÃO ORIENTADA A OBJETOS II
41
Unidade de estudo 3 Seções de estudo Seção 1 – String Seção 2 – Array Seção 3 – Construtor Seção 4 – Final e static Seção 5 – Estudo de caso: relação de clientes Seção 6 – Tratamento de exceções Seção 7 – Estudo de caso: objetos de calcular Seção 8 – Utilizando pacotes
Avançando no Java SEÇÃO 1 String
String é a classe de objetos destinada a representar uma cadeia de caracteres. Diferentes dos tipos primitivos, as variáveis do tipo String guardam referências aos objetos, e não um valor. Veja um exemplo de como criar uma String.
String x = “Criando uma String utilizando literal”; String y = new String(“Criando uma String utlizando operador new “); /* Existem métodos que retornam que retornam Strings String z = String.valueOf(30);
Uma vez criada uma variável do tipo String, ela é imutável. As Strings são adicionadas a um pool de Strings e, sendo preciso, são reutilizadas. Pode-se observar, na figura a seguir, um exemplo das implicações do uso do operador new e do pool de Strings.
Na declaração e criação das variáveis x e y, a VM utilizará os mesmos objetos presentes no cache de Strings. Entretanto, para z, o uso do operador new força a criação de uma nova String no pool. Pode-se observar que foram utilizadas duas estratégias diferentes para a comparação de Strings:
▪▪ quando foi utilizado o operador ‘==’ (comparação booleana), a VM compara as referências para as quais as duas variáveis apontam, e não o seu conteúdo. No caso de x, comparando com y, poderá dar certo, pois as variáveis apontam para mesma referência. ▪▪ nos casos onde foi utilizado o
método equals, a VM irá comparar o conteúdo das referências, que é de fato o desejo neste caso. Por isso, a comparação de Strings deve ser feita sempre utilizando equals. O operador + executa uma concatenação de objetos de Strings, gerando uma nova String. Veja, a seguir, a demonstração de concatenação de Strings, usando o operador ‘+’ as implicações da imutabilidade das Strings.
Figura 23: Comparação a String
PROGRAMAÇÃO ORIENTADA A OBJETOS II
43
String exemplo = “parte1 ” + “ parte 2”;
Nessa demonstração, o desenvolvedor pode ter a impressão de ter criado apenas uma String, mas na verdade, foram criadas três: “parte 1”, “parte 2” e “parte 1 parte 2”. Pode-se concatenar string com qualquer objeto ou tipos primitivos. Veja:
double peso = 79.4; System.out.println(“O seu peso é: “ + peso);
A classe possui alguns métodos importantes que devem ser estudados com atenção. Segue uma lista deles:
▪▪ split: divide uma String em um vetor de Strings. Exemplo:
String frase = “Alô Senai!”; String lista = frase. split(“ “); //o resultado é um vetor com 2 posições
▪▪ compareTo: compara duas String. Esse método retorna um número
negativo, se a primeira for menor, zero se forem iguais, e um número positivo se a segunda for menor. Esse método diferencia letras maiúsculas e minúsculas, por isso, deve-se ter atenção ao usá-lo. Exemplo: String primeira = “Diogo”; String segunda = “Vinícius”; int compara = primeira.comparaTo(segunda); //compara será menor que, pois ‘D’ é considerado menor que ‘V’
▪▪ toUpperCase / toLowerCase: converte uma String de maiúscula para minúscula ou vice-versa. Exemplo: String texto = “eu estudando muito.”; String novoTexto = texto.toUpperCase(); ▪▪ replace: substitui em uma string, uma ocorrência por outro valor. Exemplo: String frase = “Estudando Java”; frase = frase.replace(“Java”,“Orientação a Objetos”); Outros métodos importantes da classe String são:
▪▪ charAt – indica qual caractere ocupa o índice informado. Exemplo: String vl =”JAVA Senai”; char c = vl.charAt(1);//c será igual a ‘J’
▪▪ substring – permite obter apenas parte de uma String. Exemplo: String vl =”JAVA Senai”; String subVl = vl.substring(5,10); //subVl será igual a ‘Senai’ ▪▪ length – retorna o tamanho da String. Exemplo: String vl =”JAVA Senai”; int tamanho = vl. length(); // tamanho igual a 10
▪▪ indexOf – retorna o índice de uma determinada ocorrência Exemplo: String vl =”JAVA Senai”; int pos = vl. indexOf (“Senai”); //pos será 5
44
CURSOS TÉCNICOS SENAI
▪▪ trim – retorna uma nova string sem caracteres brancos do início e do fim de uma string Exemplo: String vl =”JAVA Senai ”; String vlTrim = vl.trim(); // vlTrim será igual a “Java Senai” ▪▪ isEmpty – retorna true se a string estiver vazia. Exemplo:
String vl = ”JAVA Senai”; boolean vazia = vl.isEmpty(); //vazia = false
Dependendo da aplicação, o fato da imutabilidade dos objetos do tipo String pode gerar uma grande carga, por exemplo, na geração de arquivos textos. Um opção é o uso das classes StringBuffer e StringBuidler. Essas classes disponibilizam o método ´append´, que permite concatenar Strings, modificando seu conteúdo, ao invés de criar novos objetos. Observe um exemplo, o uso do StringBuffer.
StringBuffer palavra = new StringBuffer(); palavra.append(“primeiro”); palavra.append(“\nsegundo”); palavra.append(“\nterceiro”); palavra.append(“\nquarto”); palavra.append(“\nquinto”); System.out.println(palavra);
A instanciação de classes do tipo StringBuffer (ou StringBuilder) deve ser feita por meio do operador new. Outros métodos importantes das classes StringBuffer e StringBuilder são: insert, reverse, replace. As classes StringBuffer e StringBuilder possuem os mesmos métodos, a diferença é que a classe StringBuilder não é threadsafe. Threadsafe é uma característica desejável em programas multitarefa, onde o trecho de código funciona corretamente em situações de concorrência.
SEÇÃO 2 Array
Um array é um container de objetos de um determinado tipo que possibilita tratar um número fixo de elementos, definidos no momento da sua instanciação. Também é conhecido por vetor (unidimensional) ou matriz (multidimensional). Podem-se criar vetores de qualquer tipo primitivo ou classe. Os elementos de um array são acessados por meio de um índice inteiro. O índice do primeiro elemento é igual a zero (0), e índice do último é igual ao tamanho do vetor -1. Um array pode ter vários níveis e seu tamanho é definido no momento da criação. No Java, a declaração não cria o objeto propriamente dito. Ao invés disso, a declaração de um array cria uma referência que pode ser usada para percorrer um array. Observe um exemplo:
PROGRAMAÇÃO ORIENTADA A OBJETOS II
45
char vetorChars[ ]; //esta forma é desencorajada. int [ ] vetorInts; String [ ][ ] matrizStrings;
É importante observar que não se deve determinar o tamanho desejado do vetor na sua declaração. Isso deve ser feito no momento da instanciação, por meio do uso do operador new.
Os objetos do vetor não são criados instantaneamente, sendo necessário, criá-los separadamente.
String [ ] matrizStrings; matrizStrings= new String[3]; matrizStrings[0] = new String(“Santa Catarina”); matrizStrings[1] = new String(“Joinville”); matrizStrings[2] = new String(“Senai”);
Veja mais exemplos de criação de vetores e matrizes.
String [ ] matrizStrings2 = {“Santa Catarina”, “Joinville”, “Senai”}; // exemplo de matriz de inteiros 4x3 int [ ] [ ] notas = new int[4][ ]; notas[0] = new int[3]; notas[1] = new int[3]; notas[2] = new int[3]; notas[3] = new int[3]; // exemplo de matriz de inteiros 3x3 int [ ] [ ]frequencia = {{7,5,4} , {7,7,7}, {9,8,7}};
Uma questão interessante, sobre matrizes no Java, é que a linguagem permite que a matriz possua linhas de tamanhos diferentes. Veja, a seguir, um exemplo de matrizes com linhas de tamanhos diferentes.
/* Exemplo de matriz de inteiros com linhas de tamanhos diferentes */ int [ ] [ ] notasProvas = new int[6][ ]; notasProvas [0] = new int[3]; notasProvas [1] = new int[2]; notasProvas [2] = new int[2]; notasProvas [3] = new int[5]; notasProvas[4] = new int[4]; notasProvas[5] = new int[12];
46
CURSOS TÉCNICOS SENAI
O tamanho de um array está no seu atributo length. Esse atributo não pode ser alterado - ele é imutável após a sua criação -, entretanto, é possível atribuir à variável, que referencia o array um novo vetor com tamanho diferente. Na listagem, a seguir, pode-se observar alguns métodos importantes para manipulação de Arrays.
▪▪ arrayCopy da classe System: permite copiar o conteúdo de um vetor
para outro vetor. Exemplo: char[] origem = { ‘d’, ‘e’, ‘c’, ‘a’, ‘f ’, ‘e’, ‘i’, ‘n’, ‘a’, ‘t’, ‘e’, ‘d’ }; char[] destino = new char[7]; System.arraycopy(origem, 2, destino, 0, 7); //o conteúdo de destino será ‘c’, ‘a’, ‘f ’, ‘e’, ‘i’, ‘n’, ‘a’,
▪▪ sort da classe java.util.Arrays. Oderna um vetor. Exemplo: int[] valores = { 10, 5, 6, 1, 2, 8}; java.util.Arrays.sort(valores); //o conteúdo do vetor valores será ordenado crescentemente
SEÇÃO 3 Construtor
O construtor é o método chamado no momento que uma nova instância do objeto é criada. Ele possibilita inicializar a instância e suas variáveis, alocando os recursos necessários ao funcionamento do objeto. O construtor deve possuir o mesmo nome da classe e não deve ser definido um tipo de retorno. Toda classe possui um construtor. Se o desenvolvedor não definir um construtor, a classe recebe um construtor padrão sem argumentos. Um construtor pode ser sobrecarregado, permitindo que uma mesma classe possua vários construtores.
Observe, a seguir, um exemplo de classe com construtor sobrecarregado. public class Empregado { private String nome; private int salario; public Empregado(String n, int s) { nome = n; salario = s; } public Empregado(String n) { this(n, 0); } public Empregado( ) { this(“Não definido”); } }
PROGRAMAÇÃO ORIENTADA A OBJETOS II
47
SEÇÃO 4
Final e static O Java disponibiliza duas palavras-chave, que modificam o comportamento da linguagem sobre classes, atributos, argumentos, variáveis e métodos: static e final. O final pode ser aplicado à classe, métodos, atributos, variáveis e argumentos. Quando aplicada, na declaração de uma classe, indicada que a classe não pode ser extendida. Isso permite, ao desenvolvedor da classe, garantir que o comportamento da classe não será alterado por uma questão de segurança, por exemplo:
public final class ValidadorSenha{ public boolean isSenhaValida(String user, String senha){ { // código de validação... } }
Um desenvolvedor que queira burlar a segurança, derivando a classe, como, no exemplo a seguir, receberia um erro no momento da compilação, indicando que a operação é ilegal.
public class ValidadorSenhaNovo extends ValidadorSenha { //<
Assim, como uma classe final, um método final de uma classe não pode ser sobrescrito nas suas subclasses. Quando aplicado a uma variável, argumento ou atributo, o operador final impede que o conteúdo seja alterado após a sua declaração, ou, no caso dos atributos de uma classe, na sua costrutora. Qualquer tentativa de mudança de valor, após a sua declaração, causa um erro de compilação. Por conta dessa restrição à escrita, a VM pode aperfeiçoar o acesso a esta variável, reduzindo o tempo despendido para operação, algo que pode ser positivo dependendo da situação. Veja um exemplo de tentativa de derivar uma classe fina.
48
CURSOS TÉCNICOS SENAI
public class Carro{
private final int anoFabricacao;
public Carro(int anoFabricacao) { this.anoFabricacao = anoFabricacao; } public void adulteraCarro(int novoAnoFabricacao){ { this.anoFabricacao = novoAnoFabricacao; //<
O static permite que um atributo ou um método fique vinculado à classe e não às instâncias. No caso das variáveis, o seu valor é compartilhado entre todas as instâncias de uma classe. O resultado é semelhante a uma variável global em outras linguagens. O acesso à variável, se não for privada, utiliza a referência da classe, conforme pode ser observado a seguir.
public class Servidor{ public static String url; // código ... } public class Cliente{ public void conectar(){ /* para acessar o atributo static, basta usar * a forma classe.atributo */ String url = Servidor.url; } }
Um uso comum do static e final é a definição de constantes, permitindo criar atributos acessíveis pelas instâncias, sem permitir que seus valores possam ser alterados. As constantes são criadas para melhorar a legibilidade do código, possibilitando evitar o uso de valores fixos no código, prática conhecida como Magic Number. O exemplo, a seguir, define uma classe para fazer Log de operações. Nessa classe são definidas quatro constantes, utilizadas no momento de registrar, definindo o tipo de operação: ERROR, WARNING, INFO, DEBUG.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
49
public class Log{
public static final int ERROR = 3; public static final int WARNING = 2; public static final int INFO = 1; public static final int DEBUG = 0;
public static void log(int type, String msg){ //... código do log .. } }
SEÇÃO 5
Estudo de caso: relação de clientes Você se lembra que, nas seções anteriores, foram definidas as classes Cliente, ClienteEspecial e ClienteDevedor? Elas compõem uma mesma hierarquia de classes, possibilitando tratar qualquer instância especializada por meio e uma referência de Cliente. Por conta disso, para criar uma lista de clientes, pode-se usar um array do tipo cliente. No exemplo de código, a seguir, você pode observar a implementação São criados três objetos, inicializados, apropriadamente, e é feita a referência, as posições e o array para os objetos. Confira:
50
CURSOS TÉCNICOS SENAI
package com.senai.main; import org.senai.cliente.Cliente; import org.senai.cliente.ClienteDevedor; import org.senai.cliente.ClienteEspecial; public class RelacaoCliente { public static void main(String args[]){ Cliente[] clientes = new Cliente[3]; Cliente joao = new Cliente(“Loja do Joao”); joao.setEndereco(“Rua dos programadores, 100”); joao.setLimiteCompras(150); joao.setTelefone(“2235-0813”); ClienteEspecial maria = new ClienteEspecial(“Loja da Maria”); maria.setEndereco(“Rua dos desenvolvedores, 101”); maria.setLimiteCompras(150); maria.setTelefone(“2235-0813”); maria.setNomeContato(“Maria”); maria.setTelefoneContato(“2357-1113”); ClienteDevedor juka = new ClienteDevedor(“Loja da juka”); juka.setEndereco(“Rua dos analistas, 110”); juka.setLimiteCompras(150); juka.setTelefone(“2235-0813”); clientes[0] = joao; clientes[1] = maria; clientes[2] = juka; listarClientes(clientes); } public static void listarclientes(Cliente[] clientes){ System.out.println(“Listagem de Clientes”); for(Cliente cliente : clientes){ System.out.println(cliente); } } }
No trecho de código, onde são exibidas as informações dos clientes, o compilador não sabe dos detalhes dos objetos, só valida se a referências é permitida. Na execução, por polimorfismo, os métodos são executados de acordo com a instância presente na memória. É importante, também, observar o uso do for-each. No método listarClientes, foi utilizado um interator, que varre o array, igualando a posição atual com a variável cliente.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
51
SEÇÃO 6
Tratamento de exceções O tratamento de exceções é o mecanismo para tratar erros durante a execução de um programa. Ele representa uma parte significativa do esforço em projetos desenvolvidos em Java. Entretanto, esse esforço não agrega valor ao produto e, normalmente, implica em problemas quando não é adequadamente codificado. As exceções são classes que representam erros durante a execução de um programa Java. Os objetos que representam as exceções podem ser “lançados”, capturados e manipulados. São considerados condições de erro:
de Throwable. Das diversas derivações de Throwable, duas merecem uma atenção especial: Error e RuntimeException. O tratamento de exceções é expresso por meio de dois grupos de palavras reservadas, que trabalham em conjunto:
▪▪ um grupo para o lançamento de exceções: throw/throws, onde as exceções são originadas ou passadas para frente; ▪▪ outro para a captura de exceções lançadas e/ou garantia de execu-
ção: try-catch-finally, com as quais, de fato, se trata as exceções.
▪▪ tentar abrir um arquivo que não existe; ▪▪ tentar usar uma conexão de
rede interrompida;
▪▪ tentar acessar posição de arrays fora da faixa; ▪▪ tentar carregar uma classe que
não está no classpath.
Na figura 23, você pôde observar a execução de um código que gera uma exceção. É criada uma referência à classe String. Ela é inicializada com null. Antes que seja instanciado um objeto do tipo String para esta referência, tenta-se utilizar o método isEmpty(), que ainda não existe. A exceção gerada é uma do tipo NullPointerException. As exceções no Java derivam da classe Throwable. Ela é a única, cujas instâncias, diretas ou indiretas, podem ser usadas para serem lançadas. Existe um grande número de classes presentes na linguagem para tratar todas as categorias de erro. Também é possível criar novas exceções, derivando de Exception, um tipo derivado
52
CURSOS TÉCNICOS SENAI
Figura 24: Gerando exceção NullPointerException
O desenvolvedor, durante a criação de uma aplicação, pode identificar situações no código onde o fluxo deva ser interrompido, por exemplo, pela inconsistência de uma informação. Também pode ocorrer que o desenvolvedor não deseja tratar uma determinada situação, como, por exemplo, a falta de um arquivo. Nessas situações, ele pode lançar uma exceção. O desenvolvedor, para lançar uma exceção, usa as palavras reservadas throw e throws. Veja, a seguir, um exemplo dessa utilização.
//... código da classe public void loadData(String caminho) throws IOException{ if(verificarArquivo(caminho) == false){ throw new IOException(“Erro a verificar arquivo”); } //código de carga dos dados }
A linguagem Java exige que toda exceção, que possa ser lançada, deve ser tratada. No exemplo anterior de código, o desenvolvedor, que disparar o método loadData, precisará tratar a exceção do tipo IOException, caso contrário, o compilador indicará que há um problema no código. Essa situação não é aplicada, caso as exceções lançadas, envolvam instâncias da classe Error, RuntimeException e das classes delas derivadas. Ainda no código mostrado, anteriormente, caso o método verificarArquivo retornar falso, será criado um objeto do tipo IOException. O fluxo de controle será interrompido, e retornará para o método chamador, um objeto de exceção. Observe, a seguir, o código que dispara o método verificarArquivo. Ele está envolvido com um conjunto de try/catch/finally.
//... código da classe String arquivo = “data.txt”; try{ loadData(arquivo); otimizarData(); } catch(IOException ioex){ System.out.println(“Problemas ao importar arquivo:”+arquivo); ioex. printStackTrace(); //imprime todo a pilha de execução } finally{ System.out.println(“Processo Encerrado”); } //... código da classe
Caso o método loadData, ou qualquer outro método dentro de um bloco try-catch, lance uma exceção de um tipo previsto por uma cláusula catch, o fluxo é desviado para uma cláusula catch apropriada. Isso permite uma consideração sobre os métodos, que podem terminar por uma das condições abaixo:
▪▪ o fluxo de controle atingiu o final do método; ▪▪ o fluxo de controle atingiu um comando return; ▪▪ ocorreu um problema grave, impedindo o fluxo normal, foi exe-
cutado um throw implícito ou explícito, que não foi apanhado por um comando try-catch daquele método. Não existindo a execução do programa, será finalizada, com mensagem de erro provida pela JVM, dizendo que uma exceção foi lançada sem que fosse apanhada. Considerando apenas o encerramento, por conta de problemas, é importante observar que a linguagem Java classifica os erros e exceções em dois grupos:
▪▪ checked: a verificação é obrigatória; ▪▪ unchecked: a verificação não é obrigatória.
O desenvolvedor, para lançar as exceções checked, deve marcar o método com o tipo de exceção a ser lançado. Isso é feito, por meio do uso da palavra reservada throws. Isso pode ser observado na declaração de método presente no exemplo try/catch/finally (código anterior). Toda a chamada ao método calcular precisará tratar ou lançar exceções do tipo Exception. Ainda nesse exemplo, pode-se observar a existência de um bloco finally. O finally define um bloco de código que sempre será executado, mesmo que uma exceção seja lançada ou não.Isso permite ao desenvolvedor, garantir que um determinado bloco de código sempre será executado, mesmo que algum problema ocorra quando, por exemplo, se trabalha da abertura de arquivos ou conexões com bancos. Um bloco try pode conter: try-catch-finally, try-catch ou try-finally. A seleção pela forma mais apropriada cabe ao desenvolvedor. O tratamento de exceções permite ao desenvolvedor, decidir entre tratar uma exceção ou lançá-la para o método invocador. Isso leva à seguinte questão: quando se utiliza uma forma ou outra? A decisão deve levar em conta a lógica envolvida e relação com usuário. Se o problema necessita de uma ação do usuário e ocorre em uma camada muito interna da aplicação, deve-se lançar exceção até um ponto no qual haja interação com usuário. Além de contar com ampla biblioteca de exceções disponíveis na linguagem, o desenvolvedor pode optar por criar uma nova exceção. No exemplo, a seguir, você pode observar a criação de exceção – que trata da ocorrência de timeout em um servidor.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
53
public class ServerTimedOutException extends Exception { private int port; public ServerTimedOutException(String motivo, int porta){ super(motivo); // chama construtor da classe pai this.porta = porta; } public int getPorta( ) { return porta; } }
SEÇÃO 7
Estudo de caso: objetos de calcular Nessa seção, você acompanhará o desenvolvimento de uma aplicação, capaz de receber uma operação e executá-la. Observe na figura, a seguir, um diagrama de classes representando o problema.
Figura 25: Diagrama UML
A classe ParserOperacao recebe uma String, contendo a operação a ser executada. Ela interpreta essa operação e encaminha para o objeto de calculadora efetivar a operação. Na figura 26, pode ser visto o código da classe Calculadora. Essa classe possui o método calcular com duas implementações distintas. Uma que recebe duas variáveis do tipo double e realiza a operação; outra que recebe duas variáveis do tipo String, converte-as, e chama a outra operação de calcular. Isso caracteriza polimorfismo de sobrecarga – a Máquina Virtual Java selecionará, no momento de execução, a implementação apropriada.
54
CURSOS TÉCNICOS SENAI
Figura 26: Código-fonte calculadora
Na figura 25, você pôde ver o código da classe ParserOperacao, que possui, associada a ela, uma referência à classe Calculadora. A operação principal é processar, que fragmenta a expressão e repassa para a calculadora executar a operação de fato. É importante observar que a análise da operação é bastante restrita: ela apenas conseguirá interpretar uma operação, se entre os elementos, existir um espaço em branco e o formato for: Número Operador Número.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
55
Figura 27: Código-fonte ParserExpressao
Na figura a seguir, você verá o código da classe Main. É nessa classe, que inicia a execução da aplicação. Ela utiliza uma classe do Swing: o JOptionPane, que será detalhada na próxima sessão. Por meio do JOptionPane, é exibida uma mensagem para que o usuário informe a expressão desejada.
Figura 28: Código-fonte Classe Principal
56
CURSOS TÉCNICOS SENAI
SEÇÃO 8
Utilizando pacotes Projetos de softwares exigem uma forma prática de organizar os arquivos envolvidos. No Java, esse mecanismo é package. Ele permite agrupar classes relacionadas, utilizando a hierarquia de diretórios nesta organização, possibilitando a criação de múltiplos níveis de classes. Deve-se utilizar a declaração de pacote package para relacionar uma determinada classe a um pacote – a estrutura de diretórios é explicitada nessa declaração. As classes que estiverem no mesmo diretório e possuírem a mesma declaração de package, comporão um pacote. Você pode observar essa organização na figura a seguir.
Todas essas informações são importantes para a sua formação na área, e aperfeiçoamento no mercado de trabalho, portanto, mantenha-se atento para que nenhuma informação passe despercebida. Na próxima unidade, vem mais novidade. Até lá!
Figura 29: Criação de um pacote
Uma classe armazenada em um pacote pode ser utilizada por outras classes, mas para isso deve estar marcada como uma classe pública, e o pacote acessível no classpath da aplicação. Devem-se importar os pacotes e classes que serão utilizados em um determinado ponto (classe) do projeto. Isso é feito por meio do uso da declaração de importação import para indicar ao compilador onde achar as classes. Nos exemplos anteriores, pôde-se observar o uso, tanto da declaração de pacotes, quanto de imports. Java Archive (JAR) é um arquivo compactado, usado para distribuir um conjunto de classes Java. Ele é usado para armazenar classes compiladas e metadados associados, que compõe uma hierarquia de pacotes. Os arquivos JAR são criados por meio da ferramenta jar. No NetBeans, pode ser criado, por meio do uso da opção ‘Construir’ (Build) ou ‘Limpar e Construir’ (Clean and Build), um diretório ‘dist’ contendo os JARs. Nessa unidade de estudo, você estudou as Strings, arrays, os construtores e o final e static, que são palavras-chave que modificam o comportamento da linguagem sobre classes, atributos, argumentos, variáveis e métodos. Nos dois estudos de caso, você teve informações importantes e exemplos práticos, tanto de relação com o cliente, quanto de calculadora. PROGRAMAÇÃO ORIENTADA A OBJETOS II
57
Unidade de estudo 4 Seções de estudo Seção 1 – Visão geral Seção 2 – Alô Senai! Seção 3 – Containers e gerenciadores de layout Seção 4 – Eventos Seção 5 – Estudo de caso: objetos de calcular
AWT e Swing SEÇÃO 1
Visão geral O desenvolvedor possui uma variedade grande de APIs para desenvolver interfaces com o usuário no Java. Duas se destacam: o AWT e o Swing. O AWT – Abstract Window Toolkit- é o antigo conjunto de ferramentas para interfaces gráficas do Java. Serve para oferecer infraestrutura mínima de interface gráfica (nivela por baixo). Os componentes do Abstract Window Toolkit estão no pacote java. awt.*. Ele contém todas as classes para criação de interfaces, entretanto apresenta alguns problemas:
▪▪ a aparência dos componentes
dependente de plataforma na qual a aplicação será executada;
▪▪ é limitada em recursos por
depender de suporte de cada plataforma para os componentes oferecidos;
▪▪ bugs e incompatibilidades entre
plataformas.
A resposta a essas limitações foi o desenvolvimento do Swing. O Swing é um conjunto de componentes gráficos, que dão suporte à construção de aplicações Java com interface gráfica e interatividade. Ele faz parte da Java Foundation Classes (JFC). Os componentes de Swing fazem parte do pacote javax.swing.*. Os componentes têm como objetivo, prover o mesmo comportamento, independente do sistema operacional. Estão disponíveis componentes, tais como:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
JTextField; JTextArea; JRadioButton; ButtonGroup; JCheckBox; JComboBox; JPanel; JScrollPane.
Confira algumas características do Swing:
▪▪ grande variedade de compo-
nente;
▪▪ ▪▪ ▪▪ ▪▪
Java 2D API; Look-and-Feel; Internationalization; Accessibility API.
SEÇÃO 2 Alô Senai!
Alô, SENAI! é um exemplo, bem básico, para criação de um programa com interface gráfica. O objetivo é criar uma janela simples, que possuirá um rótulo, um campo de edição e um botão. No campo de edição, o usuário poderá escrever um texto, nesse caso, o seu nome. Ao clicar sobre o botão, a aplicação exibirá uma mensagem, cumprimentando o usuário, utilizando o texto informado. Os elementos que compõe uma interface gráfica são:
▪▪ n (janela, painel): local onde são adicionados os componentes ou outros containers; ▪▪ componentes: botões, labels, listbox, menus etc. ▪▪ gerenciador de layout: objeto responsável pelo posicionamento dos componentes inseridos num determinado container. O componente Swing, que representa telas no sistema operacional, é o JFrame. As janelas criadas, pelos desenvolvedores, derivam dela. Pode-se criar aplicações Swing inteiras, usando apenas um editor de texto e um compilador Java, mas, para facilitar o trabalho, é melhor utilizar o NetBeans. Uma aplicação Swing usa, normalmente, pelo menos um JFrame. Um objeto derivado JFrame implementa uma única janela. Ele possui elementos chamados decorações, que são:
▪▪ a borda, ▪▪ o título; ▪▪ os botões para maximizar,
minimizar e fechar a janela.
Além do JFrame, pode ser utilizado, como componente base para aplicações, o JDialog ou o JApplet. Estes possuem um content pane. O content pane é um container sobre o qual serão adicionados os componentes gráficos que irão compor a aplicação.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
59
O primeiro passo é criar um novo projeto no NetBeans. Nesse exemplo, será criado um projeto chamado AloSenaiSwing. Para isso, foi criado o pacote com.senai.alosenai e, nesse pacote, deve-se criar um novo formulário JFrame, conforme as figuras 30 e 31.
Figura 30: Criando um JFrame
Figura 31: Nomeando um JFrame criado
O resultado dessa operação será a apresentação de um formulário em branco, onde é possível adicionar os demais componentes. O NetBeans controlará todo o código destinado à criação das janelas, inclusive quando uma classe derivada de JFrame for salva.O NetBeans cria um arquivo auxiliar para tratar dos componentes presentes na tela, e demais informações, necessárias, no momento ao qual está se desenvolvendo um formulário na IDE. Esse arquivo possui a extensão .form.
60
CURSOS TÉCNICOS SENAI
Na figura 32, você pode ver o resultado dessa operação, e um pouco da forma como o Netbeans trata aplicações Swing.
Figura 32: Editor NetBeans
É preciso adicionar os componentes necessários ao JFrame, indicando o local que se deseja incluir o componente no formulário. O NetBeans apresentará réguas para auxiliar no processo de posicionamento dos componentes. Os componentes a serem adicionados são:
▪▪ rótulo (JLabel); ▪▪ campo de texto (JTextField); ▪▪ botão (JButton). O próximo passo é configurar os componentes, para isso, é preciso clicar sobre o formulário. No canto inferior esquerdo, serão apresentadas as propriedades do formulário. Altere, se for preciso, as seguintes propriedades:
▪▪ defaultCloseOperation: esta propriedade define como a Virtual
Machine deve tratar o formulário após ele ter sido fechado. O valor deve ser: EXIT_ON_CLOSE;
▪▪ title: essa é a propriedade que trata do título da janela. Altere para: “Alo SENAI!”. Os componentes, no swing, mantêm um mesmo padrão para nome das propriedades, por isso, praticamente, todos os componentes possuem propriedades como text e enable. Isto se deve ao fato da árvore de heranças dos componentes do Swing. Veja detalhes na figura seguinte.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
61
Figura 33: Árvore de componentes Swing
Deve-se alterar a propriedade Text dos componentes a seguir.
▪▪ rótulo (JLabel): altere o texto para “Nome” ▪▪ campo de texto (JTextField): altere o texto para “Senai” ▪▪ botão (JButton): altere o Texto para “Clique Aqui!” Neste momento, a aplicação já pode ser executada, entretanto, o botão ainda não realiza nenhuma ação. O código das ações que um componente realiza, em resposta a uma ação do usuário ou do sistema, chama-se Evento. Os eventos, da mesma forma que as propriedades, seguem um mesmo padrão entre os diversos componentes. Para adicionar uma ação a um botão, há duas opções: por meio da paleta de propriedades, selecionando na listagem de eventos o enveto actionPerformed, ou dando um duplo clique sobre o componente, dessa forma, é adicionado, automaticamente, um evento do tipo actionPerformed. Ao se realizar essa ação, aparecerá no editor o método jButton1ActionPerformed. Deve-se adicionar o código para que fique similar às informações a seguir. O código executado desse projeto pode ser observado na figura 34.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { JOptionPane.showMessageDialog(this.getRootPane(), “Alo “+jTextField1.getText()+”!”,”Mensagem de Alô!”, JOptionPane.INFORMATION_MESSAGE); }
62
CURSOS TÉCNICOS SENAI
SEÇÃO 3
Containers e gerenciadores de Layout
Figura 34: Execução do projeto
O JOptionPane permite exibir mensagens, que permitem a interação com o usuário. Existem diversos tipos de mensagens. Veja!
▪▪ MessageDialog: é utilizado apenas para emitir uma mensagem, possibilitando que ela tenha um tipo. No exemplo, o tipo de mensagem foi definido como information. Além desse, há Error, Warning, Question . etc. ▪▪ InputDialog: exibe uma mensagem com uma caixa de edição, permitindo que o usuário informe um valor. Exemplo: String pessoa = JOptionPane.showInputDialog(“Quem é você?”); ▪▪ ConfirmDialog: apresenta uma mensagem, onde o usuário pode selecionar entre opções. Exemplo: int opSelecionada = JOptionPane.showConfirmDialog(null, “Confirma exclusão?”); Além dos componentes, que foram utilizados nesse exemplo, existem outros importantes. Junto com o JDK é enviado um demo do Swing, onde se pode observar todo o potencial da biblioteca, disponível em {diretório de instalação do JDK}\Demo\JFC\SwingSet2}. Entre os diversos componentes disponíveis vale destacar mais alguns.
▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
JPasswordField: caixa de texto com possibilidade de formatação. JCheckBox: botão de checagem. JRadioButton: botão mutuamente exclusivo. JComboBox: caixa de edição com lista de seleção. Jlist: lista de elementos.
JMenuBar; JMenuItem; JMenu; JCheckBoxMenuItem e JRadioButtonMenuItem: elementos para menu.
Entre os diversos tipos de componentes, há uma classe de componentes descendentes de java. awt.Container, chamados de Containers, que são componentes criados para conter outros componentes, permitindo agrupá-los e definir layouts em camadas. Existe um grupo especial de containers, chamado de top-level. Fazem parte desse grupo: JFrame, JDialog e JApplet. Esses containers são base para os componentes numa aplicação Swing. Um componente, para ser exibido na tela, deve fazer parte de um container. Além de componentes de tela, um container pode conter uma barra de menu. O JPanel se destaca entre os containers e são usados para organizar um grupo ou mais grupos de componentes filhos, permitindo separar uma tela em seções lógicas e permitindo que componentes relacionados, sejam agrupados com mais facilidade. Outro uso dessa classe é substituir o componente Canvas, quando for necessário uma área de desenho. O seu gerenciador de layout padrão é o FlowLayout. Os gerenciadores de layouts são componentes que controlam tanto a disposição, quanto a dimensão dos componentes em um container. O NetBeans facilita o desenvolvimento de aplicações Swing por gerenciar o Layout de uma maneira eficiente, criando dinamicamente GroupLayout. Confira os gerenciadores de layout disponíveis.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
63
▪▪ FlowLayout: não restringe o tamanho dos componentes que administra, e lhes permite ter o tamanho desejado. Permite alinhar os componentes à esquerda, à direita ou ao centro. Layout padrão do JPanel. ▪▪ CardLayout: permite tratar a interface como uma série de cartões, os quais você pode ver um por vez. O método add( ) é usado para adicionar cartões a um CardLayout, e recebe um JPanel e uma String como argumento, que identifica o panel. O método show( ) mostra o cartão que foi solicitado. ▪▪ BorderLayout: é o gerenciador padrão do JPanel. Divide o container em cinco áreas.
▪▪ GridLayout: o gerenciador GridLayout provê flexibilidade para colocar componentes. Ele é criado com várias linhas e colunas. GridLayout sempre ignora o tamanho dos componentes. A largura de todas as células é idêntica e é determinada, dividindo a largura disponível pelo número de colunas. O mesmo é feito para a altura. ▪▪ SpringLayout : é um ge-
renciador de layout flexível e ideal para criar interfaces gráficas elaboradas. Permite configurar relacionamento entre as bordas dos controles, por exemplo, configurar que a borda esquerda está a 5 pixels da borda direita de outro componente. Os componentes são arranjados de acordo com as restrições.
▪▪ GroupLayout: é um gerenciador de layouts que organiza grupos de componentes de maneira hierárquica de modo a viabilizar o posicionamento deles em um determinado container.
64
CURSOS TÉCNICOS SENAI
SEÇÃO 4 Eventos
A interação entre o usuário e um componente ou entre componentes de uma interface gráfica ocorre por meio de eventos. Os eventos utilizam dois elementos distintos: manipuladores de eventos e objetos de eventos. Um manipulador de evento é um método que recebe um objeto de evento, decifra, e processa a interação do usuário. Com o modelo de delegação, os eventos são enviados ao componente, mas cada componente registra um manipulador de eventos para tratá-los. Os manipuladores de eventos são chamados Listeners. Os Listeners são classes que implementam a interface de EventListener ou uma das suas derivações. Listeners podem receber e processar o evento, desse modo, o manipulador de evento pode estar em um objeto separado do componente. Todo evento tem uma interface de listeners correspondentes, que define métodos em uma classe designada a receber aquele tipo de evento. A classe que implementa a interface define esses métodos, e pode ser registrada como um listener. Importante notar que não são propagados eventos de componentes, que não possui nenhum listener registrado.
SEÇÃO 5
Estudo de caso: objetos de calcular O objetivo desse estudo de caso é criar interface gráfica para calculadora, já desenvolvida, na seção3. Serão utilizados alguns princípios de um padrão de arquitetura chamado MVC (Model, View, Control). O MVC procura separar a camada de lógica de negócio, da camada de lógica de apresentação. Isso possibilita desenvolver, manutenir e testar cada camada isoladamente. Outra característica da adoção desse modelo é a independência entre apresentação da aplicação, dos dados e das operações sobre os dados. O Model (modelo) é a lógica de negócio. Ele possui a representação detalhada das informações da aplicação. O Model, por exemplo, implementa as entidades envolvidas na solução do problema proposto. A View (visão) é a camada de interface com o usuário e onde o usuário interage com a aplicação. Nela são apresentadas as informações para o usuário, possibilitando a ele responder a uma condição. Essa camada não deve acessar diretamente ao banco de dados, e, normalmente, também não solicita diretamente operações ao Model. O Controller intermedia a View e o Model controlando todo o processo. Ele transforma eventos gerados na View em operações no Model. Cada iteração do usuário com a View é, primeiramente, interpretada pelo Controller, para, então, acessar o Model.
No exemplo do estudo de caso, desta unidade, será utilizada uma forma simplificada de MVC para ilustrar o seu uso. Como primeira tarefa, deve-se abrir o projeto da calculadora desenvolvido na seção 3. Não será preciso criar um Model, visto que na seção 3, há a classe ParserOperacao, que já representa toda a lógica de negócio envolvida. Feito isso, a próxima tarefa é criar um novo pacote chamado ‘com.senai. calculadora.mvc’. Em projetos mais elaborados, seria importante separar os três elementos em três pacotes distintos: ‘com.senai.calculadora.model’, ‘com. senai.calculadora.view’ e ‘com.senai.calculadora.control’. No pacote criado, deve-se criar um novo JFrame, chamado, por exemplo, CalculadoraView. A propriedade title precisa ser definida como “Calculadora”. Nesse JFrame deve conter:
▪▪ rótulo (JLabel): altere o texto para “Operacão” e o seu nome para “jlOperacao”; ▪▪ campo de Texto (JTextField): limpe o conteúdo e altere o seu nome para jtfExpressao; ▪▪ botão (JButton): altere o seu texto para “Calcular” e o seu nome para jbCalcular.
O formulário ficará conforme a figura a seguir.
Figura 35: Classe CalculadoraView
A próxima etapa será criar uma nova classe no pacote ‘com.senai.calculadora.mvc’. Ela deverá se chamar CalculadoraController. Nela existirão referências tanto à View, quanto à classe ParserOperacao. O código da classe CalculadoraController pode ser visto a seguir. Durante a codificação dessa classe, o Netbeans poderá indicar alguns erros, pois, serão utilizados métodos que ainda não foram implementados na View.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
65
package com.senai.calculadora.mvc; import com.senai.calculadora.ParserOperacao; import javax.swing.JOptionPane; public class CalculadoraController { private ParserOperacao parserOperacao; CalculadoraView calculadoraView; public CalculadoraController() { parserOperacao = new ParserOperacao(); calculadoraView = new CalculadoraView(); calculadoraView. setCalculadoraController (this); } public void show (){ calculadoraView.setVisible(true); } public void calcular(String expressao){ try{ double resultado = parserOperacao.processar(expressao); calculadoraView.setResultado(resultado); }catch(Exception e){ JOptionPane.showMessageDialog(calculadoraView, “Erro ao processar expressão!\n”+e.getMessage(), “Erro”, JOptionPane.ERROR_MESSAGE); } } }
Nesse ponto, deve-se modificar o JFrame CalculadoraView para suportar as novas operações. Observe a seguir o código que deve ser adicionado à classe. Também deve-se adicionar, no evento, a chamada para o CalculadoraController. O código para isso é o que aciona o evento do botão. Confira. Código adicional na CalculadoraView // código continua ... public class CalculadoraView extends javax.swing.JFrame { private CalculadoraController calculadoraController; public void setCalculadoraController( CalculadoraController calculadoraController){ this.calculadoraController = calculadoraController; } public void setResultado(double resultado){ String vl = String.valueOf(resultado); jtfExpressao.setText(vl); } // código continua ...
66
CURSOS TÉCNICOS SENAI
Código Evento do botão // código continua ... private void jbCalcularActionPerformed(java.awt.event.ActionEvent evt) { calculadoraController.calcular(jtfExpressao.getText()); } // código continua ...
Por fim, deve-se modificar a classe principal (main) do projeto, para que ela exiba e utilize a CalculadoraController. Veja a modificação necessária, no código, a seguir, e a execução da aplicação na figura 36.
package com.senai.calculadora; import com.senai.calculadora.mvc.CalculadoraController; public class Main { public static void main(String[] args) { CalculadoraController calculadoraController = new CalculadoraController(); calculadoraController.show(); } }
Figura 36: Classe CalculadoraView
Nesta unidade você acompanhou o estudo de caso de um objeto de calcular. Na próxima unidade de estudo você terá uma visão geral sobre entradas e saídas, aprenderá a manipular dados e acompanhará um estudo de caso. Bons estudos!
PROGRAMAÇÃO ORIENTADA A OBJETOS II
67
Unidade de estudo 5 Seções de estudo Seção 1 – Visão geral Seção 2 – Manipulando arquivos Seção 3 – Estudo de caso: editor de texto
Entrada e Saída SEÇÃO 1
SEÇÃO 2
O Java disponibiliza uma grande variedade de formas para criar, manipular e gerir operações de Entrada/Saída, destinadas a tratar arquivos, conexões de rede ou blocos de memória. É possível tratar arquivos formatados, não formatados, compactados etc, em diferentes níveis de complexidade e abstração e de diferentes maneiras. As operações de entrada e saída, no Java, são feitas por meio de Streams. Stream é uma sequência de ordenada de dados, que possuem uma fonte ou destino. Os pacotes responsáveis por essas operações são java.io e Java.nio. Nesse material, será apresentado somente o pacote java.io., que define Entradas/Saídas como:
O Java disponibiliza uma classe, que representa tanto arquivos, quanto diretórios. Essa classe é o File, que permite um gerenciamento, como, verificar se um arquivo/diretório existe, exclui arquivos/diretórios ou mesmo ler informações. Veja alguns métodos importantes da classe File:
Visão Geral
▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
File; InputStream e OutputStream; Reader e Writer; BufferedReader e BufferedWriter; DataInput e DataOutput; ObjectInput e Object Output.
Manipulando arquivos
▪▪ boolean canRead(): verifica se tem permissão para leitura; ▪▪ boolean canWrite(): verifica se tem permissão para escrita; ▪▪ boolean compareTo(File outroArquivo): compara dois caminhos
de arquivos;
▪▪ boolean delete: exclui o arquivo. No caso de diretório, ele precisa estar vazio; ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
boolean exists(): verifica se o caminho passado existe;
▪▪ ▪▪ ▪▪ ▪▪ ▪▪
long lastModified(): retorna a última modificação do arquivo;
boolean isAbsolute(): verifica se o caminho passado é absoluto; boolean isDirectory(): verifica se o caminho é um diretório; boolean isHidden (): verifica se é oculto; boolean mkdir(): cria um diretório com o caminho do File; boolean renameTo(File dest): renomeia o arquivo/diretório;
File[] listFiles: lista os arquivos contidos em um diretório. Caso, não seja um diretório, retorna null; long length(): retorna o tamanho do arquivo; String getAbsolutePath(): retorna o caminho absoluto; String getName(): retorna o nome do arquivo ou diretório;
String[] list: lista os nomes dos arquivos contidos de um diretório. Caso, não seja um diretório, retorna null;
▪▪ void setReadOnly(boolean readable): modifica o atributo do arquivo para apenas leitura.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
69
Veja um exemplo de uso da classe File:
import java.io.File; public class ListandoArquivos { public static void main(String args[]){ for(File root : File.listRoots()){ //lista os diretórios raizes System.out.println(“Raiz: “+root.getAbsolutePath()); if(root.listFiles() == null){ // se não possui lista de arqivos continue; //continua no próximo laço } for(File arq : root.listFiles()){ //lista os diretórios raizes System.out.print(“ “+arq.getAbsolutePath()); if(arq.isHidden()){ //se for oculto, exibe (o) System.out.print(“ (o)”); } if(arq.isDirectory()){ System.out.print(“ (d)”); //se for dir, exibe (d) }else{ //senão, exibe o tamanho System.out.print(“ tam:”+arq.length()); } System.out.println(“”); } //verifica se tem diretório temp no raiz, se não tiver tenta criar File temp = new File(root.getAbsoluteFile()+”Temp\\”); if(temp.exists() == true){ System.out.print(“Criando diretório temporário...”); try{ temp.mkdir(); }catch(SecurityException e){ System.out.print(“ Permissão negada!”); } finally{ System.out.println(); } } else{ System.out.println(“Já possui diretorio temporário!”); } } } }
Quando a instância que a classe File se referencia é um diretório, existem dois métodos para retornar o seu conteúdo (arquivos que possuem): list( ) e o listFiles( ). Esses métodos possuem, além da implementeção que não recebe argumentos, uma construtora que permite passar como parâmetro um objeto da interface FilenameFilter.
70
CURSOS TÉCNICOS SENAI
A interface FilenameFilter tem um método abstrato accept( ), que, quando implementado, retorna um array de File. O conteúdo do array são Strings, que representam arquivos e diretórios. O método accept( ) filtra o retorno dos dois métodos (list( ) e listFiles( )), por exemplo, pode-se definir um filtro para que sejam retornados somente arquivos .exe e .com. Observe um exemplo de como criar um novo tipo de execução:
import java.io.File; public class ListandoArquivos { public static void main(String args[]){ for(File root : File.listRoots()){ //lista os diretórios raizes System.out.println(“Raiz: “+root.getAbsolutePath()); if(root.listFiles() == null){ // se não possui lista de arqivos continue; //continua no próximo laço } for(File arq : root.listFiles()){ //lista os diretórios raizes System.out.print(“ “+arq.getAbsolutePath()); if(arq.isHidden()){ //se for oculto, exibe (o) System.out.print(“ (o)”); } if(arq.isDirectory()){ System.out.print(“ (d)”); //se for dir, exibe (d) }else{ //senão, exibe o tamanho System.out.print(“ tam:”+arq.length()); } System.out.println(“”); } //verifica se tem diretório temp no raiz, se não tiver tenta criar File temp = new File(root.getAbsoluteFile()+”Temp\\”); if(temp.exists() == true){ System.out.print(“Criando diretório temporário...”); try{ temp.mkdir(); }catch(SecurityException e){ System.out.print(“ Permissão negada!”); } finally{ System.out.println(); } } else{ System.out.println(“Já possui diretorio temporário!”); } } } }
PROGRAMAÇÃO ORIENTADA A OBJETOS II
71
Agora, veja um exemplo de lista de arquivos com uso de filtro.
package com.senai.file; import java.io.File; import java.io.FilenameFilter; class FiltroExe implements FilenameFilter { public boolean accept(File dir, String arq) { return arq.endsWith(“.exe”); } }
A operação de leitura deve ser feita por meio do uso de classes derivadas da classe abstrata InputStream. Os métodos básicos do InputStream são:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪ ▪▪
int read() int read(byte[]) int read(byte[ ], int ini, int tam) void close() int available() void skip(long tam)
public class ListandoFileFiltro { public static void main(String args[]) { //lista os diretórios raizes for (File root : File.listRoots()) { // se não possui lista de arqivos if (root.listFiles() == null) { //continua no próximo laço continue; } //lista os aquivos exe e com for (File arq : root.listFiles(new FiltroExe())) { System.out.print( arq.getAbsolutePath()); //se for oculto, exibe (o) if (arq.isHidden()) { System.out.print(“ (o)”); } System.out.println(“ tam:” + arq.length()); } } } }
72
CURSOS TÉCNICOS SENAI
Uma das classes concretas, derivadas da InputStream, é FileInputStream. Ela permite realizar operações sobre arquivos, como, ler um byte do arquivo, por exemplo. Na instanciação de um FileInputStream, deve-se passar o caminho do arquivo que será lido. A leitura de arquivos-texto é realizada pelas classes FileInputStream, InputStreamReader e BufferedReader. Um exemplo de leitura de arquivo pode ser visto na figura a seguir.
Figura 37: Leitura de arquivo texto
O FileInputStream lê bytes. O InputStreamReader, uma derivada da classe Reader, lê caracteres, o que facilita a manipulação de arquivos-texto. A classe BufferedReader permite ler linhas inteiras por meio do método readLine. Além de ser possível ler de arquivos, pode-se ler as entradas, feitas pelo usuário, em um console. Essa operação pode é feita, substituindo a instanciação do objeto FileInputStream e passado como parâmetro o System.ini para o InputStreamReader. O código, desse exemplo, pode ser visto a seguir.
try { Reader inputStreamReader = new InputStreamReader(System.in); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); System.out.println(“Lendo do teclado”); for (String linha = “”; linha != null && linha.equals(“fim”)!=true; linha = bufferedReader.readLine()) { System.out.println(“linha lida:” + linha); } } catch (FileNotFoundException ex) { System.out.println(“Ocorreram problemas ao abrir arquivo”); } catch (IOException ex) { System.out.println(“Ocorreram problemas ao abrir arquivo”); }
PROGRAMAÇÃO ORIENTADA A OBJETOS II
73
Similar à leitura, a operação de gravação deve ser feita por meio do uso de classes derivadas da classe abstrata OutputStream. Os métodos básicos do OutputStream são:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪
void write(int a) void write(byte[]) void write(byte[], int ini, int tam) void close() void flush()
A gravação de arquivos-texto é um trabalho em conjunto, entre as classes FileOutputStream, OutputStreamWriter e BufferedWriter. FileOutputSream permite gravar um byte. O OutputStreamWriter grava um char, e o BufferedWriter, grava Strings. Um exemplo de gravação de arquivo pode ser visto na figura 38.
Figura 38: Gravação de arquivo-texto
74
CURSOS TÉCNICOS SENAI
Outra forma de ler/gravar arquivo, empregando uma implementação disponível no Java, de mais alto nível, é utilizando as classes: java.io.FileWriter/java.io.PrintWriter e java.io.FileReader e java. io.BufferedReader. Observe, agora, um exemplo do uso dessas classes no código a seguir.
package com.senai.file; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import javax.swing.JOptionPane; public class FileReaderWriter { public static void main(String[] args) { //Gravando o arquivo try { FileWriter writer = null; writer = new FileWriter(“c:\\temp\\alice.txt”); PrintWriter saida = new PrintWriter(writer); saida.println(“- Nesta direção, disse o Gato, girando a pata direita,” +“ mora um Chapeleiro. “); saida.println(“E nesta direção, apontando com a pata esquerda,” +”mora uma Lebre de Março.”); saida.close(); writer.close(); } catch (IOException ex) { System.out.println(“Ocorreram problemas ao gravar arquivo”); } // Lendo gravando try { FileReader reader = new FileReader(“c:\\temp\\alice.txt”); BufferedReader leitor = new BufferedReader(reader); String linha = null; while ((linha = leitor.readLine())!=null) { JOptionPane.showMessageDialog(null, linha); } } catch (IOException ex) { System.out.println(“Ocorreram problemas ao abrir arquivo”); } } }
PROGRAMAÇÃO ORIENTADA A OBJETOS II
75
SEÇÃO 3
Estudo de caso: editor de texto Você vai conferir, agora, os passos para criar um editor de textos simples, utilizando Java. Será empregada uma simplificação do MVC. 1. Criar e preparar um novo projeto. 2. Criar uma classe que represente a lógica do editor de texto. 3. Criar uma tela swing para consumir a classe da lógica. 4. Criar uma classe que orquestre as outras duas classes. Deve-se criar um novo projeto no eclipse, nomeado EditorTexto. Nesse projeto, deve-se adicionar um pacote chamado com.senai.texto. O projeto estará conforme figura a seguir.
Figura 39: Projeto editor de texto
O próximo passo será criar a classe com a lógica do editor. Ela será chamada de EditorModel. Veja o código da Classe EditorModel.
76
CURSOS TÉCNICOS SENAI
package com.senai.texto; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class EditorModel { private File arquivo; public void setArquivo(File arqivo) { this.arquivo = arqivo; } public String carregar() throws IOException { FileReader reader = new FileReader(arquivo); BufferedReader leitor = new BufferedReader(reader); StringBuilder conteudo = new StringBuilder(); String linha = “”; String novaLinha =””; while ((linha = leitor.readLine()) != null) { conteudo.append(novaLinha); conteudo.append(linha); novaLinha = “\n”; } leitor.close(); reader.close(); return conteudo.toString(); } public void gravar(String conteudo) throws IOException { FileWriter writer = new FileWriter(arquivo); PrintWriter saida = new PrintWriter(writer); saida.print(conteudo); saida.close(); writer.close(); } }
Dois métodos merecem destaque, nessa classe: carregar e gravar. Ambos manipulam arquivos e, por conta dos métodos que utilizam, podem dar origem a exceções do tipo IOException. Essa classe não interage com o usuário, por isso, optou-se por não tratá-las por ora.. Foram utilizadas as palavras reservadas throws para, no caso da ocorrência de uma exceção do tipo IOException, lançá-la para o método chamado, evitando que seja preciso tratar nesse local. Próximo passo: adicionar um JFrame. Ele deve se chamar EditorView. Será utilizada uma barra de menus, na parte superior, onde o nome do menu principal será “arquivo”. Deve-se adicionar dois itens de menu a ele, sendo um para salvar e outro para carregar. É importante renomear esses dois itens para jmCarregar e jmSalvar.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
77
Será adicionado, também, ao formulário uma área de texto. O Netbeans adicionará, automaticamente, sob a área de texto, um JScrollPane, para que sejam criadas barras de rolagem em textos muito longos. O formulário deverá ficar similar ao que pode ser observado na figura a seguir.
Figura 40: Formulário editor
A próxima etapa será criar o objeto, que controlará a aplicação. Será preciso adicionar uma nova classe chamada EditorControl. Uma melhoria, adicionada a esse estudo de caso, é o uso de um padrão de projeto chamado Singleton. Tal padrão, garante que dada uma JVM, somente uma instância da classe existirá na memória, evitando, assim, a existência de mais de um Controller. Confira o código dessa classe.
package com.senai.texto; import java.io.IOException; import javax.swing.JFileChooser; import javax.swing.JOptionPane; public class EditorController { // o padrão singleton precisa que a classe possua uma instancia dela mesmo private static EditorController instance; private EditorModel editorModel; private EditorView editorView; //que a construtora seja privada, de modo que não se possa instanciar de fora private EditorControl() { initEditor(); }
78
CURSOS TÉCNICOS SENAI
// E um método que possibilite só seja criada uma instância da classe public synchronized static EditorController getInstance() { if (instance == null) { instance = new EditorControl(); } return instance; } private void initEditor() { editorView = new EditorView(); editorView.setControl(this); editorView.setTitle(“Editor de Texto”); } public void show() { editorView.setVisible(true); } { JFileChooser fc = new JFileChooser(); int res = fc.showOpenDialog(editorView); if (res == JFileChooser.APPROVE_OPTION) { editorModel = new EditorModel(fc.getSelectedFile()); try { editorView.setText(editorModel.carregar()); editorView.setTitle(“Editor de Texto: “ + fc.getSelectedFile().getAbsolutePath()); } catch (IOException io) { JOptionPane.showMessageDialog(editorView, “Problema ao carregar arquivo”, “Editor”, JOptionPane.ERROR_MESSAGE); } } } public void gravar() { JFileChooser fc = new JFileChooser(); int res = fc.showSaveDialog(editorView); if (res == JFileChooser.APPROVE_OPTION) { editorModel = new EditorModel(); editorModel .setArquivo(fc.getSelectedFile()); try { editorModel.gravar(editorView.getText()); editorView.setTitle(“Editor de Texto: “ + fc.getSelectedFile().getAbsolutePath()); } catch (IOException io) { JOptionPane.showMessageDialog(editorView, “Problema ao carregar arquivo”, “Editor”, JOptionPane.ERROR_MESSAGE); } } } }
PROGRAMAÇÃO ORIENTADA A OBJETOS II
79
Falta, agora, modificar a view para que possa chamar o controle, quando o usuário, a título de exemplo, interagir com o menu. Deve-se adicionar eventos nos dois itens de menu, e modificar o código da seguinte maneira:
public class EditorView extends javax.swing.JFrame { private EditorController editorControl; public void setControl(EditorController editorControl){ this.EditorController = editorControl; } public String getText(){ return jTextArea1.getText(); } public void setText(String text){ jTextArea1.setText(text); } //... continua o código... private void jmCarregarActionPerformed(java.awt.event.ActionEvent evt) { editorControl.carregar(); } private void jmSalvarActionPerformed(java.awt.event.ActionEvent evt) { editorControl.gravar(); } //... continua o código
A última coisa, que precisa ser feita, é criar uma classe, que contenha um método main, para disparar a execução do editor de texto. Veja o código da classe main e, na figura 41, o editor rodando.
package editortexto; import com.senai.texto.EditorControl; public class Main { public static void main(String[] args) { EditorController EditorController = EditorControl.getInstance(); editorControl.show(); } }
80
CURSOS TÉCNICOS SENAI
Figura 41: Editor de texto executando
Nesta unidade de estudos, você aprendeu a manipular arquivos e, ainda, viu como se cria um editor de texto. Na próxima unidade, você conhecerá os JDBC e verá como unir todas as informações estudadas até agora.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
81
Unidade de estudo 6 Seções de estudo Seção 1 – Visão geral
Collections SEÇÃO 1
Visão geral As arrays são limitadas: uma vez criadas não podem ter seu tamanho modificado, não disponibilizam mecanismos para procura de elementos e não disponibilizam para saber quanto dos seus itens já foram utilizados. A solução para essas questões é o uso de coleções ou como é conhecido no Java, Collections. Uma collection é um tipo de objeto que permite agrupar múltiplos elementos num só, sendo usado para armazenar, consultar e manipular dados. Alguns exemplos cotidianos de coleções são: uma fila de banco, uma lista de compras, uma pilha de livros, um conjunto de elementos etc. Boa parte das linguagens de programação orientadas a objetos oferecem frameworks para representar e manipular coleções. Tais frameworks são formados por:
As coleções fornecem operações básicas para manipular o seu conteúdo. Essas operações estão sujeitas às características de cada coleção. As operações básicas ao usar as coleções são:
▪▪ ▪▪ ▪▪ ▪▪ ▪▪
adicionar objetos; remover objetos; verificar se existe um objeto; recuperar um objeto; percorrer os objetos um a um.
O Java oferece um excelente framework de coleções, que inclui listas, conjuntos e mapas. As abstrações (interfaces) de coleções do Framework Java estão distribuídas de forma hierárquica.
▪▪ interfaces: abstrações que representam as coleções;
▪▪ implementações: classes concretas que implementam as interfaces; ▪▪ algoritmos: métodos para
pesquisa e ordenação, que são oferecidos pelas classes; que implementam as interfaces, e são polimórficos e reutilizáveis.
Figura 42: Editor de texto executando
Collection é a raiz da hierarquia das coleções básicas. Essa interface é implementada por todas as coleções e é usada quando se deseja com uma generalização das coleções. Algumas coleções permitem inserir e/ ou duplicar elementos, outras não. Algumas são ordenadas, outras não. O Java não fornece classe, que implemente esta interface diretamente, mas fornece de coleções específicas, tais, como, Set e List
PROGRAMAÇÃO ORIENTADA A OBJETOS II
83
A interface Set abstrai um conjunto matemático e não pode conter elementos duplicados. O SortedSet, como pôde ser observado na figura 42, define um conjunto que mantém os elementos em ordem ascendente. São adequados para conjuntos ordenados naturalmente como, por exemplo, uma lista de palavras. A interface List define uma coleção ordenada e pode conter elementos duplicados. Permite inserir um elemento, numa posição específica da lista, e permite acessar os elementos por meio de um índice. o que permite manter vários elementos antes de processá-los. Além dos métodos de Collection, também oferece métodos a mais para inserção, extração e operações de inspeção. Utiliza FIFO (First In First Out) como mecanismo de ordenação. Pode operar como uma pilha, possibilitando o uso do poll, para remover o seu primeiro. Os elementos são adicionados no fim da fila. O Map representa uma lista de pares chave/valor. Não pode conter chaves duplicadas. Cada chave mapeia um valor. SortedMap, uma especialização de Map, representa uma lista de pares chave/valor ordenados com ordem ascendente pela chave. É adequado para conjuntos ordenados naturalmente como, por exemplo, um dicionário, uma lista telefônica etc. No exemplo, a seguir, confira um dos usos do Collection e Arraylist.
package com.senai.collection; import java.util.ArrayList; import java.util.Collection; public class Main { public static void main(String[] args) { /* na declaração abaixo pode-se observar o uso do mecanismo chamado * generic. */ Collection alunos = new ArrayList(); alunos.add(“João”); alunos.add(“Maria”); alunos.add(“Ana”); alunos.add(“Marcelo”); for (String aluno : alunos) { System.out.println(aluno); } } }
84
CURSOS TÉCNICOS SENAI
Na declaração da coleção alunos, pode-se observar o uso do mecanismo chamado generic. Uma coleção pode conter qualquer tipo de objeto, entretanto, é importante para o compilador Java, identificar que tipo de dado será utilizado e assim promover algumas validações. Por exemplo, se a coleção está definida para receber String, o compilador emitirá um erro se o desenvolvedor tentar adicionar um objeto do tipo Long. Nesta aunidade de estudos você teve uma visão geral sobre as Collections. Na próxima unidade, você conhecerá o JDBC e sua interface. Para aprofundar mais o seu estudo, faça pesquisas e procure por literaturas na área. Isso ajudará a fortalecer o seu aprendizado.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
85
Unidade de estudo 7 Seções de estudo Seção 1 – Visão geral Seção 2 – Interfaces do JDBC
JDBC SEÇÃO 1
Visão geral Java Database Connectivity (JDBC) é uma API na qual é definido um conjunto de classes e interfaces, que viabilizam a conexão entre uma aplicação Java e um banco de dados. Essas classes e interfaces ficam agrupadas no pacote java.sql. O JDBC possibilita que as aplicações possam:
▪▪ fazer uma conexão com um banco de dados; ▪▪ criar uma instrução usando SQL; ▪▪ executar um consulta SQL no
banco de dados;
▪▪ recuperar e manipular o resultado de um consulta; ▪▪ executar Stored Procedures. Dada a diversidade de bancos de dados existentes e as especificidades de cada um, os fornecedores precisam desenvolver o driver JDBC, implementando as interfaces da API. As aplicações ficam livres dos detalhes de cada banco, permitindo uma certa independência de plataforma. Um JDBC “Driver” é um conjunto de classes, que implementam as interfaces de JDBC. Esse conjunto de classes concretas é quem fará a ponte entre o código cliente, que usa a API JDBC, e o banco de dados. São essas classes que sabem se comunicar por meio do protocolo proprietário do banco de dados.
Confira os tipos de drivers JDBC.
▪▪ Ponte JDBC-ODBC: provê acesso por um ou mais drivers de ODBC.
Middleware: São sistemas de software que intermedeiam e/ou integram outros sistemas de software.
▪▪ Native-API: converte chamadas JDBC em chamadas no programa cliente para Oracle, Sybase, Informix, DB2, ou outro DBMS. Essa classe de Driver requer que algum código binário esteja carregado em cada máquina do cliente. ▪▪ Net-Protocol: traduz JDBC API para um protocolo DBMS independente, que é traduzido, então, a um protocolo de DBMS por algum server. Esse middleware de servidor de rede pode conectar Java aos clientes, baseado em muitos bancos de dados diferentes. ▪▪ Native-Protocol: converte um JDBC em um protocolo de rede usado diretamente por um DBMS. Faz com que o Java seja a própria ponte entre a base, tornando-se um programa cliente.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
87
SEÇÃO 2
Interfaces do JDBC Um driver de banco de dados tem que prover uma classe que implementa a interface java.sql.Driver. Essa classe é, então, registrada pela classe java.sql.DriverManager para se conectar a um banco de dados. O DriverManager, por meio do método getConnection, recebe como parâmetro uma String de conexão JDBC e retorna um objeto do tipo Connection. Connection é uma conexão com um banco de dados específico. Dentro do contexto de uma conexão, são executadas declarações SQL e devolvidos resultados. Observe um exemplo de conexão. public class TesteConexaoBanco { public static void main(String[] args) throws SQLException { Connection conexao = DriverManager.getConnection( “jdbc:postgresql://localhost:5432/ControleClientes”,”user”,”user”); System.out.println(“Conectado!”); conexao.close(); } }
O Driver JDBC precisa estar carregado na JVM no momento da execução. O Driver deve ser adicionado ao projeto,caso contrário, durante a execução desse código será gerado um erro do tipo “java.sql.SQLException: No suitable driver found...”. Na figura, a seguir, pode-se ver o local onde o driver deve ser adicionado. Observe.
Figura 43: Editor de texto executando
88
CURSOS TÉCNICOS SENAI
Durante a carga das classes presente no classpath, o Driver irá registrar-se, possibilitando o seu uso. O desenvolvedor pode fazer isso, explicitamente, observe o exemplo a seguir.
//algum código ... //registrando a classe do driver Class.forName(“com.progress.sql.jdbc.JdbcProgressDriver”); Connection conexao = DriverManager.getConnection( “jdbc:postgresql://localhost:5432/ControleClientes”,”user”,”user”); //algum código...
Confira, a seguir, as interfaces relevantes do JDBC.
▪▪ Statement: é a interface utilizada para executar uma declaração SQL e obter o seu resultado. ▪▪ PreparedStatement: é a interface utilizada para representar uma declaração pré-compilada de SQL. ▪▪ CallableStatement: é uma interface que executa procedimentos
SQL.
▪▪ ResultSet: um ResultSet provê acesso a um conjunto de dados. Um objeto ResultSet, normalmente, é gerado executando uma Statement. ▪▪ ResultSetMetaData: é a interface utilizada para ter acesso aos tipos e propriedades das colunas de um ResultSet. ▪▪ DatabaseMetaData: retorna informações sobre o banco de dados como um todo. A inserção de valores em uma tabela pode ser feita por meio do uso de Statement e PreparedStatement. A seguir, você poderá ver um exemplo de inserção de valores, utilizando as duas opções, e, logo após, uma figura com um exemplo contendo o conteúdo inserido.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
89
package com.senai.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; public class TesteInsert { public static void main(String[] args) throws SQLException { Connection conexao = DriverManager.getConnection( “jdbc:postgresql://localhost:5432/ControleClientes”, “postgres”, “123”); System.out.println(“Conectado!”); //insere registros com statement Statement stmt = conexao.createStatement(); stmt.executeUpdate(“INSERT INTO \”Cliente\” values(0,’Alan Turing’,” + “’Rua dos Cientistas, n. 85’,’1597-2584’,’ ‘,’ ‘,0)”); stmt.close(); //insere registros com preperadStateme PreparedStatement preStmt = conexao.prepareStatement( “INSERT INTO \”Cliente\” values(?,?,?,?,?,?,?)”); preStmt.setLong(1, 2); preStmt.setString(2, “Diogo”); preStmt.setString(3, “Rua dos Desenvolvedores, 21”); preStmt.setString(4, “2357-1113”); preStmt.setString(5, “Joao”); preStmt.setString(6, “7532-2357”); preStmt.setLong(7, 2); preStmt.execute(); preStmt.close(); onexão.close(); } }
Figura 44: Registros inseridos
90
CURSOS TÉCNICOS SENAI
Utilizando o Statement é possível retornar os valores de uma consulta. O método que realiza esta operação é o executeQuery. O retorno da sua execução é um ResultSet. Você pode observar isso, no exemplo de código, a seguir.
package com.senai.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TesteSelect { public static void main(String[] args) throws SQLException { Connection conexao = DriverManager.getConnection( “jdbc:postgresql://localhost:5432/ControleClientes”, “postgres”, “123”); System.out.println(“Conectado!”); Statement stmt = conexao.createStatement(); ResultSet rs = stmt.executeQuery(“Select * from \”Cliente\””); System.out.println(“* Imprimindo contatos *”); while(rs.next()){ System.out.print(rs.getInt(“uid”)+”, “); System.out.print(rs.getString(“nome”)+”, “); System.out.print(rs.getString(“endereco”)+”, “); System.out.print(rs.getString(“telefone”)+”, “); System.out.print(rs.getString(“nome_contato”)+”, “); System.out.print(rs.getString(“telefone_contato”)+”, “); System.out.println(rs.getInt(“tipo”)); } stmt.close(); conexao.close(); } }
Outra forma possível é por meio de um objeto PreparedStatement. Confira esse detalhamento, no exemplo, a seguir.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
91
package com.senai.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class TesteSelectPreparedStatement { public static void main(String[] args) throws SQLException { Connection conexao = DriverManager.getConnection( “jdbc:postgresql://localhost:5432/ControleClientes”, “postgres”, “123”); System.out.println(“Conectado!”); PreparedStatement preStmt = conexao.prepareStatement( “Select * from \”Cliente\” where nome=?”); preStmt.setString(1, “Diogo”); ResultSet rs = preStmt.executeQuery(); System.out.println(“* Imprimindo contatos *”); while(rs.next()){ System.out.print(rs.getInt(“uid”)+” “); System.out.print(rs.getString(“nome”)+” “); System.out.print(rs.getString(“endereco”)+” “); System.out.print(rs.getString(“telefone”)+” “); System.out.print(rs.getString(“nome_contato”)+” “); System.out.print(rs.getString(“telefone_contato”)+” “); System.out.println(rs.getInt(“tipo”)); } preStmt.close(); conexao.close(); } }
92
CURSOS TÉCNICOS SENAI
Está vendo quanta coisa importante ainda vem pela frente? Então, prepare-se, pois na próxima unidade de estudos, você aprenderá a preparar o ambiente de trabalho, instalando JDK, NetBeans e PostgressSQL. Até mais!
PROGRAMAÇÃO ORIENTADA A OBJETOS II
93
Unidade de estudo 8 Seções de estudo Seção 1 – Instalando JDK e NetBeans Seção 2 – Instalando o PostgresSQL
Preparando o Ambiente de Trabalho SEÇÃO 1
Instalando JDK e NetBeans Todas as ferramentas utilizadas, nos exemplos, são ferramentas gratuitas e disponíveis para download. Elas possuem tanto versões Java, quanto Linux, além de versões para outros sistemas operacionais. Neste material, será detalhada apenas a versão para Windows O primeiro passo é instalar o JDK. Para isso, é necessário baixar o instalador do site da Oracle, disponível em . Uma das opções é JDK+NetBeans Bundle.
Figura 45: JDK + NetBeans
Em seguida, deve-se aceitar a o termo e optar por baixar a versão Windows. Terminado o download, o instalador deve ser executado. No instalador, é necessário aceitar o termo de licença. Após isso, será solicitado o local de instalação. Finalizada a instalação, deve-se configurar duas variáveis de ambiente. Com elas, é possível, utilizar o Java via console em qualquer diretório. Esse processo é feito no painel de controle, opção sistema e botão variáveis de ambiente. PROGRAMAÇÃO ORIENTADA A OBJETOS II
95
Figura 46: Adicionando variáveis de ambiente
É hora de criar as variáveis.
▪▪ JAVA_HOME: indica onde a versão do Java está instalada. O conteúdo deve ser o caminho para instalação. Exemplo: C:\Arquivos de Programas\Java\jdk1.6.0_07 ▪▪ PATH: possivelmente, já deve existir esta variáviel. Portanto, deve-se acrescentar ao conteúdo, o caminho completo para se chegar à pasta bin do Java. Por exemplo: C:\Arquivos de Programas\Java\ jdk1.6.0_07\bin\. É possível utilizar a variável JAVA_HOME como parte do caminho na variável PATH. Utilizando o mesmo exemplo, ficaria desta forma: %JAVA_HOME%\bin\
96
CURSOS TÉCNICOS SENAI
SEÇÃO 2
Instalando o PostgresSQL O banco de dados, utilizado no exercício, foi o PostgresSQL. Para instalá-lo é necessário baixá-lo do site .
Figura 47: PostgreSQL
A instalação é um processo simples, mas é preciso atenção com a senha de administração do PostgreSQL informada . Feita a instalação, deve-se criar um banco de dados chamado ControleClientes. Crie um usuário senai (senha senai) e atribua permissão total a esse usuário. Veja o script detalhado de criação da tabela Cliente, utilizada nos exemplos.
CREATE TABLE “Cliente” ( uid integer NOT NULL, nome character varying(50) NOT NULL, endereco character varying(200) NOT NULL, telefone character varying(25), nome_contato character varying(50), telefone_contato character varying(25), tipo integer NOT NULL DEFAULT 0, CONSTRAINT pk_cliente PRIMARY KEY (uid) )
PROGRAMAÇÃO ORIENTADA A OBJETOS II
97
O driver JDBC para PostgresSQL pode ser obtido em . Nos exemplos, foi utilizado o driver tipo 4. Não é preciso instalar o driver, basta copiá-lo para algum diretório do sistema. Nos exemplos, considerou-se que o driver foi copiado para uma pasta jar no diretório de instalação do postgress.
Figura 48: Driver JDBC PostgreSQL
98
CURSOS TÉCNICOS SENAI
Nesta unidade de estudos, você aprendeu como instalar o JDK, o NetBeans e o PostgresSQL. Porém, não basta apenas instalar, é preciso fazer a codificação. É isso que você aprenderá na próxima unidade. Então, prepare-se!
PROGRAMAÇÃO ORIENTADA A OBJETOS II
99
Unidade de estudo 9 Seções de estudo Seção 1 – Classes, interfaces e pacotes Seção 2 – Nomeando atributos e variáveis Seção 3 – Métodos Seção 4 – Endentação, comentários, blocos de código, espaços e linhas brancas
Padrões de Codificação
SEÇÃO 1
Classes, interfaces e pacotes Existe um conjunto de práticas e padrões, adotados pela comunidade Java, que devem ser seguidos. Uma vez seguidos esses padrões, fica fácil compreender exemplos, tutoriais e projetos disponíveis na internet. Uma classe deve atender apenas uma responsabilidade, que deve ser descrita em um javadoc. Cada classe/interface de um projeto deve estar em seu próprio arquivo com o mesmo nome da classe/ interface. Classes extensas de em ser evitadas. Entretanto, não há um número determinado - cada caso exige avaliação apropriada. A título de exemplo, se for preciso, desenvolver uma classe com mais de 500 linhas, deve ser considerado um forte indício que esta classe está tratando de mais de uma responsabilidade.
▪▪ evitar caracteres não ASCII (caracteres de língua de origem latina, como caracteres acentuados, cedilha etc.), caracteres especiais (@, #, $, %, &, *, _ etc.) ou números; ▪▪ se o nome de uma classe seja composto por mais de uma palavra, a
primeira letra de cada palavra deve ser maiúscula;
▪▪ nomes pluralizados devem ser evitados. A diferença entre os nomes das classes e os nomes das interfaces se refere ao tipo de palavra utilizado. As classes devem ser nomeadas, utilizando substantivos e as interfaces devem ser nomeadas para que passem a ideia de uma qualidade ou característica. Veja alguns exemplos de nomes de classes e interfaces. public class Pedido public class ClienteEspecial public class Boleto public interface Distribuido public interface OperacaoRemota
Os pacotes (package) devem-se ser nomeados, utilizando apenas letras minúsculas. O nome do pacote reflete a estrutura dos diretórios. Por exemplo, o pacote nomeado como com.senai.aulajava terá os arquivos que o compõem na pasta: \com\senai\ aulajava.
Os nomes de classes e interfaces devem seguir o seguinte padrão:
▪▪ a primeira letra de cada palavra deve ser maiúscula e as abreviações devem ser evitadas;
PROGRAMAÇÃO ORIENTADA A OBJETOS II
101
SEÇÃO 2
Nomeando atributos e variáveis Os nomes dos atributos e das variáveis devem ser escritos com letras minúsculas. Nos casos de nomes compostos, a primeira letra de cada palavra deve ser grafada com letra maiúscula. Deve-se evitar:
▪▪ o uso de sublinhado; ▪▪ o cifrão ($) – porque este caracter tem significado especial a classes
internas;
▪▪ caracteres não ASCII e números. Veja alguns exemplos: String clienteAtual; int valorTotal; float totalizador;
Nos atributos de classe não se deve acrescentar o nome da classe, evitando, assim, situações como: classe Conta possuir o atributo saldoConta. Aqui, o correto seria chamar o atributo de saldo.
Deve-se nomear as constantes com todas as letras maiúsculas e com as palavras separadas por sublinhado. Exemplo: public final int NUM_DIAS_SEMANA; public final short VELOCIDADE_MAXIMA;
Nome de atributos e variáveis, que representam coleções, vetores ou matrizes devem ser nomeados no plural. List livros; public Aluno []alunos;
102 CURSOS TÉCNICOS SENAI
SEÇÃO 3 Métodos
Os métodos devem executar apenas uma tarefa. A operação deve ser descrita em javadoc, onde também devem ser detalhados os parâmetros recebidos pelo método. Deve-se evitar métodos muito extensos.
Assim, como as variáveis e os atributos, os nomes de métodos devem ser escritos com letras minúsculas. Nos casos de nome compostos, , a primeira letra de cada palavra deve ser grafada com letra maiúscula. Não se deve utilizar o caractere sublinhado (underscore) e deve ser evitado o uso de caracteres não ASCII e números. Os métodos, normalmente, devem utilizar verbos ou frases verbais. Métodos que retornem um tipo booleano devem usar prefixo “is”, seguido de um substantivo ou adjetivo. Os métodos que retornam o valor de um atributo do objeto são nomeados com substantivos com o prefixo “get”. Já os métodos que alteram o valor de um atributo do objeto são nomeados com substantivos com o prefixo “set”. Confira os exemplos: public boolean isAtiva() public void setQuantidade(long quantidade){ public double getSaldo(){ public void sacar(double value) public transferirValor(...)
Existem algumas recomendações gerais. Fique atento! Deve-se utilizar uma (e somente uma) linha em branco antes de cada bloco de código. Deve-se colocar um espaço (e somente um) em branco entre cada operador em expressões. Deve-se utilizar em todas as estruturas as chaves {}. Isto se aplica mesmo nos casos referentes a declarações simples (com apenas uma linha).
Com as informações sobre os padrões de codificação, com certeza, ficará muito mais fácil entender todos os códigos vistos, até agora, e não restará dúvida na hora que você for escrever algum. Agora você já está apto a desenvolver aplicações Java!
SEÇÃO 4
Endentação, comentários, blocos de código, espaços e linhas brancas A endentação (indentação ou recuo) trata da organização do código fonte de um programa, de modo, a indicar as relações hierárquicas entre os elementos. Todos os elementos no mesmo nível ficam alinhados com o mesmo espaçamento da margem esquerda. No Java, seu papel é estético, melhorando a legibilidade do código fonte. Deve-se colocar apenas uma declaração por linha.
Esta deve estar a quatro espaços (ou uma tabulação do início do bloco de código). Os trechos, que não são óbvios, devem ser comentados, mas evite comentários desnecessários. .. Use o comentário de linha // para comentários curtos (//) e, para os comentários mais longos, utilize o bloco (/*...*/).. O comentário de documentação (/** ... */) deve ser utilizado para fornecer uma API de documentação para o seu programa, por meio do javadoc. PROGRAMAÇÃO ORIENTADA A OBJETOS II
103
Finalizando Parabéns, você chegou ao final deste curso. Esta unidade curricular buscou complementar seus conhecimentos em orientação a objetos. Foram abordados os principais assuntos que envolvem a aplicação da orientação a objetos no JAVA, as principais API´s e padrões de desenvolvimento. Com o domínio dos assuntos, aqui, apresentados, você não encontrará dificuldades em aprender, além do que foi apresentado para você, utilizando referências em livros ou na internet. Lembre-se que na área de informática e tecnologia é muito importante estar sempre atualizado. Sucesso na sua carreira e até uma próxima!
PROGRAMAÇÃO ORIENTADA A OBJETOS II
105
Referências ▪▪
BOOCH, Grady; RUMBAUGH, James; JACOBSON, Ivar. UML – Guia do Usuário. 2. ed. Rio de Janeiro: Campus, 2006.
▪▪
BLOCK, Joshua. Java Efetivo. 2. ed. São Paulo, SP: Editora Alta Books, 2008
▪▪
CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 Dias Java 2. 4. ed. São Paulo, SP: Campus, 2005.
▪▪
CAELUM. FJ-11 Java e Orientação a Objetos. Disponível em: . Acesso em: 01 abr. 2011.
▪▪
CAELUM. FJ-16 Laboratório Java com Testes, XML e Design Patterns. Disponível em: . Acesso em: 01 abr. 2011.
▪▪
CAELUM. FJ-21 Java para Desenvolvimento Web. Disponível em: . Acesso em: 01 abr. 2011.
▪▪
DEITEL, Paul J. Java: como programar. 6. ed. São Paulo, SP: Editora Pearson, 2005.
▪▪
LUCKOW, Decio Heinzelmann; MELO, Alexandre Altair de. Programação Java Para a Web – Aprenda a desenvolver uma aplicação financeira pessoal com as ferramentas mais modernas da plataforma Java. São Paulo: Novatec, 2010.
▪▪
ORACLE, Java at Glance. Disponível em: . Acesso em: 01 abr. 2011
▪▪
SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Tradução da segunda edição. Rio de Janeiro, RJ: Editora Alta Books, 2005.
▪▪
SINTES, Anthony. Aprenda Programação Orientada a Objetos em 21 dias. São Paulo, SP: Makron Books, 2002.
▪▪
SOMMERVILLE, Ian. Engenharia de Software. 8. ed. São Paulo: Pearson, 2007.
▪▪
WINCK, Diogo; GOETTEN, Vicente. AspectJ - Programação orientada a aspectos com Java. São Paulo: Novatec, 2006.
PROGRAMAÇÃO ORIENTADA A OBJETOS II
107
Equipe de Desenvolvimento de Recursos Didáticos Coordenação de Educação a Distância Beth Schirmer Coordenação Projetos EaD Maristela de Lourdes Alves Coordenação de Desenvolvimento de Recursos Didáticos Gisele Umbelino Projeto Educacional Angela Maria Mendes Israel Braglia Projeto Gráfico Daniela de Oliveira Costa Jordana Paula Schulka Juliana Vieira de Lima
Design Educacional Evelin Lediani Bao Capa, Ilustrações, Tratamento de Imagens D’imitre Camargo Martins Diego Fernandes Luiz Eduardo Meneghel Diagramação Carlos Filip Lehmkuhl Loccioni Revisão e Fechamento de Arquivos Daniela de Oliveira Costa Juliana Vieira de Lima Revisão Ortográfica e Normatização SENAI/SC em Jaraguá do Sul
PROGRAMAÇÃO ORIENTADA A OBJETOS II
109