Apostila - Java Jse Programacao Basica - Atulizada PDF
Apostila - Java Jse Programacao Basica - Atulizada PDF
Apostila - Java Jse Programacao Basica - Atulizada PDF
ELISAMARA DE OLIVEIRA
Professor autor/conteudista
LUIZ CARLOS QUERINO FILHO
É vedada, terminantemente, a cópia do material didático sob qualquer
forma, o seu fornecimento para fotocópia ou gravação, para alunos
ou terceiros, bem como o seu fornecimento para divulgação em
locais públicos, telessalas ou qualquer outra forma de divulgação
pública, sob pena de responsabilização civil e criminal.
SUMÁRIO
Apresentação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1. A plataforma Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1. Histórico e evolução da linguagem Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.1. História da linguagem de programação Java . . . . . . . . . . . . . . . . . . 6
1.1.2. Principais conceitos da plataforma Java . . . . . . . . . . . . . . . . . . . . 8
1.2. IDE Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.1. Ambiente de desenvolvimento Java . . . . . . . . . . . . . . . . . . . . . . 11
1.2.2. Obtendo e instalando o Eclipse . . . . . . . . . . . . . . . . . . . . . . . . .12
1.2.3. Conhecendo o Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
1.2.4. Criando o primeiro projeto no Eclipse . . . . . . . . . . . . . . . . . . . . . 21
1.3. Estrutura básica de programação em Java SE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.3.1. Instruções de entrada e saída em janelas . . . . . . . . . . . . . . . . . . 33
1.3.2. Tipos primitivos do Java, strings e conversão de valores . . . . . . . . . 35
1.3.3. Conceitos básicos de memória, comparação de strings e strings
mutáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38
1.3.4. Uso do operador ternário . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.3.5. Projeto calculadora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3. Herança e polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.1. Herança em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.1.1. Conceito de herança . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.1.2. Superclasses e subclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.1.3. Exercício prático guiado: herança de cliente no sistema bancário . . . . 73
3.2. Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.2.1. Conceito de polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.2.2. Sobrecarga de métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.3. Polimorfismo na prática em Java: exercício prático guiado . . . . . . . . . . . . . . . . . 86
Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Glossário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
APRESENTAÇÃO
Seja bem-vindo(a), vamos trabalhar juntos nos conceitos e práticas essenciais da linguagem Java.
Vamos tratar da introdução formal ao mundo da linguagem Java por meio da sua “fundação
básica”, o Java SE (Standard Edition). A linguagem Java, dada sua história e imensa popularidade,
abrange uma série de áreas de utilização. O Java SE concentra-se em abranger os elementos básicos
dela, que são comuns para todas as aplicações, sejam programas do tipo desktop, aplicativos web
ou para dispositivos móveis. Ou seja, é o básico da linguagem, que você utilizará em praticamente
qualquer programa feito em Java.
Quando você estiver mais avançado dentro da tecnologia Java, conhecerá os outros campos
de aplicação da linguagem, como nos softwares empresariais e destinados à web que são criados
com o Java EE (Enterprise Edition), mas perceberá que o Java SE estará sempre lá com você. O
logotipo oficial da linguagem Java é exibido na figura 1.
FIGURA 1 - Java
Fonte: http://www.logoeps.com/java-eps-vector-logo/40925/
Então vamos lá! Prepare-se para mergulhar de cabeça na linguagem de programação orientada
a objetos mais usada no mundo.
Pág. 5 de 105
1. A PLATAFORMA JAVA
Vamos tratar de uma rápida introdução formal a Java, que pode ser definida não apenas como
uma linguagem de programação, mas também uma completa plataforma de desenvolvimento de
software. Veremos um pouco de sua história e seu modo de funcionamento e faremos a instalação
do ambiente de desenvolvimento integrado no qual criaremos nossos aplicativos.
Para entender o início da linguagem Java, temos que compreender a distinção básica entre os
paradigmas de programação orientado a objetos e estruturado.
No paradigma estruturado, que surgiu primeiro, os programas são definidos como uma coleção
de funções e estruturas de programação básicas, que por sua vez utilizam dados armazenados
em variáveis. Não há uma relação óbvia e direta entre funções e dados; é responsabilidade do
programador estabelecê-la, passando as variáveis como parâmetros das funções.
Já no paradigma orientado a objetos, tem-se uma relação mais direta entre dados e ações (as
funções da programação estruturada). Os dados possuem funções, que atuam diretamente sobre
eles (ou sobre outros dados).Isso ocorre colocando-os em unidades denominadas objetos, os
quais passam a ter também ações: passam a “saber” como usar ou processar seus dados (ou os
existentes em outros objetos).
Esta última, principalmente por usar como base a linguagem C,largamente conhecida pelos
programadores, tornou-se em pouco tempo a principal linguagem OO em uso. Porém tinha (e ainda
tem) alguns pontos negativos, como uma sintaxe complexa para declaração e uso de classes e um
Pág. 6 de 105
modelo de gerenciamento de memória manual, que obriga o programador a ter controle preciso
sobre a memória alocada para objetos.
De acordo com Deitel e Deitel (2010), em junho de 1991 James Gosling, Mike Sheridan e Patrick
Naughton, programadores da extinta Sun Microsystems (que foi adquirida pela Oracle em 2009),
começaram a desenvolver uma linguagem de programação OO que fosse mais fácil de ser aprendida
e utilizada do que C++. Além disso, deveria possuir recursos avançados de gerenciamento de
memória que livrassem o programador da tarefa de alocar e liberar recursos para os objetos e,
sobretudo, deveria poder ser executada em computadores de diferentes arquiteturas. Como eram
ávidos consumidores de café, batizaram a linguagem com o nome da ilha de onde vinha a sua
marca favorita da bebida: Java.
A linguagem Java foi lançada oficialmente em 1995 e, graças a seus recursos poderosos, sua
simplicidade e a facilidade no entendimento de sua sintaxe,além da capacidade de execução em
múltiplas plataformas, tornou-se rapidamente um sucesso. Outra característica importante que
contribuiu para o seu sucesso foi a existência de recursos para a sua utilização na internet. Na
época, o acesso à rede começava a ser disponibilizado comercialmente, vindo a alcançar milhões
de pessoas e a se tornar parte da vida de todo o mundo.
James Gosling, considerado o “pai do Java”, delineou no documento The Java language
environment (que se tornou a “definição formal” da linguagem) os cinco princípios básicos dela
(GOSLING; MCGILTON, 1997):
1. Java deve ser uma linguagem simples, orientada a objeto e com conceitos familiares aos
programadores.
2. Java deve ser robusta e segura.
3. Java deve ser neutra em relação à arquitetura de execução, ou seja, deve ser portável.
4. Java deve executar com alto desempenho.
5. Java deve ser interpretada, utilizar threads e ser dinâmica.
CURIOSIDADE
Vimos que existem as mais diversas linguagens de programação. Vejam quais são as linguagens
mais populares no site abaixo:
https://www.tiobe.com/tiobe-index/
À medida que se conhece a linguagem e seus recursos, percebe-se que, duas décadas depois,
esses princípios básicos foram plenamente alcançados e implementados.
Pág. 7 de 105
Em virtude de a Sun (e, hoje,a Oracle) sempre ter disponibilizado as ferramentas para criação
de programas Java pela internet (o JDK), a linguagem ganhou enorme aceitação na comunidade de
desenvolvedores, principalmente entre os entusiastas do chamado software livre ou open source.
Por essas e outras razões a Sun passou a liberar,em 2006, todo o código-fonte principal dela, usando
licenças livres como a GPL.
Hoje Java é, além de uma linguagem, uma plataforma completa de desenvolvimento e conta com
uma rica comunidade de suporte. A filosofia do software livre está tão presente nela que, apesar
de a marca ainda pertencer a uma empresa, todo o processo de atualização, melhoria e evolução
da linguagem é controlado por um grupo que envolve várias pessoas da comunidade, conhecido
como Java Community Process (JCP). Até mesmo a mascote oficial da linguagem, o Duke, tem seu
desenho liberado nos termos do software livre e pode ser usado sem restrições.
Fonte: https://commons.wikimedia.org/w/index.php?curid=3232280
Como dissemos, Java não é somente uma linguagem de programação, mas uma plataforma de
desenvolvimento de software. Mas o que isso significa?Que, junto da linguagem, existem bibliotecas,
ferramentas, frameworks e recursos para que o programador crie aplicativos nos mais diferentes
tipos de equipamentos, de computadores desktop a servidores e de smartphones a set-top-boxes.
Pág. 8 de 105
A plataforma Java (ou seja, a base em que os programas Java são executados) foi criada desde
o início com o intuito de ser utilizada nos mais variados tipos de aparelhos, com os mais diversos
tipos de processadores, arquiteturas e sistemas operacionais.
ATIVIDADE REFLEXIVA
A criação do Java foi uma atividade empreendedora de seus criadores. Vimos que foi uma ação muito
efetiva e que rendeu bons frutos. Você acha que na época não havia outras linguagens que podiam
dar conta do recado? E, na sua opinião, ainda hoje o Java é uma linguagem que continua dando certo?
Para conseguir sua meta de fazer um mesmo programa ser executado em diferentes plataformas,
o Java teve de seguir uma abordagem diferente.
Um programa Java (com código escrito em arquivos com a extensão .java também passa por
um processo de compilação. Mas o arquivo gerado pelo compilador Java (o javac) não conterá
código em linguagem de máquina, pois este é sempre dependente da plataforma na qual o programa
será executado. Ao invés disso, é gerado em bytecode, que são instruções que somente podem ser
executadas pelo Java Virtual Machine (JVM), a máquina virtual Java. Esse processo é ilustrado na
figura abaixo:
Pág. 9 de 105
contém o bytecode do programa. Esse bytecode apenas poderá ser executado por um programa
especial, a máquina virtual Java,que deverá estar sempre presente no computador no qual queremos
executar nosso programa. É tarefa da JVM ler o bytecode e convertê-lo para a linguagem de máquina
específica do computador e do sistema operacional no qual será executado.
O JDK contém, além do javac e das bibliotecas básicas da linguagem, uma cópia da máquina
virtual, que também é instalada. Isso porque, sem a JVM, não seria possível executar os programas
usando o comando java, que é o interpretador de bytecode, responsável por enviar o programa para
ser executado.
Fonte: https://commons.wikimedia.org/w/index.php?curid=12351968
Pág. 10 de 105
Quem não é programador não precisa, obviamente, instalar o JDK para obter a JVM. Por isso,
a Oracle disponibiliza também o Java Runtime Environment (JRE), que contém a máquina virtual
para que os usuários comuns possam executar os aplicativos escritos em Java no seu formato
compilado, ou seja, em bytecode.
Isso leva à seguinte conclusão: a máquina virtual Java funciona como uma espécie de tradutor
entre o bytecode e a linguagem de máquina do computador no qual o programa será executado.
Então, consequentemente, a máquina virtual deve ser feita “sob medida” para a plataforma (o tipo
de computador e sistema operacional) no qual o programa será executado.
Por essa razão, o computador (ou dispositivo) em que um programa escrito em Java será
executado possui uma máquina virtual construída especificamente para ele. Isso significa que
aquela usada em sistemas Windows não funciona em sistemas Linux. Você deverá ter instalada a
máquina virtual específica para seu computador e sistema operacional.
Contudo, à medida que os programas Java crescem em tamanho e complexidade, trabalhar com
linha de comando torna-se bastante improdutivo. Começa-se a gastar um tempo valioso no ciclo
de desenvolvimento do software. Para otimizar o processo de criação de um aplicativo, existem os
IDEs (integrated development environments ou ambientes de desenvolvimento integrado). Esses
programas integram um conjunto de recursos que auxiliam o desenvolvedor no processo de criação
de um software, como:
Pág. 11 de 105
• recursos de depuração visual, para que o programador possa executar o código linha por linha,
analisando os valores obtidos;
• acesso à documentação da linguagem.
Dada a imensa popularidade da linguagem Java, existem diversos IDEs disponíveis para utilização,
cada uma com suas vantagens e desvantagens. Os mais populares entre os desenvolvedores
são o Eclipse (livre e mantido por uma comunidade mundial de usuários) e o NetBeans (também
livre, mas mantido pela Oracle). Ambos possuem recursos avançados de edição, compilação e
teste de aplicativos Java, podendo ser considerados até mesmo equivalentes em quantidade de
funcionalidades.
Utilizaremos o Eclipse, que é o IDE mais utilizado pelos desenvolvedores Java, tanto no meio
acadêmico quanto no mundo empresarial.
SAIBA MAIS
Não é o IDE que compila os programas. Na maioria dos casos (como no Eclipse), ele funciona como
um intermediário entre o usuário e o compilador/interpretador da linguagem. É responsável por
passar o código digitado pelo usuário ao compilador e repassar o resultado (como erros e avisos).
Existem casos em que um IDE traz junto um compilador, mas, em outros, é necessário que o usuário
já o tenha instalado previamente.
O Eclipse é um software livre, com código-fonte aberto. Isso significa, entre outras coisas, que
você não precisa se preocupar com questões de licenciamento e pode usá-lo (e copiá-lo) livremente.
Após entrar no site, baixe o instalador do Eclipse Oxygen (codinome da versão mais recente
no momento da elaboração deste material) ou de uma versão mais nova (se já existir), clicando no
botão indicado na figura 5. O site colocará automaticamente a versão correta para seu sistema
operacional. Apenas fique atento com relação ao número de bits: se você ainda usar um sistema
operacional de 32 bits, clique no link Download packages e escolha a versão correta.
Pág. 12 de 105
FIGURA 5 - Obtendo o instalador do Eclipse
Fonte: http://www.eclipse.org/downloads.
CURIOSIDADE
Para executar o Eclipse, você precisa ter o Java instalado. Isso parece óbvio, já que o usaremos para
criar programas nessa linguagem. Mas tem outra coisa...
Por isso, você precisa do Java não somente para compilar e executar os programas, mas também
para poder executar a ferramenta usada no desenvolvimento dos seus aplicativos.
Após clicar na versão desejada, você será redirecionado para outra página, na qual poderá iniciar
o download. Com base na sua localização, o site do Eclipse escolherá o servidor mais rápido dentre
os disponíveis. A figura 6 ilustra esse processo.
Pág. 13 de 105
FIGURA 6 - Link para download do instalador do Eclipse.
Fonte: http://www.eclipse.org/downloads
Terminado o download, você obterá um programa executável que realizará o processo completo
de obtenção e instalação do Eclipse no seu computador. Execute o instalador clicando sobre ele
após ser baixado no seu navegador, ou localize-o na pasta de Downloads do seu sistema operacional
e clique duas vezes sobre o executável. A tela da figura 7 será exibida.
Pág. 14 de 105
FIGURA 7 - Início da instalação do Eclipse.
Na janela que será exibida, escolha a versão desejada do Eclipse. Para esta aula utilizaremos
o Eclipse IDE for Java Developers. Clique sobre esta opção.
A tela seguinte (figura 8) permite que você especifique a pasta onde o Eclipse será instalado.
Note que as duas opções marcadas farão que um atalho para o programa seja criado no menu
iniciar e na área de trabalho (no caso de instalação no sistema operacional Windows).
Pág. 15 de 105
FIGURA 8 - Opções de instalação do Eclipse.
SAIBA MAIS
O processo de instalação fará o download da versão escolhida. Por isso, é necessário que você tenha
uma conexão ativa com a Internet durante o processo.
Outro detalhe importante: não coloque o Eclipse em uma pasta (ou dentro de um caminho de
pastas) que contenha espaços ou caracteres internacionais (como acentos e cedilha), pois ele pode
apresentar problemas de execução.
Quando estiver pronto para iniciar o processo de instalação, clique no botão Install, como
indicado na figura 8.
Será mostrada em seguida a licença de utilização do Eclipse. Clique sobre o botão Accept Now
para que a instalação comece.
Pág. 16 de 105
Assim que todos os arquivos necessários tiverem sido baixados e instalados corretamente,
você poderá iniciar o Eclipse pelos atalhos criados ou clicando no botão Launch, que será exibido
no fim da instalação (Figura 9).
Ao abrir o Eclipse pela primeira vez, você será questionado sobre a localização do seu workspace
(espaço de trabalho). Esse é o nome que o programa dá para uma pasta dentro do seu computador
na qual ficarão armazenados os seus projetos. Todo projeto criado será, por padrão, gravado
dentro dela.
Pág. 17 de 105
O Eclipse sugere inicialmente que você use como seu workspace uma pasta nova com o
nome eclipse-workspace e que será criada dentro da pasta pessoal do seu usuário. Se quiser,
você pode mudar a pasta para uma de sua preferência - apenas tome cuidado para não definir
o workspace em um caminho que contenha espaços ou caracteres de acentuação/cedilha, para
evitar problemas futuros.
O item 2 trata-se de uma opção que, se marcada, definirá a pasta indicada como workspace
padrão e não perguntará mais por isso nas próximas inicializações. Se você tem certeza de que
esse será o melhor local para guardar seus projetos, marque essa caixa para que não tenha que
confirmar o workspace toda vez que abrir o Eclipse. Clique em OK em seguida.
Se você quiser mudar o workspace mais tarde, pode fazer isso clicando no menu File>Switch
Workspace>Other.
Depois de alguns segundos, você será apresentado à tela de boas-vindas do programa. Você
pode fechá-la clicando no “X”.
Pág. 18 de 105
FIGURA 11 - Tela de boas-vindas do Eclipse
Agora você poderá visualizar a tela principal do Eclipse. Essa é a chamada perspectiva Java. Como
o Eclipse tem uma grande variedade de recursos (podendo ser até usado para se criar programas
em C/C++ ou PHP), há uma série de possíveis configurações para sua tela principal. Cada uma é
chamada de perspectiva e é adequada a uma determinada situação. A perspectiva Java é a mais
usada por programadores.
Pág. 19 de 105
FIGURA 12 - Perspectiva Java do Eclipse
Veja na figura que temos uma barra de menus e logo abaixo uma barra de ferramentas, da mesma
maneira que na maioria dos aplicativos. A perspectiva Java possui ainda cinco partes internas,
indicadas na figura 12 como ‘a’, ‘b’, ‘c’, ‘d’ e ‘e’. São elas:
a) Package Explorer: é aqui que se visualizam os projetos criados no Eclipse e seus arquivos.
Todo programa Java criado nele será definido como um projeto, que consiste em um
conjunto de arquivos de código-fonte, configurações e bibliotecas, dentre outros.
b) Editor de código: nessa divisão central, são abertos os arquivos selecionados dentro de
um projeto, por meio do Package Explorer. Na maior parte do tempo, você estará com
arquivos com código Java abertos nesse local, em queeles poderão ser editados.
c) Task List: Você pode controlar nesta aba as tarefas ainda marcadas como “por fazer”
dentro do seu software. Não utilizaremos este recurso na nossa disciplina; por isso, se
quiser, pode fechar esta aba para disponibilizar mais espaço às outras abas do Eclipse.
Pág. 20 de 105
d) Outline: mostra uma estrutura hierárquica do código-fonte aberto. Por aqui você pode
localizar rapidamente elementos existentes no arquivo, como variáveis e métodos.
e) Problems/Console/JavaDoc - nessa área podem ser abertas diferentes abas, porém
aquelas com que você deverá ter mais contato são as seguintes:
◊ Problems: aqui serão exibidos os erros e demais avisos sobre problemas existentes no código.
◊ Console: essa aba será aberta quando você executar um aplicativo Java não gráfico, que
utiliza comandos de entrada e saída no console.
◊ JavaDoc: a importantíssima documentação da linguagem Java. Clicar em cima do nome
de uma classe ou método no código-fonte faz que sua documentação seja mostrada nessa
aba (requer que você esteja conectado à internet).
Quanto à barra de menus e aos botões da barra de ferramentas, conheceremos suas funções
aos poucos, à medida que desenvolvermos nossos aplicativos.
Chegou a hora de testarmos esse IDE.Para confirmar se o ambiente está funcional, faremos
uma versão do tradicional “Alô,mundo!”utilizando o Eclipse.
Crie um novo projeto Java no Eclipse clicando sobre a seta para baixo logo à direita do primeiro
botão da barra de ferramentas e selecionando Java Project no menu que será exibido.
Pág. 21 de 105
Em seguida, será mostrada uma janela, na qual deverá ser fornecido um nome para o projeto
em Project Name. Informe AloEclipse (dessa forma, sem espaço e sem acento na letra o) e clique
em Finish. Repare que, em Location, estará indicado que o projeto será gravado em uma subpasta
com esse mesmo nome (AloEclipse) dentro do seu workspace.
Depois de alguns segundos, você verá o projeto AloEclipse, recém-criado, listado no Package
Explorer. Clique sobre a seta à esquerda do nome do projeto para exibir seu conteúdo.
Pág. 22 de 105
FIGURA 15 - Projeto AloEclipse e seu conteúdo.
Observe que nosso projeto contém apenas dois itens: uma pasta denominada src e uma
referência à biblioteca básica do JavaSE, de onde vêm as classes fundamentais da linguagem.O
que nos interessa neste momento é a pasta src – é nela que colocamos o código-fonte em Java, e
podemos ver que por enquanto não temos nenhum.
Em Java, como em toda linguagem orientada a objetos, trabalhamos escrevendo nosso código
em classes. Dentro destas, usamos outras classes (algumas criadas por nós mesmos, outras já
existentes dentro da biblioteca básica do Java) para definir o funcionamento do nosso programa.
Na maioria das vezes, devemos instanciar as classes em objetos para podermos usá-las. Em alguns
casos, porém, não precisamos fazer isso: podemos usá-las diretamente.
Por que estamos falando nisso agora, quando ainda não temos nem mesmo uma classe? Porque
precisamos ter uma que sirva como “pontapé inicial”, que não será necessariamente usada para
criar objetos, mas que contenha dentro dela o início do programa.
Em Java, iniciamos o programa criando uma classe com um nome qualquer que contenha um
método especial: main(). Esse método foi definido para que programas Java tenham um ponto
de entrada, ou seja, possam ter um local determinado para começar. Basta escrevê-lo dentro da
primeira classe do projeto (que se torna sua classe principal), seguindo algumas regras básicas
com relação à sua sintaxe.
A “mágica” ocorre por meio do interpretador Java: quando executamos um aplicativo, ele
busca pelo método main() (que deve ter exatamente esse nome) para poder iniciar a execução do
programa.Por isso, criaremos uma classe de entrada no aplicativo (que chamaremos neste exemplo
de Principal) e, dentro dela escreveremos esse método.
Pág. 23 de 105
Já sabemos que a classe é a unidade básica de código em um programa Java. Como veremos
mais adiante, Java organiza as classes dentro de identificadores, chamados pacotes. Um pacote é
basicamente uma “classificação” para elas. Além de organizar melhor os aplicativos e bibliotecas,
possibilita que várias classes sejam criadas com o mesmo nome sem que ocorram conflitos (veremos
como isso é possível mais à frente).
Por isso, antes de criar uma classe, precisamos criar a categoria na qual ela será arquivada, ou
seja, o seu pacote. Quando criamos um pacote dentro do Eclipse, é criada uma subpasta dentro
da pasta principal de fontes do seu projeto. Quando uma classe for definida como pertencente ao
pacote, será colocada dentro dessa pasta. Simples assim.
Para criar um pacote, clique sobre a pasta src e em seguida sobre o botão New Java Package
na barra de ferramentas.
Nomes de pacote devem ser definidos sempre com letras minúsculas – essa é a primeira de
uma série de convenções usadas pela maioria dos programadores Java que você deve seguir. Outra
coisa: existe uma forma padronizada de definir qual o nome de um pacote; veremos isso mais
adiante. Por enquanto, defina-o com o mesmo do projeto, só que em letras minúsculas (aloeclipse).
Escreva o seu nome em Name e depois clique em Finish.
Pág. 24 de 105
FIGURA 17 - Criando um novo pacote de classes Java.
Observe à esquerda, no Package Explorer, que agora possuímos um pacote denominado aloeclipse
dentro da pasta src. Ele está vazio – precisamos colocar nossa classe dentro dele. No Package
Explorer, clique sobre o pacote aloeclipse; em seguida, clique sobre o botão New Java Class na
barra de ferramentas. Com essa ação, indicamos ao Eclipse que queremos criar uma nova classe
Java e que ela deverá ser colocada dentro do pacote que selecionamos.
Pág. 25 de 105
A janela mostrada será exibida. Nela, podemos configurar vários aspectos da nova classe a ser
criada.Você pode perceber que, em razão de termos selecionado o pacote aloeclipse no Package
Explorer, o Eclipse já detectou que essa classe pertencerá a ele (veja a configuração Package) e
que seu arquivo correspondente ficará na pasta src do projeto (indicado em Source Folder).
Siga o que está indicado na figura e informe o nome da classe (em Name) como Principal (dessa
maneira exata, com a letra P maiúscula e as restantes minúsculas). Também não se esqueça de
marcar a caixa indicada pela outra seta (public static void main). Em seguida, clique sobre o botão
Finish para que a classe seja criada.
Pág. 26 de 105
SAIBA MAIS
A linguagem Java é case sensitive. Portanto, nomes de classes, variáveis, métodos, objetos, ou seja,
identificadores em geral, devem sempre ser escritos levando em consideração essa diferenciação.
Apesar de Java diferenciar maiúsculas das minúsculas nos nomes, o programador é livre para usá-las
da maneira que bem entender. Isso quer dizer que você pode criar uma classe chamada Principal ou
PRINCIPAL.
A maioria dos programadores (e a Oracle, até) segue um padrão de como usá-las. Um deles é sempre
começar o nome de uma classe com uma letra maiúscula. Esta disciplina foi escrita seguindo (e
indicando) o uso desses padrões conforme necessário, para que você vá se habituando aos poucos.
Ao selecionar a caixa de marcação public static void main, indicamos ao Eclipse que essa
classe deverá ser criada contendo um método main() vazio, que servirá como “porta de entrada”
ao nosso aplicativo.
Como você já sabe, esse é um método muito especial da linguagem Java e deve sempre ser
declarado e escrito seguindo uma sintaxe específica, para que a máquina virtual do JRE possa
encontrá-lo (se ele existir) no seu programa.
SAIBA MAIS
Métodos são os nomes dados às funções desempenhadas pela classe, ou seja, às suas ações. Os
métodos são as implementações do que foi denominado operações em UML.
Pág. 27 de 105
Veja o novo arquivo criado no seu projeto, o Principal.java. Ele será aberto na tela central
do Eclipse.
Um arquivo .java é um arquivo de texto sem formatação,que pode ser editado com qualquer
editor. Mas, quando é aberto dentro do Eclipse, possui sua sintaxe colorizada e também passa a
ser processado pelo editor do programa;com isso, você recebe alguns avisos e dicas na barra cinza
à esquerda do código.
Veja, por exemplo, o ícone de um bloco de notas logo à esquerda da linha //TODO na figura.
Isso indica que o Eclipse a reconheceu como um tipo de comentário especial, usado para designar
tarefas a ser realizadas no software.
Pág. 28 de 105
SAIBA MAIS
Um recurso importante do Eclipse, que vem desabilitado por padrão, é a exibição dos números das
linhas do código, à esquerda. Essa exibição ajuda em vários aspectos, como a localização de erros.
Habilite a exibição dos números de linha clicando no menu Window > Preferences do Eclipse. Na
janela que será aberta, clique sobre a chave General > Editors > TextEditors, à esquerda, e marque, à
direita, a opção Show line numbers.
Em seguida, clique em OK para que a numeração passe a ser exibida na coluna da esquerda do editor
de código.
Aproveitando que os números de linhas apareceram, vamos entender o conteúdo desse arquivo
a partir do código mostrado no quadro 1:
• Linha 1: definimos que a classe existente nesse arquivo pertence ao pacote (package) aloeclipse.
• Linha 3: aqui, inicia-se a classe Principal. A palavra-chave public indica o seu encapsulamento
(público, ou seja, essa classe é acessível por qualquer outra). O identificador class indica que
se trata, obviamente, de uma classe, e deve ser seguido pelo nome dela. Ao final da linha,
abrimos um bloco de chaves que somente será fechado na linha 10.
• Linha 5: dentro de uma classe, definimos seu conteúdo (ou seja, seus atributos e operações).
Nesse caso, começamos a definir um método (operação). Esse método, como já vimos, é
especial: serve como ponto de entrada para a execução do programa. Por isso, sua declaração
deve seguir esse padrão: ser público (public), estático (static), não retornar valores (void) e
chamar-se main, recebendo como parâmetro um vetor de strings (String[]). O método começa
nessa linha e termina na linha 8.
Pág. 29 de 105
Agora, vamos ao que interessa: programar. Logo abaixo da linha do comentário //TODO (que
você pode remover, se quiser), insira o comando a seguir:
Poderíamos ter usado também System.out.println, que funcionaria normalmente. Mas vamos
variar e ver como fica melhor.
Estamos usando aqui uma classe do Java (ou seja, ela faz parte da biblioteca padrão da linguagem)
chamada JOptionPane. Ela é utilizada para exibição de uma pequena janela de mensagens e faz
parte de um framework (um conjunto de classes) chamado Swing – esse é o nome do pacote de
componentes gráficos que o Java usa para a criação de aplicativos em janelas.
O ponto (.) logo após JOptionPane indica que vamos usar um de seus métodos (ou seja, as
ações que essa classe sabe fazer). Nesse caso, estamos chamando o método showMessageDialog.
Esse método exibe uma pequena janela contendo o texto passado como segundo argumento
(uma string Java). O primeiro argumento pode ser mantido como null, pois somente é usado em
casos em que a janela de mensagem será exibida por outra janela.
Não podemos executar nosso projeto ainda. Existe um erro nele, como você pode ver pelo
sublinhado em vermelho na linha 7, como mostra a figura:
Pág. 30 de 105
O Eclipse, além de detectar que existe um erro relacionado à classe JOptionPane, proporciona
formas automatizadas de tentar resolver o problema (trata-se de um recurso denominado QuickFix).
Você pode ver as sugestões de correção de duas formas: clicando e mantendo o cursor do mouse
sobre o elemento com erro ou clicando diretamente no símbolo da pequena lâmpada com um “x”
na coluna da esquerda. Das duas maneiras, será exibido um menu com sugestões de possíveis
soluções, como na figura 22.
Não basta simplesmente clicar em qualquer uma das soluções e achar que tudo será resolvido.
Você deve saber o que está corrigindo, antes de tudo.
Esse erro está relacionado a um fato muito simples: o Java está dizendo que não conhece a
classe JOptionPane. “Mas como?”, você pergunta. “Você não disse antes que JOptionPane é parte
da biblioteca padrão do Java?”. Ocorre que a classe está lá, mas a nossa classe Principal ainda não
foi informada sobre sua existência. Isso é feito usando um comando da linguagem Java chamado
import, que faz com que uma classe passe a ser “reconhecida” dentro da outra.
Clique sobre a primeira sugestão da lista, como indicado na figura, e veja o que mudou no seu
código. Primeiro: o erro sumiu. Segundo, a linha exibida a seguir foi adicionada ao código, logo
depois de package.
Pág. 31 de 105
import javax.swing.JOptionPane;
Por que existe javax.swing antes do nome da classe? Trata-se do pacote ao qual ela pertence,
pois não são só as classes criadas que pertencem a pacotes.
Agora sim podemos executar o programa e ver o que acontece.Só uma precaução antes: salve!
Você deve ter notado, no lado esquerdo do nome do arquivo Principal.java, na aba do editor de
código, um pequeno asterisco (*). Ele indica que o arquivo ainda não foi salvo.
Habitue-se a salvar todo o conteúdo do seu projeto de tempos em tempos. Para isso, prefira
usar sempre o botão Save All, para salvar tudo de uma vez só, como indicado na figura.
Se não estivéssemos usando um IDE, agora seria o momento de compilar o arquivo.java para
bytecode (arquivo .class) e executá-lo com o interpretador java. Mas tudo isso é automatizado pelo
IDE clicando sobre um simples botão do Eclipse: o Run.
Pág. 32 de 105
Em poucos segundos, seu aplicativo será executado e compilado, e uma pequena janela com
a mensagem “Alô, Eclipse!” será exibida.
Muito bem, agora você sabe como é criar um aplicativo Java usando uma ferramenta de
desenvolvimento integrado.
Para saída de dados no console (em modo apenas texto) você já foi apresentado ao comando
System.out.println(), que imprime na tela o argumento passado a ele, seguido de uma quebra de linha.
Com a intenção de começar a usar recursos de interface gráfica, passaremos a utilizar a classe
JOptionPane, que faz parte do framework Swing, o padrão atual para construção de aplicativos em
janela em Java.
Pág. 33 de 105
A classe JOptionPane possui vários métodos estáticos para exibição de caixas de mensagens
– pequenas janelas contendo algum tipo de informação.
SAIBA MAIS
Em resumo, métodos estáticos são aqueles executados diretamente de uma classe e não de um
objeto instanciado a partir dela. Falaremos mais sobre eles em breve.
Existe também um outro método estático importante em JOptionPane que serve para a entrada
de dados: o showInputDialog(). Chamando esse método, uma pequena janela semelhante à do
showMessageDialog() será mostrada, com uma novidade: uma caixa de entrada de texto para que
o usuário digite algo. Esse valor digitado será devolvido como uma string por esse método. Veja
sua sintaxe básica:
O usuário digita a informação na caixa e, após clicar no botão OK, o valor informado será
retornado como uma string. No código mostrado acima, guardamos esse retorno em uma string
chamada nome.
Pág. 34 de 105
Acrescente a linha abaixo ao seu código e veja como, dessa maneira, criamos um pequeno
programinha muito bem educado.
SAIBA MAIS
Neste ponto, você já deve ter visto o recurso de autocompletar em ação. Ele aparece alguns segundos
após você digitar um ponto depois do nome de um objeto ou classe ou quando está escrevendo
qualquer identificador e pressiona CTRL + ESPAÇO.
FIGURA 27 – Autocompletar do Eclipse
Além de um grande economizador de tempo, ele ajuda você a aprender mais sobre a linguagem,
investigando métodos e classes disponíveis. Outra vantagem: ao usá-lo, o Eclipse faz o import da
classe referente ao método escolhido!
Você já conhece os tipos básicos (também chamados tipos primitivos) de Java, como int (para
valores inteiros), double (para valores decimais), char (para um único caractere) e boolean (para
valores true, verdadeiro, ou false, falso).
Pág. 35 de 105
É importante lembrar que Java trata números literais sem ponto decimal como int e aqueles
que possuem ponto como double. Ou seja, int e double são os tipos default para valores numéricos
colocados diretamente no código. Por exemplo, o compilador Java vai considerar que estamos
passando um int para o método na linha a seguir:
produto.adicionarQuantidadeAoEstoque(5);
No exemplo abaixo, como o valor passado possui ponto decimal, será considerado como um
double:
aluno.gravarMedia(9.5);
Você também já conhece uma string. Em Java, ela (que é uma sequência de caracteres
alfanuméricos) não é um tipo primitivo, mas, efetivamente,uma classe. Por isso, quando usamos
e declaramos uma string, não estamos lidando com uma variável simples, mas com um objeto. A
diferença é que objetos são mais complexos e poderosos que variáveis de tipos primitivos.
Um recurso muito versátil das strings Java é sua possibilidade de concatenação, ou seja, de
junção de duas ou mais em uma nova. A concatenação é realizada usando o sinal de adição (+)
entre elas. Veja o exemplo no quadro:
Pág. 36 de 105
Apesar de a conversão no sentido valor numérico -> string ser automática quando esses valores
são concatenados, há situações em que precisamos fazê-la manualmente. Isso ocorre principalmente
na entrada de dados.
Sabemos que o método showInputDialog() do JOptionPane retorna o valor informado com uma
string. Pois bem: suponha que estamos solicitando ao usuário um valor numérico que será usado
em um cálculo matemático. Não poderemos realizar operações matemáticas em um objeto string.
Precisamos obter um valor em um tipo numérico (int ou double, por exemplo) a partir desse valor.
Para obter o valor int equivalente a uma string, usamos o método parseInt(), existente na classe
Integer (uma classe utilitária para inteiros, usada também quando precisamos tratar um valor inteiro
como um objeto, e não como um tipo primitivo int). Passamos a esse método a string contendo o
valor numérico, e ele nos devolve o int equivalente. O quadro 3 ilustra esse processo.
Já no caso de double, usamos o método parseDouble(), disponível na classe Double (outra classe
utilitária, também utilizada nos casos em que é necessário um objeto contendo um valor com casas
decimais), com funcionamento semelhante ao anterior. Veja exemplo no quadro.
Pág. 37 de 105
SAIBA MAIS
Suponha que, no exemplo anterior, o usuário inadvertidamente forneça um número inválido como
valor de conta, incluindo, por exemplo, letras no campo de digitação. Exemplos: “12mmn”, “3.4Stt”,
“asdasd”.
Nesses casos, não será possível realizar a conversão. Ocorrerá o que chamamos de exceção em Java.
Para impedir que o usuário receba uma mensagem de erro, precisamos tratar a exceção, ou seja,
definir alguma ação caso ela ocorra. Fazemos isso em Java usando a instrução try...catch.
Para o caso de uma conversão numérica, poderíamos tratar o erro de fornecimento de um valor
inválido da seguinte forma:
FIGURA 28 – Erro de fornecimento
Caso o método parseDouble() não consiga realizar a conversão, será disparada a exceção
NumberFormatException. O bloco catch será então executado, mostrando uma mensagem de aviso
ao usuário.
Em Java, objetos, assim como variáveis, são alocados como espaços na memória do computador.
Os nomes que definimos para eles servem apenas como referências a essas áreas. É por esse
motivo que não devemos comparar duas strings em Java usando o sinal de igualdade (==), e sim o
método equals, existente nos objetos dessa classe.
Quando comparamos duas strings usando ==, não será feita uma comparação do conteúdo,
mas sim da posição de memória ocupada pelo objeto. Mas, quando usamos equals(), a comparação
é feita precisamente pelo conteúdo. Por isso, sempre que precisar comparar strings por valor em
Java, prefira usar equals().
Mas há uma outra questão importante, também relativa ao uso de memória em Java.Toda vez
que declaramos um objeto da classe String,estamos definindo uma cadeia de caracteres imutável.
Pág. 38 de 105
Isso significa simplesmente que, após definir o conteúdo de uma string, não podemos mais modificar
seu conteúdo. Ou seja, não podemos acrescentar, remover ou trocar caracteres dentro dela. Isso
só pode ser feito por meio de uma reatribuição.
Suponha que estejamos construindo uma string que vai conter uma lista de nomes de candidatos
aprovados em um concurso. O código anterior resulta em uma lista impressa na tela semelhante a:
Pode-se tirar duas conclusões nisso: obteve-se o resultado pretendido e foi possível mudar
o valor da string resultado, pois concatenamos a ela duas linhas novas de texto. Mas isso não é
realmente o que aconteceu.
A string resultado continua imutável. O que fizemos foi, nas duas últimas linhas do código,
reatribuir um valor a ela, composto do seu conteúdo anterior concatenado com a nova linha. Isso
resulta em duas cópias (para cada linha de concatenação) da variável na memória.
Em um exemplo como esse, ou com algumas poucas linhas a mais, não haveria grandes
problemas em relação a uso de memória e desempenho do programa. Porém, suponha que estejamos
montando uma string resultante da concatenação (usando reatribuição) de centenas de linhas
em um laço. Isso significa centenas de cópias desnecessárias da variável na memória, com seu
conteúdo crescendo exponencialmente, ou seja, muita memória desperdiçada e sérios problemas
de desempenho para o aplicativo.
Em casos como esse, é muito mais interessante usar a classe StringBuilder do Java, que foi criada
justamente para essa finalidade: proporcionar a criação de uma string mutável sem degradação do
desempenho. É, literalmente, um construtor de strings.
Pág. 39 de 105
Para usar StringBuilder, basta instanciá-la em um objeto e usar o método append para que
um novo conteúdo seja concatenado à string, com mínimo prejuízo de memória e desempenho. O
exemplo do quadro usando StringBuilder ficaria como apresentado no quadro abaixo:
Posteriormente, para obter do objeto StringBuilder uma string tradicional, basta usar o método
toString().
Ignorado por muitos, o operador ternário ?: é uma forma conveniente de se obter um resultado
com base no teste verdadeiro ou falso de uma condição, tudo em uma única linha.Pode ser usado
para substituir estruturas if...else, tornando o código mais conciso. Sua sintaxe é a seguinte:
Caso a condição seja avaliada como verdadeira, o resultado receberá valorSeVerdadeiro. Caso
seja avaliada como falsa, receberá valorSeFalso. Exemplo prático em Java:
Para praticar conversão de string para valores numéricos, uso de operadores aritméticos e
concatenação de strings, vamos implementar um projeto de uma calculadora simples que solicitará
inicialmente dois números ao usuário, por meio de JOptionPane.showInputDialog(), e exibirá, usando
apenas um JOptionPane.showMessageDialog, o resultado das quatro operações matemáticas
básicas usando ambos.Ao final, o projeto deverá funcionar de modo semelhante à sequência de
execução definida na figura.
Pág. 40 de 105
FIGURA 29 - Sequência de execução para a calculadora, recebendo os números 16 e 2.
• Obter o primeiro número. Caso o usuário digite caracteres inválidos, será exibido um aviso e
atribuído 0 ao valor.
• Obter o segundo número, fazendo a mesma validação realizada para o primeiro.
• Calcular soma, subtração, divisão e multiplicação desses números.
• Montar uma string que exiba os resultados das quatro operações.
• Exibir a string ao usuário em uma janela.
Conseguiremos realizar facilmente esses passos usando os conceitos aprendidos até agora.
Um forma de implementar esse exercício é mostrada no quadro 8.
Pág. 41 de 105
QUADRO 8 – Código-fonte do arquivo Calc.java
1 package calculadora;
2
3 import javax.swing.JOptionPane;
4
5 public class Calc {
6
7 public static void main (String[] args) {
8
9 double valor1 = 0;
10 double valor2 = 0;
11 double soma, sub, mult, div;
12
13 String valorStr;
14
15 try {
16 valorStr = JOptionPane.showInputDialog{null, “Informe o primeiro
número:”);
17 valor1 = Double.parseDouble(valorStr);
18 } catch (NumberFormatException ex) {
19 JOptionPane.showMessageDialog(null, “Número inválido.
Considerando 0 para número 1.”);
20 }
21
22 try{
23 valorStr = JOptionPane.showInputDialog{null, “Informe o segundo
número:”);
24 valor2 = Double.parseDouble(valorStr);
25 } catch (NumberFormatException ex) {
26 JOptionPane.showMessageDialog(null, “Número inválido.
Considerando 0 para número 2.”);
27 }
28
29 soma = valor1 + valor2;
30 sub = valor1 - valor2;
31 mult = valor1 * valor2;
32 div = valor1 / valor2;
33
34 StringBuilder resposta = new StringBuilder();
35 resposta.append(valor1 + “ + “ + valor2 + “ = “ + soma + “\n”);
36 resposta.append(valor1 + “ - “ + valor2 + " = " + sub + “\n”);
37 resposta.append(valor1 + “ * “ + valor2 + “ = “ + mult + “\n”);
38 resposta.append(valor1 + “ / “ + valor2 + “ = “ + div + “\n”);
39
40 JOptionPane.showMessageDialog(null, resposta);
41
42 }
43
44 }
Fonte: elaborado pelo autor
Pág. 42 de 105
Vamos entender o que está sendo feito nos principais pontos da listagem.
• Linhas 9 a 11: declaração de variáveis double para os valores e para os resultados das operações
matemáticas. Note que zeramos os valores de valor1 e valor2. Isso é necessário, pois o uso
do try...catch na conversão de string para double (que temos posteriormente) faz com que o
compilador Java indique um possível cálculo com valor não inicializado nas operações. Além
do mais, definimos anteriormente que valores fornecidos incorretamente ficarão zerados,então
já começamos com essa consideração.
• Linha 13: declaramos uma única variável string para poder apenas guardar o valor retornado
pelos métodos showInputDialog.
• Linhas 15 a 20: solicitamos o valor1 ao usuário. Caso seja informado um valor inválido, ocorrerá
uma exceção de formatação. Nesse caso, exibimos uma mensagem de alerta, indicando que
o valor para o número em questão ficará zerado.
• Linhas 22 a 27: fazemos o mesmo processo das linhas 15 a 20, só que agora para o segundo
número (variável valor2).
• Linhas 29 a 32: realizamos aqui as quatro operações matemáticas básicas usando os valores
fornecidos.
• Linhas 34 a 38: para montar a string que será exibida ao usuário, contendo as quatro operações,
realizaremos várias concatenações. Por isso, como vimos anteriormente, nada melhor que
utilizar um objeto StringBuilder, juntando valores e símbolos por meio do seu método append.
Veja que, ao final da cada operação matemática, concatenamos também a string“\n”. Esse
é um caractere de escape, oriundo da linguagem C, que resulta em uma quebra de linha na
impressão do texto.
• Linha 40: encerramos o programa exibindo a string criada no objeto StringBuilder.
Pág. 43 de 105
2. CLASSES E OBJETOS EM JAVA
A API do Java SE é riquíssima em número de classes prontas. As que vimos até agora são
um pequeno exemplo. Mas, mesmo contando com esse conjunto, a linguagem não traz classes
relativas ao domínio de um sistema, para produtos ou clientes em um sistema de vendas, por
exemplo. O que Java contém são classes que auxiliarão o desenvolvedor a criar as suas, relativas
à implementação do modelo conceitual de um sistema projetado por meio da engenharia de
requisitos e modelagem UML. Neste módulo, começaremos a implementar em Java classes
relativas ao sistema bancário, para que você tenha o entendimento essencial de como transportar
o modelo conceitual para a programação.
Você já sabe que, em orientação a objetos, os blocos fundamentais de um sistema são suas
classes. Elas servem como moldes para os objetos, que são criados instanciando-as.
O objeto é como uma cópia ou instância de uma classe, mas que possui um estado (também
chamado de conjunto de atributos, propriedade ou campo) que dá a ele “vida própria” e características
específicas. Além do estado, o objeto também possui operações (também chamadas de ações ou
métodos) que foram recebidas de sua classe e que permitem que realize suas funções.
SAIBA MAIS
Você já sabe que, em Java, devemos nomear as classes com a primeira letra maiúscula e as demais
minúsculas. Mas também precisa ficar sabendo que:
1. Nomes de classe devem ser definidos no singular (Cliente é o correto, e não Clientes)
2. Para classes com duas ou mais palavras no nome, capitalize sempre a primeira letra de cada
palavra. Exemplo: ContaCorrente.
Pág. 44 de 105
A classe Cliente terá, por enquanto, três campos (o nome pelo qual chamamos os atributos em Java)
e um método (que é como chamamos as operações). Veja o diagrama UML para Cliente na figura 31:
Se você olhou para a figura 31 e percebeu a falta de alguma coisa, tem toda a razão: não
colocamos os símbolos que especificam a visibilidade dos campos (público, privado ou protegido).
Vamos deixar a classe sem eles por enquanto – falaremos mais sobre a visibilidade em breve.
Aí vem a pergunta: como vamos criar essa classe em Java?Os campos serão variáveis dentro
dela. Já o método será uma função semelhante à main() que utilizamos até agora.
Com relação às variáveis, há um detalhe: as que criamos até o momento eram colocadas dentro
de main(). Isso faz delas locais ao método (ou seja, elas só existem e são visíveis dentro dele). Por
isso, não são consideradas campos das classes. As variáveis que representarão os campos são
colocadas fora de seus métodos. Geralmente elas são declaradas no início da classe, logo após a
chave de abertura.
Pág. 45 de 105
Uma classe pode conter quantos campos precisar. Cada objeto instanciado a partir dela possuirá
seus próprios valores armazenados em cada um dos campos. Por essa razão, eles também são
chamados de variáveis de instância.
O tipo de um campo pode ser um tipo primitivo (int, double, char, boolean), uma classe Java
(string, random...) ou até mesmo classes criadas por você dentro do seu programa.
No nosso exemplo do Cliente, os campos nome, cidade e estado podem ser declarados como
string.
SAIBA MAIS
Nomes de variáveis (tanto as locais em um método quanto as que são campos de uma classe) devem
começar com letras minúsculas, capitalizando as demais palavras.
Também devem ser evitados ao máximo nomes resumidos, que prejudiquem a legibilidade do código.
Exemplos:
// Correto! É um bom nome de variável!
doublesaldoChequeEspecial;
// Errado! Não use maiúscula no início do nome - confunde com as
classes!
DoubleSaldoChequeEspecial;
// Errado! Nomes muito resumidos prejudicam o entendimento do código.
doublesce;
Podemos ter um método em um objeto chamado calculadora (que pode ser, por sua vez, uma
instância da classe Calculadora), por exemplo, que retorna um resultado de um fatorial.Chamamos
a execução colocando um ponto após o nome do objeto e escrevendo seu nome, como no exemplo:
Pág. 46 de 105
Nesse exemplo, chamamos o método calcularFatorial existente no objeto calculadora. Passamos
a ele o número 6 como parâmetro. Dentro do corpo do método, será feito o cálculo do fatorial desse
valor, e o resultado será retornado para ser guardado na variável resultado, do tipo int.
No caso da classe Cliente, especificamos um método chamado listarDados, que vai trazer uma
ficha cadastral do cliente. Nesse caso, então, podemos assumir um retorno do tipo string para ele.
Uma classe pode conter vários métodos. Todo objeto instanciado a partir dela também
os possuirá e os poderá utilizar. Dentro de um método, podem ser usadas variáveis locais
(declaradas e válidas apenas dentro do método), valores passados ao método como parâmetro
(válidos também somente dentro do método) e campos da classe (lembrando que cada objeto
instanciado possuirá seus próprios valores para eles) nos quais o método está definido.
Os argumentos ou parâmetros de um método, assim como seu retorno e variáveis locais,
também podem ser tipos primitivos ou objetos.
Para criar nossa classe Cliente, vamos começar a implementação do nosso sistema bancário. Ele
conterá inicialmente duas classes: Principal e Cliente (mesmo tendo outra classe, vamos continuar
precisando de uma classe Principal com um método main para termos um ponto de entrada e uma
interface com o usuário).
SAIBA MAIS
Pacotes são usados em Java para organizar classes e demais identificadores, além de possibilitar
que duas ou mais classes tenham o mesmo nome (desde que pertençam a pacotes distintos).
Podemos nomeá-los usando subníveis, dividindo-os com pontos. Neste exemplo, nosso sistema
possui dois subníveis de pacotes: modelo e tela, ambos pertencentes a banco.
No Eclipse, você cria os pacotes dentro da pasta src do projeto, clicando no seguinte botão da barra
de ferramentas.
Siga os passos:
1. Crie um novo projeto Java no Eclipse chamado SistemaBancario (sem acento e espaços
no nome).
Pág. 47 de 105
2. Após criar o projeto, clique sobre a pasta src e crie um pacote chamado banco.tela.Em
seguida, adicione um segundo pacote, chamado banco.modelo.
3. No pacote banco.modelo, colocaremos a classe Cliente. O termo modelo é usado quando
nos referimos aos elementos de um programa relativos aos seus dados principais.
4. Já o pacote banco.tela vai conter a classe Principal, que por sua vez possuirá o método main.
Além de porta de entrada ao sistema, essa classe e esse método atuarão como a interface
do aplicativo com o usuário. Por essa razão, ela será colocada em um pacote próprio, que
representa melhor sua finalidade.
5. Crie a classe Principal (clique sobre o pacote banco.tela antes de criá-la, para que ela seja
colocada dentro dele) clicando no botão da barra de ferramentas do Eclipse. Na janela
que será aberta, especifique o nome em Name e não deixe de marcar a opção public static
void main durante a criação para que tenhamos uma função main dentro dela.
6. Em seguida, clique sobre o pacote banco.modelo e crie uma segunda classe. Dessa vez, dê
a ela o nome Cliente e não marque a opção public static void main.
7. Terminando essas etapas, a estrutura do seu projeto deverá ficar semelhante à exibida na
figura 32.
FIGURA 32 - Estrutura inicial do projeto SistemaBancario
Pág. 48 de 105
Agora, clique duas vezes sobre a classe Cliente.java e vamos escrever seu código, de acordo
com a listagem mostrada no quadro 10.
• Linha 1: está indicado que a classe que será definida a seguir pertence ao pacote banco.modelo.
• Linha 3: nessa linha inicia-se o código da classe. Veja que a chave aberta ao final dela é fechada
apenas na linha 15. Tudo que estiver contido dentro desse par de chaves pertence à classe.
Aí a iniciamos indicando que ela é pública (public). A palavra public determina que poderá
ser usada por qualquer outra. Depois de public, a class Cliente indica que estamos definindo
uma classe chamada Cliente.
• Linhas 4 a 7: como tínhamos colocado no diagrama da classe Cliente, declaramos aqui os três
atributos que ela possui. Veja que todos são do tipo string, adequado para o tipo de informação
que conterão. Todo objeto instanciado da classe Cliente possuirá seus próprios valores para
esses campos.
• Linhas 9 a 13: definimos um único método para essa classe. Sua função é retornar uma string
listando os dados do cliente. A palavra string, no início da linha 9 antes do nome do método, indica
que ele retornará um objeto desse tipo. Veja que ele se chama obterDados e, nesse caso, não
recebe parâmetros (ou seja, nenhum valor precisará ser passado a ele quando for executado).
A chave no final da linha 9 indica o início do método, que é encerrado pela outra na linha 13.
Pág. 49 de 105
• No caso de métodos que retornam valores (ou seja, aqueles que não possuem void na sua
declaração), devemos usar o comando return para devolvê-los a quem os invocou. Nesse exemplo,
montamos uma string concatenando os dados do cliente (obtidos das variáveis locais do objeto:
nome, cidade e estado) e retornamos para que possa então ser impressa ao usuário. Note que
o método listarDados() pode acessar os campos, pois está contido na mesma classe.
Agora vamos colocar nossa nova classe em uso. Abra a classe Principal.java e escreva dentro
do seu método main a seguinte linha:
Inicialmente, aparecerão sublinhados vermelhos no lugar em que escrevemos Cliente. Isso ocorre
porque nossa classe Principal não a reconhece. Como ela está em um pacote diferente, devemos
acrescentar um import para ela.
Você pode fazer isso de duas formas: usando a ajuda do Eclipse ou manualmente, adicionando
a linha seguinte ao código, abaixo do comando package banco.tela e antes do início da classe:
import banco.modelo.Cliente;
Perceba que, assim que você terminar de escrever o comando, o erro na linha anterior irá
desaparecer.
Agora que não temos mais erros, vamos entender o que fizemos.Você simplesmente acabou de
declarar e instanciar (ou seja, criar) um objeto de uma classe sua. A sintaxe básica para declarar
um objeto é a mesma da declaração de variáveis:
NomeDaClassenomeDoObjeto;
A diferença aqui é que declaramos e instanciamos o objeto em uma única linha. O instanciamento
é feito pelo operador new e pelo método construtor.
O método construtor é um comando especial da classe, que serve para inicializá-la e que sempre
tem o mesmo nome da classe. Poderíamos também ter escrito a linha:
Pág. 50 de 105
Cliente cliente;
cliente = new Cliente();
Geralmente, é usada a primeira forma, que deixa o código mais sucinto. É ela que usaremos
nos nossos exemplos.
Agora, faça um teste: na linha seguinte, escreva o nome do objeto (cliente) seguido de um ponto
(.) e aguarde a exibição da janela pop-up do autocompletar.Você deverá ver algo semelhante ao
mostrado na figura 33.
Provavelmente você esperava ver os membros do objeto cliente que ele possui,já que é uma
instância da classeCliente. Esses membros seriam os campos nome, cidade e estado e o método
listarDados. Mas o que você encontra? Um monte de nomes estranhos.Mas não há nada de errado.
Temos duas questões importantes aqui:
• Você não está visualizando os campos e os métodos da classe Cliente pois, como não definimos
a visibilidade deles, foi assumido um valor padrão. Conhecido no Java como packageprivate,
indica que um campo ou método sem especificador de visibilidade só poderá ser acessado por
classes pertencentes ao mesmo pacote. Infelizmente, não é o caso aqui: Cliente pertence ao
pacote banco.modelo e Principal, ao pacote banco.tela. Resumindo:acesso negado a campos
e método.
Pág. 51 de 105
• Toda classe criada em Java sem uma superclasse (que é o caso aqui, por enquanto) herda
automaticamente a chamada “classe raiz” da linguagem, denominada Object e pertencente
ao pacote java.lang. É dela que vêm esses métodos “estranhos” exibidos na figura.
Para poder usar os campos e o método existentes em cliente de dentro da classe Principal,
teremos que colocar um modificador de visibilidade diferente neles. Abra o código da classe Cliente
e acrescente a palavra public no início da declaração das variáveis e do método, como indicado na
listagem do quadro 11.
QUADRO 11 - Listagem da classe Cliente com modificadores de visibilidade nos seus membros
1 package banco.modelo;
2
3 public class Cliente {
4
5 public String nome;
6 public String cidade;
7 public String estado;
8
9 public String listarDados() {
10 return “NOME: “ + nome + “\n” +
11 “CIDADE: “ + cidade + “\n” +
12 “ESTADO: “ + estado;
13 }
14
15 }
Fonte: elaborado pelo autor
Agora sim volte ao Principal.java, coloque o cursor ao lado do ponto em cliente e pressione as
teclas CTRL+ESPAÇO para ativar o autocompletar. Você verá os campos e o método disponíveis
para uso.
Pág. 52 de 105
Vamos colocar valores nos campos e executar o método listarDados. Adicione ao seu método
main o código novo exibido na listagem do quadro 12.
Pág. 53 de 105
2.1.3. Métodos construtores
SAIBA MAIS
Garbage Collector
Toda vez que criamos um objeto com new, um espaço de memória é reservado para ele. Quando ele
não é mais usado, esse espaço deve ser liberado, por motivos óbvios de desempenho e economia de
recursos do computador.
Nos primórdios das linguagens orientadas a objetos, o programador deveria se preocupar com
esse fato: era obrigação dele “jogar fora” um objeto que não estava mais sendo usado, para liberar
memória. Com o tempo, percebeu-se que essa prática prejudicava a produtividade, além de poder
causar erros nos programas (por exemplo, quando um programador colocava uma instrução para
excluir um objeto quando ele ainda estava sendo usado).
Foram criadas técnicas para resolver essa questão, e Java, como boa linguagem moderna orientada a
objetos, implementa uma delas: a coleta de lixo.
Um elemento importante da máquina virtual do Java, o coletor de lixo (garbage Collector, literalmente,
“lixeiro”) procura por objetos não mais utilizados no programa para que possam ser “jogados no lixo”,
liberando a memória por eles usada. Assim, você só precisa se preocupar em criar o objeto (usando o
new). Deixe a preocupação de excluí-lo com o “lixeiro” do Java.
Mas atenção: isso não significa que você pode “abusar”. Evite ao máximo instanciar objetos sem
necessidade, para não prejudicar o desempenho do aplicativo e do sistema no qual ele está sendo
executado.
public Cliente() {
}
• O construtor é público (e é assim na maioria das vezes, mas você pode criá-lo com outro tipo
de visibilidade);
• Um construtor nunca possui retorno (nem mesmo void);
• Seu conteúdo, nesse caso (dentro de chaves), está vazio.
Isso faz que um objeto seja criado com seus campos totalmente vazios. Se quisermos, podemos
definir esse mesmo construtor dentro da classe Cliente colocando valores default nos campos.
Pág. 54 de 105
Suponha, por exemplo, que a maioria dos clientes do banco seja de São Paulo, SP. Podemos então
já iniciar o objeto com esses valores, como exemplificado no quadro.
A partir de agora, o construtor default vazio não será mais usado, e sim esse do quadro.
Podemos também escrever mais de um construtor,sempre com o mesmo nome da classe, mas
usando parâmetros diferentes. Isso se chama sobrecarga de métodos em Java.
Por exemplo, podemos manter esse construtor padrão sem parâmetros, mas termos também
um segundo no qual passamos os dados iniciais do cliente como parâmetros para que o objeto
seja criado já com eles, sem necessidade de definirmos um campo de cada vez. Para fazermos
isso, adicione, dentro da sua classe Cliente, o novo construtor exibido no quadro 14.
QUADRO 14 - Novo construtor com parâmetros
1 public Cliente (String nome, String cidade, String estado) {
2 this.nome = nome;
3 this.cidade = cidade;
4 this.estado = estado;
5 }
Fonte: elaborado pelo autor
Agora podemos usar qualquer um dos dois construtores. Se instanciarmos um objeto usando
o sem parâmetros, devemos fazer desta forma:
Cliente cliente = new Cliente();
Assim,teremos um objeto cliente com os valores padronizados para os campos (por exemplo,
com cidade igual a São Paulo). Podemos modificar esses valores depois usando a atribuição direta.
Mas podemos economizar tempo usando agora o segundo construtor da seguinte maneira:
Nesse exemplo, o objeto cliente já começará com os valores para nome, cidade e estado, sem
necessidade de atribuição manual para cada um deles.
Pág. 55 de 105
SAIBA MAIS
Repare que os parâmetros recebidos por esse construtor mostrado no quadro 14 (que vão trazer os
valores iniciais para o objeto) possuem o mesmo nome dos campos da classe.
Usamos o this para eliminar a ambiguidade. A variável especificada com this será considerada
como o campo da classe (this quer dizer este/esta – as variáveis existentes nesta classe). Assim, a
atribuição será feita no sentido correto.
Você pode até possuir métodos estáticos junto de não estáticos (listarDados, que criamos em
Cliente, é um destes) na mesma classe, mas os primeiros não podem acessar variáveis de instância
(ou seja, os campos) de um objeto. Para que um método estático possa usar um campo da classe,
este deve também ser configurado como estático.
Por exemplo, poderíamos criar na nossa classe Cliente um campo estático do tipo int chamado
quantidade, que começará com zero e será incrementado toda vez que um novo cliente for instanciado.
A existência desse campo abre também mais duas possibilidades interessantes:
• Podemos usá-lo para definir um código único para cada cliente instanciado;
• Podemos criar também em Cliente um método estático que retorna o valor desse campo quantidade
– assim, poderemos saber a qualquer momento quantos objetos Cliente foram criados.
Pág. 56 de 105
Adapte sua classe Cliente para que contenha o código apresentado no quadro 15:
Pág. 57 de 105
Vamos entender o que está sendo feito:
• Como agora teremos um campo para o código do cliente, ele é declarado na linha 5.
• Na linha 10, temos o campo estático do tipo int chamado quantidade. Essa variável vai guardar
na classe a quantidade de clientes já cadastrados. Não precisamos inicializá-la, pois, em Java,
variáveis int já começam contendo 0.
• Na linha 13, dentro do primeiro construtor (sem parâmetros), incrementamos a quantidade
em 1. Isso significa que, quando esse construtor for executado, terá sido realizada a criação
de um novo cliente. Na linha 14, aproveitamos e usamos o valor atual de quantidade como
código do cliente. Repetimos isso no outro construtor, nas linhas 21 e 22.
• Como agora temos uma informação adicional de um cliente (seu código), acrescentamo-la ao
retorno de listarDados(), na linha 29.
• Ao final, nas linhas 35 a 37, implementamos um método estático –qtdClientes()– que retorna
a quantidade de clientes guardada na variável.
Para poder utilizar os novos recursos da classe Cliente, adapte sua classe Principal de acordo
com a listagem do quadro 16.
Pág. 58 de 105
Execute seu projeto e veja o resultado.
2.2. Encapsulamento
O exercício que implementamos anteriormente não está incorreto, mas possui um detalhe
que pode ser melhorado para que se encaixe melhor ainda na “vida real”. Você pode ter percebido
que o campo saldo foi declarado como público na classe Conta. Esse fato implica que, a qualquer
momento, o usuário de um objeto da classe Conta pode fazer o seguinte:
conta.saldo = 1000000000000;
Ou seja, o dono da conta pode modificar o saldo da conta quando quiser, para qual valor desejar,
o que com certeza é péssimo para o banco, o dono do sistema. Mas é principalmente ruim porque
fere um princípio importantíssimo da orientação a objetos: o encapsulamento.
Para ocultar ou limitar o acesso aos elementos de uma classe (tanto campos, como o saldo no
exemplo bancário, quanto métodos), usamos os modificadores de visibilidade. Em Java, temos as
seguintes opções:
Pág. 59 de 105
• public: o acesso ao membro da classe é irrestrito. Qualquer outra classe pode ter acesso livre
a ele. Isso implica, no caso dos campos, poder obter e modificar seus valores;
• private: é o modificador mais restritivo, pois oculta totalmente o campo ou método do “mundo
exterior”. Campos e métodos private só podem ser usados dentro da própria classe em que
são definidos;
• protected: permite o acesso ao membro dentro da sua própria classe (assim como private) e
também nas suas subclasses (classes criadas a partir dela – falaremos sobre herança mais
adiante);
• sem modificador: quando não colocamos um modificador na declaração do campo ou método,
o Java assume-o como packageprivate. Isso significa que o membro só pode ser acessado
dentro da própria classe e por outras classes pertencentes ao mesmo pacote.
Deve-se evitar ao máximo definir campos de uma classe como public, pois assim se abre
mão totalmente do controle do que pode ser colocado dentro dela. Para seguir o princípio do
encapsulamento, o ideal é definir os campos sempre como private ou protected (neste último caso,
para quando se for criar uma subclasse que precisará usar um campo da sua superclasse).
Mas, se colocarmos private em um campo, não poderemos atribuir um valor a ele, nem mesmo
acessar seu conteúdo. Se você abrir a classe Cliente e definir os campos como private, como no
quadro 17, perceberá que o Eclipse indica agora vários erros no código da classe Principal.
QUADRO 17 - Trecho inicial da classe Cliente com os campos modificados com private
1 package banco.modelo;
2
3 public class Cliente {
4
5 private int codigo;
6 private String nome;
7 private String cidade;
8 private String estado;
9
10 private static int quantidade;
Fonte: elaborado pelo autor
Pág. 60 de 105
QUADRO 18 - Trecho do código da classe Principal em que surgem os erros
21 Cliente cliente = new Cliente();
22 cliente.nome = JOptionPane.showInputDialog(null, “Nome do Cliente: “);
23 cliente.cidade = JOptionPane.showInputDialog(null, “Cidade do Cliente: “);
24 cliente.cidade = JOptionPane.showInputDialog(null, “Estado do Cliente: “);
Fonte: elaborado pelo autor
Não se preocupe. Faça essa mudança para que depois possamos contornar esse problema
de maneira muito mais eficiente do que simplesmente definir o campo como public: usando os
métodos getters e setters.
Um método getter – que poderia ser traduzido como “pegador” – é um método público existente
dentro de uma classe que é usado para outra obter um valor interno da primeira, ou seja, ele retorna
um campo private.
É um redirecionador: ao invés de obtermos o valor do campo diretamente (se for público), usamos
o getter como intermediário. Como? Adicione apenas as linhas 28 a 30 da listagem exibida no quadro
19 ao seu arquivo Cliente.java. Você pode adicionar o método em qualquer ponto da classe, mas a
convenção mais usada é colocá-los após o(s) construtor(es).
Pág. 61 de 105
Agora, quando uma outra classe precisar obter o nome de um cliente, deverá executar o método
getNome() dentro do objeto. Veja na linha 29 que esse método retorna o conteúdo do campo nome.
Exemplo de uso:
SAIBA MAIS
É uma convenção de Java que métodos getter devem ter seu nome definido da seguinte forma:
• Começando com get em letras minúsculas.
• Seguindo com o nome do campo com sua primeira letra maiúscula.
Você pode perguntar: qual a utilidade então de se usar um getter, já que o valor do campo será
retornado de qualquer jeito?
Dessa maneira padrão, realmente não há mudança. Mas, dessa forma, o acesso ao campo fica
controlado e, se quisermos, podemos determinar dentro do getter como o conteúdo deverá ser
apresentado ao usuário. Por exemplo, podemos fazer uma formatação do valor antes de ele ser
retornado.
Suponha que quiséssemos retornar apenas o primeiro nome do cliente (apesar de estar armazenado
em nome seu nome completo). Podemos modificar o getter para o exemplo do quadro 20:
Pág. 62 de 105
O método substring, existente em todo objeto da classe String, retorna uma parte dela existente
entre o índice do primeiro parâmetro, 0 no exemplo, e o índice anterior ao segundo parâmetro. nome.
indexOf(‘ ‘) será a posição dentro da string em que ocorre o primeiro espaço (se ele contiver um
espaço; caso contrário, retornamos o valor completo – tudo isso testado com um operador ternário).
O valor que vai ser colocado no campo privado é passado como um parâmetro ao setter. Dentro
do seu corpo, atribuímos o valor do parâmetro ao campo da classe. Veja no quadro 21, nas linhas
32 a 34, o setter para o nome do cliente, colocado dentro da classe Cliente logo após seu getter.
QUADRO 21 - Trecho de código da classe Cliente com setter para o campo nome implementado
28 public String getNome() {
29 return (nome.contains(“ “) ? nome.substring(0, nome.indexOf(‘ ‘)) :
nome);
30 }
31
32 public void setNome(String nome) {
33 this.nome = nome;
34 }
Fonte: elaborado pelo autor
Perceba que, assim como fizemos no construtor que criamos para Cliente, usamos o mesmo
nome do campo local da classe para o parâmetro (nome). Por isso, para não causar ambiguidade e
definirmos que o campo local é que receberá o parâmetro (e não o contrário), usamos this na linha 33.
Pág. 63 de 105
SAIBA MAIS
Assim como nos getters, é uma convenção de Java que métodos setter devem ter seu nome definido
da seguinte forma:
• Começando com set em letras minúsculas.
• Seguindo com o nome do campo com sua primeira letra maiúscula.
Novamente, você pode achar que dessa maneira estamos apenas “trocando seis por meia
dúzia”. A forma default do setter, como implementada no quadro anterior, realmente não faz nenhum
controle do que é colocado em nome, mas permite que facilmente implementemos isso, sua grande
vantagem, como no exemplo do quadro 22:
No exemplo, antes de atribuir o parâmetro ao campo, o setter verifica se o primeiro foi passado
vazio. Caso tenha sido, atribui “não fornecido” ao nome; caso contrário, coloca nesse campo o valor
fornecido como argumento.
Agora que temos um setter para o campo nome, podemos começar a corrigir os problemas na
classe Principal. Troque a linha em que colocávamos diretamente o valor retornado pelo JOptionPane
no campo nome pela chamada ao setter, como na linha 23 da listagem do quadro a seguir:
Pág. 64 de 105
QUADRO 23 - Classe Principal com uso do setter para o nome do cliente
21 Cliente cliente = new Cliente();
22 //cliente.nome = JOptionPane.showInputDialog(null, “Nome do Cliente:
“);
23 cliente.setNome(JOptionPane.showInputDialog(null, “Nome do Cliente:
“));
24 cliente.cidade = JOptionPane.showInputDialog(null, “Cidade do Cliente:
“);
25 cliente.estado = JOptionPane.showInputDialog(null, “Estado do Cliente:
“);
Fonte: elaborado pelo autor
Agora, precisamos fazer algumas modificações no nosso sistema bancário, por três motivos:
Vamos impedir que o usuário da classe Conta possa manipular o saldo diretamente. A partir
de agora, ele deverá obrigatoriamente usar métodos para tanto (saque ou depósito). Futuramente,
quando você for apresentado ao conceito de interfaces em Java, poderá transformar esses métodos
saque e depósito em classes que implementam a interface Transação.
Pág. 65 de 105
Veja que agora temos o símbolo indicando a visibilidade desejada para os campos e métodos,
assim como seus tipos. Não foram colocados todos os métodos no diagrama (como getters, setters
e construtores) para nos focarmos naquilo que precisaremos incluir ou modificar, ou seja:
• Como criaremos subclasses para Conta e Cliente na próxima aula, mudaremos a visibilidade
de seus campos para protected.
• Para manipulação do saldo, deveremos implementar dois métodos públicos em Conta:
◊ sacar(), que receberá um valor double de saque como parâmetro e somente o realizará
(subtraindo o valor do parâmetro do saldo) se houver saldo suficiente. Note que esse método
deverá retornar um boolean: true, se o saque foi realizado (havia saldo disponível), ou false,
caso contrário (o saldo era insuficiente). Podemos usar esse retorno na interface para avisar
ao usuário sobre a realização ou não.
◊ deposito(), que receberá uma valor double de depósito como parâmetro. Nesse caso, não
há retorno no método – basta adicionar o valor do parâmetro ao saldo.
• Após movimentar sua conta, o usuário desejará ver como ficou seu saldo. Para isso, teremos
o método getSaldoFormatado, que retornará uma string com o saldo da conta em formato
monetário.
Pág. 66 de 105
1º passo: adaptando a classe Cliente
Abra a classe Cliente e altere seu código seguindo o exemplo da listagem do quadro 24.Nesse
caso, é bastante simples: basta mudar os modificadores de visibilidade dos campos. Repare que
manteremos o campo estático quantidade como private; não é necessário colocá-lo como protected,
e mais adiante você descobrirá o porquê.
Veja que colocamos o contador como private, pela mesma razão de termos definido o Cliente
dessa forma.
Pág. 67 de 105
O principal vem agora: a implementação dos métodos de obtenção do saldo formatado, de
saque e de depósito. Acrescente-os logo no final da classe Conta, após o método listarDados(), de
acordo com o quadro 26.
• Como definimos o saldo como protected, não poderemos acessá-lo diretamente a partir da
classe Principal. Seria interessante ao cliente visualizar seu saldo atual após uma operação
de saque ou depósito. Por isso, adicionamos o método getSaldoFormatado(), definido nas
linhas 26 a 28, cuja função é retornar uma string com o saldo da conta em formato monetário.
• O método depositar (linhas 30 a 32) é bastante simples: recebe um valor double como parâmetro
e adiciona-o ao saldo da conta.
• Para realizar um saque, será usado o método sacar (linhas 34 a 41) que também recebe um
valor como argumento. Porém, o saque somente será possível se o saldo for superior ou igual
ao valor passado. Nesse caso, subtraímos o valor do saque e retornamos true, sinalizando
que a operação foi realizada com sucesso. Se o saldo for inferior, caímos no else da linha 34
–nesse caso, não é feita mudança no saldo, e o método retorna false.
Pág. 68 de 105
3º passo: testando as implementações na classe Principal
Para testar a implementação, vamos adicionar à classe Principal, logo após a criação dos
objetos cliente e conta, um pequeno “menu de movimentação” da conta, com opções para realizar
um saque ou um depósito ou finalizar o programa.
Acrescente à classe Principal, logo após a exibição dos dados da conta instanciada, o código
exibido no quadro 27.
Pág. 69 de 105
Explicações do código do quadro 27:
• Linhas 34 e 35: declaramos duas variáveis auxiliares – uma int para a opção escolhida no
menu e uma string para receber o valor digitado pelo usuário no JOptionPane.
• Linha 36: iniciamos um laço que termina na linha 58 e que se repetirá enquanto a opção de
menu escolhida pelo usuário for 1 (depósito) ou 2 (saque).
• Linhas 37 e 38: montamos uma string com o menu de opções.
• Linha 39: abrimos um bloco try para tratar erros de conversão de valores. Caso o usuário
forneça um valor que não possa ser convertido para número (nas opções menu ou valores), o
fluxo de execução do programa será direcionado para o catch na linha 55, que exibe um aviso.
• Linha 40: usando um JOptionPane, solicitamos a opção do usuário. O retorno já é convertido
para int e armazenado na variável opcao.
• Linha 41: abrimos um switch...case que é encerrado apenas na linha 54. Ele fará o tratamento
adequado da opção do menu escolhida pelo usuário.
• Linhas 42 a 46: se a opção for igual a 1, o usuário escolheu fazer um depósito. Após obter
o valor com um JOptionPane e convertê-lo para double, passamos para o método depositar
existente no objeto conta, que faz a mudança no saldo. Avisamos o usuário de que o depósito
foi realizado com outro JOptionPane. O comando break logo em seguida impede que o fluxo
de execução passe ao case seguinte.
• Linhas 47 a 53: no caso da opção 2 (saque), inicialmente solicitamos o valor desejado ao usuário
e fazemos sua conversão para double. Como o método sacar retorna um boolean indicando
se o saque teve sucesso ou não, fazemos a chamada a ele diretamente na condição do if. Se
o retorno for verdadeiro, o saque foi realizado; caso contrário, falhou. Em ambos os casos,
avisamos o usuário sobre o ocorrido.
Assim, finalizamos juntos a tarefa de melhorarmos ainda mais nosso sistema bancário.
Pág. 70 de 105
3. HERANÇA E POLIMORFISMO
Conheceremos como Java implementa dois dos mais poderosos recursos da programação
orientada a objetos: herança e polimorfismo. Ao final, você terá evoluído seu sistema bancário
ainda mais dentro da modelagem realizada na disciplina de UML.
A herança possibilita que você crie uma classe utilizando outra como base. É uma das formas
mais frequentes de reutilização de código e uma maneira de tornar os programas mais organizados
e fáceis de ser mantidos e atualizados.
Para criar uma relação de herança, estabelecemos primeiro uma generalização de um elemento
de um sistema. Em seguida, criamos as versões especializadas desse elemento, que recebem então,
de forma direta e automática, as características do primeiro.
Você pode verificar um diagrama de classes UML com dois exemplos de herança e generalização
já adequados à implementação que estamos fazendo até este ponto na figura 36.
Pág. 71 de 105
No caso de Cliente, criamos duas classes especializadas: uma para cliente pessoa física
(denominada PessoaFisica) e outra para cliente pessoa jurídica (chamada PessoaJuridica). Deixamos
essa classe ainda mais genérica, contendo apenas os campos comuns aos dois tipos (codigo,
cidade e estado) – perceba que movemos o campo nome, específico de pessoas físicas, para a
classe correspondente.
Assim, quando instanciarmos um objeto da classe PessoaFisica, teremos, além dos campos e
métodos existentes em Cliente, campos adicionais para nome e CPF. Já quando criarmos um objeto
da classe PessoaJuridica, receberemos, além do que já existe em Cliente, um campo para o CNPJ
e outro para a razão social.
A classe Conta também é um exemplo que pode ser especializado com herança. Isso porque,
em um banco, o cliente pode abrir tanto uma conta corrente quanto uma conta poupança, sendo
que cada uma possui características próprias.
Observe na figura anterior que criamos uma classe ContaCorrente, que herda da classe Conta e
que a complementa com os campos limite e juros, assim como traz o método aplicarJuros(). Já a
classe ContaPoupanca também herda as características básicas da classe Conta, mas acrescenta
campos para a data de aniversario (tipo classe Date de Java – um objeto dessa classe armazena
uma data específica) e o rendimento, assim como um método para aplicar os rendimentos ao saldo
(aplicarRendimentos).Implementaremos as classes ContaPoupanca e ContaCorrente mais adiante,
quando tratarmos de polimorfismo em Java.
Existe uma terminologia para nos referirmos às classes participantes em um esquema de herança.
Chamamos a classe mais genérica, aquela que possui as características que serão herdadas pelas
demais, de superclasse. No exemplo da figura anterior, Cliente é a superclasse.
Há a possibilidade de, dentro da subclasse, utilizar recursos na superclasse, desde que sejam
declarados como protected ou public. Para tanto,utiliza-se a palavra-chave super.
Vamos agora implementar no sistema bancário a herança para os dois tipos básicos de cliente.
Pág. 72 de 105
3.1.3. Exercício prático guiado: herança de cliente no sistema bancário
Vamos começara implementação da nossa herança em Java generalizando mais a classe Cliente.
Abra seu código-fonte e exclua a declaração do campo nome, assim como seu getter e seu setter.
Também remova a utilização deste dentro dos dois construtores existentes na classe e seu uso
dentro do método listarDados. Sua classe Cliente deverá ficar como a listagem exibida no quadro 28.
Pág. 73 de 105
37 public void setEstado(String estado) {
38 this.estado = estado;
39 }
40
41 public String listarDados() {
42 return “CÓDIGO: “ + codigo + “\n” +
43 “CIDADE: “ + cidade + “\n” +
44 “ESTADO: “ + estado;
45 }
46
47 public static int qtdClientes() {
48 return quantidade;
49 }
50
51 }
Não se preocupe com erros que podem aparecer nas outras classes: vamos corrigi-los daqui a
pouco. Agora, vamos adicionar a classe PessoaFisica. Clique em cima do nome do pacote banco.
modelo à esquerda, no Project Explorer, e clique sobre o botão New Java Class do Eclipse. Se não
se lembra de como fazer isso, oriente-se pela figura 37.
Na janela que será mostrada, especifique o nome da classe como PessoaFisica em Name e
clique em Finish para que a classe seja criada.
Pág. 74 de 105
A classe recém-criada inicia-se sem especificação de herança (mas, mesmo assim, ela ainda
herda a classe básica do Java, java.lang.Object). Nesse caso, precisamos especificar que PessoaFisica
herda Cliente.
Em Java, a palavra-chave extends é usada para indicar a superclasse de uma classe, ou seja,
de quem ela herda suas características iniciais. Para fazer isso, inclua o código extends Cliente na
sua declaração, como na linha 3 do quadro 29.
Pág. 75 de 105
Agora, implemente o restante do código para PessoaFisica seguindo a listagem do quadro 30.
Pág. 76 de 105
No quadro, temos em PessoaFisica os campos adicionais nome e CPF, assim como seus
respectivos getters e setters. Até aí, nenhuma novidade. Mas veja os dois métodos construtores:
um sem parâmetro, que cria o objeto com valores default, e outro em que o usuário pode passar os
dados do cliente para que seja criado já com todas as informações necessárias.
Percebeu a novidade? O comando super do Java!Como seu próprio nome dá a entender, ele é
usado para nos referirmos aos elementos existentes na nossa superclasse.
O comando super(), na linha 9 dentro do construtor PessoaFisica(), por exemplo, executa antes
de tudo o construtor sem parâmetros existente na superclasse Cliente. Isso ocorre para inicializar
também cidade e estado, assim como incrementar a quantidade de clientes criados e atribuir um
código para eles.
Já na linha 15, dentro do construtor PessoaFisica (string cidade, string estado, string nome,
string cpf), chamamos o segundo construtor de Cliente, aquele que recebe uma cidade e um estado
como parâmetros. Fazemos isso pois também precisamos criar o cliente PessoaFisica com uma
cidade e um estado,de acordo com aquilo que o usuário passou como argumentos no construtor
dessa classe.
Veja que, nas linhas 36 a 38, implementamos uma nova versão de listarDados(), específica
para clientes pessoa física. Ela vai trazer os dados específicos de PessoaFisica (nome e cpf) junto
daqueles que já existiam em Cliente, obtidos pela chamada a esse método usando super.listarDados.
Pág. 77 de 105
Para completar, vamos agora criar e escrever o código para PessoaJuridica. Siga a listagem
do quadro 31.
Para testar o uso das duas classes, vamos modificar o método main, dentro da classe Principal,
para que o usuário possa escolher, assim que o sistema for iniciado, se irá cadastrar um cliente
pessoa física ou pessoa jurídica.
Altere seu método main, na classe Principal, para que ele fique como na listagem do quadro 32.
Pág. 78 de 105
QUADRO 32 - Código da classe Principal com uso das classes PessoaFisica e PessoaJuridica
1 package banco.tela;
2
3 import javax.swing.JOptionPane;
4
5 import banco.modelo.Cliente;
6 import banco.modelo.Conta;
7 import banco.modelo.PessoaFisica;
8 import banco.modelo.PessoaJuridica;
9
10 public class Principal {
11
12 public static void main(String[] args) {
13
14 Cliente cliente = new Cliente();
15
16 String tipoCliente = JOptionPane.showInputDialog(null, “Escolha o
17 tipo de cliente:\n” + “F - Pessoa Física\nJ - Pessoa Jurídica”);
18
19 if (tipoCliente.equals(“F”)) {
20 cliente = new PessoaFisica();
21 ((PessoaFisica)cliente).setNome(JOptionPane.showInputDialog(null,
“Nome do Cliente: “));
22 ((PessoaFisica)cliente).setCpf(JOptionPane.showInputDialog(null,
“CPF do Cliente: “));
23 } else if (tipoCliente.equals(“J”)) {
24 cliente = new PessoaJuridica();
25 ((PessoaJuridica)cliente).setRazaoSocial(JOptionPane.
showInputDialog(null, “Razão Social: “));
26 ((PessoaJuridica)cliente).setCnpj(JOptionPane.showInputDialog(null,
“CNPJ do Cliente: “));
27 } else {
28 JOptionPane.showInputDialog(null, “OPÇÃO INVÁLIDA! Encerrando o
programa...”);
29 return;
30 }
31
32 cliente.setCidade(JOptionPane.showInputDialog(null, “Cidade do
Cliente: “));
33 cliente.setEstado(JOptionPane.showInputDialog(null, “Estado do
Cliente: “));
34
35 JOptionPane.showInputDialog(null, “DADOS DO CLIENTE\n\n” +
36 cliente.listarDados());
37
Pág. 79 de 105
38 Conta conta = nmew Conta(cliente);
39
40 JOptionPane.showInputDialog(null, “DADOS DA CONTA\n\n” +
41 conta.listarDados());
42
43 int opcao = 0;
44 String ret;
45 do {
46 String mensagem = “SALDO EM CONTA: “ + conta.getSaldoFormatado() + “\n\n”
47 + “OPÇÕES: \n1 - Depositar valor\n2 - Sacar valor\n3 - Finalizar”;
48 try {
49 opcao = Integer.parseInt(JOptionPane.showInputDialog(null, “Valor
do depósito:”);
50 switch (opcao) {
51 case 1:
52 ret = JOptionPane.showInputDialog(null, “Valor do depósito:”);
53 conta.depositar(Double.parseDouble(ret));
54 JOptionPane.showInputDialog(null, “Depósito realizado!”);
55 break;
56 case 2:
57 ret = JOptionPane.showInputDialog(null, “Valor do saque:”);
58 if (conta.sacar(Double.parseDouble(ret))) {
59 JOptionPane.showInputDialog(null, “Saque realizado!”);
60 } else {
61 JOptionPane.showInputDialog(null, “FALHA NO SAQUE!”);
62 }
63 }
64 } catch (NumberFormatException ex) {
65 JOptionPane.showInputDialog(null, “VALOR INVÁLIDO!”);
66 }
67 } while ((opcao == 1) || (opcao == 2));
68 }
69 }
Fonte: elaborado pelo autor
• Linha 14: começamos instanciando um objeto da classe Cliente. Criamos um objeto genérico,
pois ainda não sabemos se o cliente será pessoa física ou pessoa jurídica. De qualquer maneira,
será um cliente, por isso esse objeto será útil em qualquer um dos casos.
• Linha 16: exibimos um JOptionPane para que o usuário escolha o tipo de cliente que está
cadastrando. Se informar a letra “F”, é um cliente pessoa física; caso digite “J”, será pessoa
jurídica. O valor digitado fica guardado na variável tipo Cliente, uma string.
Pág. 80 de 105
• Linhas19 a 22: se o tipo de cliente for pessoa física, iniciamos aqui um bloco que solicitará ao
usuário os dados específicos. Assim, invocamos o construtor dessa classe específica para
inicializar nosso objeto cliente (linha 20). Porém, o compilador Java conhece a variável cliente
como um objeto da classe Cliente – foi assim que a declaramos na linha 14. Apesar de o que
estamos fazendo aqui ser totalmente válido – afinal, um objeto da classe PessoaFisica é também
um objeto da classe Cliente (em virtude da herança) –, precisamos “avisar” o compilador Java
que nas linhas 21 e 22 utilizaremos cliente como um objeto da classe PessoaFisica. Assim,
usamos nessas linhas um outro recurso poderoso (e prático) de Java, o casting, que permite
que um objeto de um tipo (classe) seja interpretado como de outro tipo (classe). Isso só será
possível se houver uma relação de herança ligando esse objeto aos dois tipos, como é o caso
aqui. Você não pode, por exemplo, tentar usar casting em objetos que não possuem relação
“hereditária”um com o outro (por exemplo, um da classe Cliente com um de Conta). Nesse
caso, como sabemos que o cliente também é uma pessoa física, o comando –(PessoaFisica)
cliente – diz ao compilador que cliente também possui os métodos de um objeto PessoaFisica.
Por essa razão, podemos usar setNome e setCpf nele.
• Linha 23 a 26: aqui verificamos se é um cliente do tipo pessoa jurídica. Caso seja, inicializamos
cliente de modo mais específico como um objeto PessoaJuridica. Em seguida, usamos
novamente o casting para poder chamar métodos específicos de PessoaJuridica em cliente
(setRazaoSocial e setCnpj).
• Linhas 27 a 30: caso o usuário tenha digitado um valor inválido, que não indique nem
cliente pessoa física, nem pessoa jurídica, exibimos um aviso e encerramos o método main
(consequentemente encerrando o programa) com return.
• Linhas 32 e 33: já definimos em cliente, nas linhas anteriores, os valores específicos do seu tipo
(por exemplo, nome para pessoa física e razão social para pessoa jurídica). Faltam agora os
dados genéricos para qualquer tipo: cidade e estado. Definimos esses valores usando agora,
diretamente, o objeto cliente, sem casting e interpretado genericamente como do tipo Cliente.
• Linha 35: mostramos a “ficha cadastral” de cliente, usando o método listarDados(). Note que,
durante a execução, será exibida a versão de listarDados() específica para o tipo de cliente,
inicializado como pessoa física (linha 20) ou pessoa jurídica (linha 24). Aqui, estamos usando
o recurso do polimorfismo, que veremos em mais detalhes a seguir.
Antes de executar, você perceberá que surgiu também um erro na classe Conta. Trata-se do
uso do getter getNome() em listarDados. Como agora só teremos nome em cliente pessoa física
(e não mais no cliente genérico, como está declarado em Conta), precisaremos fazer um pequeno
ajuste nessa classe. Modifique o método listarDados em Conta seguindo a listagem no quadro 33.
Pág. 81 de 105
QUADRO 33 - Nova versão do método listarDados na classe Conta
20 public String listarDados() {
21 String nome;
22 if (cliente instanceof PessoaFisica) {
23 nome = ((PessoaFisica)cliente).getNome();
24 } else {
25 nome = ((PessoaJuridica)cliente).getRazaoSocial();
26 }
27 return “NÚMERO: “ + numero + “\n” +
28 “CORRENTISTA: “ + nome + “\n” +
29 “SALDO: “ + DecimalFormat.getCurrencyInstance().format(saldo);
30 }
Fonte: elaborado pelo autor.
• Na linha 22, usamos um comando especial de Java chamado instanceof. Ele serve para
verificarmos se um determinado objeto é uma instância de uma determinada classe. Por
exemplo, cliente instanceofPessoaFisica retorna true se o objeto cliente for dessa classe ou
false se ele for uma instância de PessoaJuridica (a outra possibilidade).
• Se ele for pessoa física, na linha 23, usamos novamente o casting para poder interpretar o
cliente genérico como PessoaFisica e usar seu método getNome. Caso seja pessoa jurídica,
usamos também casting na linha 25 para obter sua razão social.
• O valor obtido é usado, então, no retorno desse método para impressão dos dados da conta.
Acabamos usando aqui novamente o próximo assunto de que trataremos: polimorfismo.Se você
ainda não entendeu completamente como ele funciona, não se preocupe. Vamos posteriormente
implementá-lo em mais um local importante.
3.2. Polimorfismo
Pág. 82 de 105
Nós já usamos o polimorfismo no exercício anterior e vamos aplicá-lo novamente. Veja a nova
versão do diagrama de classes do sistema bancário na figura 38:
Na figura, temos dois casos evidentes de polimorfismo: o método listarDados()e o método sacar().
O primeiro caso de polimorfismo já está implementado no código Java do nosso sistema: trata-
se do método listarDados(), existente em Cliente, PessoaJuridica e PessoaFisica. É um mesmo
método que possui três formas diferentes de executar – semelhantes, mas com conteúdo específico
à classe no qual é definido.
Se você abrir o código da classe Cliente, verá que ela contém a versão básica de listarDados(),
que traz apenas uma string com o código, a cidade e o estado do cliente (veja no quadro 34).
Como a classe PessoaFisica herda a classe Cliente, podemos concluir que um cliente PessoaFisica
já receberá o método listarDados proveniente dela. Mas aí vem a pergunta: esse listarDados atende
às necessidades de PessoaFisica? Não, pois não mostra duas outras informações importantes
Pág. 83 de 105
sobre esse tipo: nome e CPF. Agora, veja a nova implementação de listarDados() existente em
PessoaFisica, exibida no quadro 35.
Mas isso não significa que perdemos o listarDados original. Veja no quadro 35 que, dentro
de listarDados(), fazemos uma chamada ao existente em Cliente, nossa superclasse, usando o
comando super. Assim, podemos fazer que essa nova versão funcione como um complemento da
versão anterior.
A sobrecarga de métodos é um poderoso recurso existente na linguagem Java. Com ela, podemos
definir versões diferentes de um mesmo método (ou seja, com um mesmo nome) em uma mesma
classe. Podemos diferenciá-los por seus parâmetros.
Vamos supor que precisássemos ter em nossa classe Conta um método para depositar em
dinheiro e outro para depositar em cheque. A ideia inicial de quem não conhece a possibilidade da
sobrecarga de métodos é implementar dois métodos com nomes distintos:
depositarEmDinheiro(double valor);
depositarEmCheque(double valor, int numeroDoCheque);
Pág. 84 de 105
depositar(double valor);
depositar(double valor, int numeroDoCheque);
Quando o programador quiser invocar um depósito em dinheiro, basta passar ao método depositar
um único parâmetro, o valor do depósito:
depositar(5000);
Quando for feito em cheque, passamos dois parâmetros: o valor e o número do cheque.
depositar(2000, 73612);
O compilador Java saberá que, no primeiro caso, estamos chamando a versão de depósito para
dinheiro, já que só um valor está sendo passado, e que,no segundo,queremos a versão de depósito
para cheques, uma vez que dois parâmetros estão sendo informados, um jeito muito mais fácil e
sucinto.
Nós também já fizemos sobrecarga de métodos. Quando? Nos construtores das classes. Veja,
no quadro 36, os dois construtores para Cliente que criamos.
Pág. 85 de 105
Cliente cli1 = new Cliente(); // cria um objeto cliente usando o
primeiro construtor
Cliente cli2 = new Cliente(“Campinas”, “São Paulo”); // cria um outro
objeto usando a segunda versão
Não se esqueça de adaptar a classe Principal para utilizar as novas subclasses de Conta. Dê ao
usuário a possibilidade de escolher a criação de uma conta corrente ou de uma conta poupança.
Dica: para facilitar, crie o campo aniversario de ContaPoupanca como um int (ao invés de Date, como
indicado na figura 38) e armazene nele somente o dia do aniversário da conta poupança. Para obter o
dia atual em Java, use a classe Calendar com a seguinte linha de código:
int hoje = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
Tente fazer essa prática sozinho e depois volte para conferir o resultado, mostrado a seguir no
passo a passo da solução.
Pág. 86 de 105
Não se esqueça de indicar que ele herda a classe Conta, por meio do uso da palavra extends na
sua declaração (linha 5).
Pág. 87 de 105
39 String nome;
40 if (cliente instanceof PessoaFisica) {
41 nome = ((PessoaFisica)cliente).getNome();
42 } else {
43 nome = ((PessoaJuridica)cliente).getRazaoSocial();
44 }
45 return “NÚMERO: “ + numero + “\n” +
46 “CORRENTISTA: “ + nome + “\n” +
47 “SALDO: “ + DecimalFormat.getCurrencyInstance().format(saldo
+ limite);
48 }
49
50 public void aplicarJuros() {
51 if (saldo < 0)
52 saldo = saldo - (saldo * juros / 100);
53 }
54
55 }
Fonte: elaborado pelo autor
• Linhas 7 e 8: declaramos aqui os dois campos privados específicos dessa classe, o limite e a
taxa de juros, ambos do tipo double.
• Linhas 10 a 14: o primeiro construtor para ContaCorrente recebe um objeto Cliente apenas
como parâmetro, invoca o construtor equivalente na superclasse e atribui valores default para
o limite e a taxa de juros.
• Linhas 16 a 20: o segundo construtor permite a especificação de valores para o limite e a taxa
de juros da nova conta corrente.
• Linhas 22 a 25: nessas linhas, está declarada uma reimplementação do método
getSaldoFormatado(), que já existia na superclasse Conta. Na linha 22, inserimos uma annotation
(anotação) Java, que funciona como uma espécie de “comentário inteligente” - nesse caso,
a annotation @Override sinaliza ao compilador que esse método está sobrescrevendo outro
existente na superclasse. Apesar de não ser obrigatório, o uso dela é conhecido como uma boa
prática de programação Java. A nova versão de getSaldoFormatado() foi escrita para trazer o
valor do limite somado ao saldo, obtendo assim o real saldo disponível (linha 24).
• Linhas 27 a 35: aqui está contida a reimplementação do método sacar(). O método sacar() de
ContaCorrente deve considerar também o limite disponível no cheque especial, o que fazemos
na linha 29.
Pág. 88 de 105
• Linhas 37 a 48: a reimplementação de listarDados() contém o acréscimo do limite na exibição
do saldo disponível.
• Linhas 50 a 53: caso você tenha implementado o método aplicarJuros(), essa seria uma das
maneiras de escrevê-lo – subtraindo o valor dos juros do saldo apenas se este estiver negativo
(sem considerar o limite do cheque especial, nesse caso).
Pág. 89 de 105
30 }
31 }
32
33 public void aplicarRendimentos() {
34 if (aniversario == Calendar.getInstance().get(Calendar.DAY_OF_
MONTH)) {
35 saldo = saldo + (saldo * rendimento / 100);
36 }
37 }
38
39 }
Fonte: elaborado pelo autor
• Linhas 7 e 8: declaramos os dois campos específicos de uma conta poupança – seu dia de
aniversário e sua taxa de rendimento.
• Linhas 10 a 20: nelas, estão contidos os dois construtores para ContaPoupanca, um com valores
default para os campos e o outro permitindo que eles possam ser passados como parâmetro.
• Linhas 22 a 31: a implementação do método sacar(), em ContaPoupanca, deverá verificar se
o saque estará sendo feito após o dia do aniversário, garantindo que os rendimentos tenham
sido aplicados. Na realidade, a implementação prática deveria considerar também o mês para
ficar mais condizente com a realidade, mas simplificamos nesse caso para podermos nos
concentrar no uso do polimorfismo. Você pode ajustar o código, caso julgue adequado, mas
veja a nota importante abaixo.
• Linhas 33 a 37: essa é uma das formas como você pode implementar o método aplicarRendimentos(),
creditando a aplicação da taxa de rendimentos sobre o saldo da conta.
• Importante: além da questão da consideração do mês na data de aniversário, em uma situação
real, precisaríamos também possuir um setter para o campo rendimento (setRendimento), uma
vez que essa taxa varia de mês a mês.
Pág. 90 de 105
QUADRO 39 - Inclusão da escolha do tipo de conta na interface do sistema
1 cliente.setCidade(JOptionPane.showInputDialog(null, “Cidade do Cliente:
“));
2 cliente.setEstado(JOptionPane.showInputDialog(null, “Estado do Cliente:
“));
3
4 JOptionPane.showInputDialog(null, “DADOS DO CLIENTE\n\n” +
5 cliente.listarDados());
6
7 // INÍCIO DO NOVO TRECHO
8
9 Conta conta;
10
11 String tipoConta = JOptionPane.showInputDialog(null, “Tipo de conta a ser
criada:\n” +
12 “C - Conta Corrente\nP - Conta Poupança”);
13
14 if (tipoConta.equals(“P”)) {
15 conta = new ContaPoupanca(cliente);
16 } else {
17 conta = new ContaCorrente(cliente);
18 }
19
20 // FIM DO NOVO TRECHO
21
22 JOptionPane.showInputDialog(null, “DADOS DA CONTA\n\n” +
23 conta.listarDados());
Fonte: elaborado pelo autor
O mais interessante é que não precisamos modificar mais nada. O uso do polimorfismo
faz o resto.
Se for instanciada uma conta corrente, a exibição do saldo e o saque considerarão o limite
disponível, o que não ocorrerá no caso de uma conta poupança. Faça o teste e veja na prática.
Você verá que, no caso de ContaPoupanca, o saque não será permitido, pois usamos o construtor
que define o dia atual como aniversário. A condição implementada em sacar() impede que ele seja
realizado, pois verificará que o dia atual não é superior ao aniversário. Para que o saque em uma
ContaPoupanca funcione, modifique a linha relativa à criação do objeto dessa classe para usar o
construtor com mais parâmetros e passe um dia de aniversário inferior ao atual.
Pág. 91 de 105
4. ARRAYS DE OBJETOS E COLEÇÕES
Existe um momento em que um conjunto limitado de variáveis não é suficiente nem adequado
para armazenar um grupo de informações. Nos casos em que precisamos ter em um sistema
uma série de dados de um determinado tipo, precisamos recorrer a estruturas que possibilitem o
armazenamento de muitos valores ao mesmo tempo. Você já conhece os vetores em Java usados
para armazenar um conjunto de valores de tipos primitivos, como int ou double. Mas e no caso
de objetos? O que fazemos quando precisamos guardar, por exemplo, um conjunto de objetos da
classe Conta? Veremos agora como resolver essa questão.
Um vetor em Java de valores de um tipo primitivo, como int, pode ser declarado, inicializado e
utilizado da forma indicada no quadro 40.
Pág. 92 de 105
O que você ainda não sabe é que podemos ter em Java vetores de objetos, assim como de tipos
primitivos. Por exemplo, poderíamos declarar no nosso sistema bancário um vetor para Clientes e
armazenar objetos dessa classe em suas posições, como é mostrado no quadro 41.
O vetor clientes possui espaço para cinco objetos da classe Cliente. Perceba que, para cada objeto
referenciado por seu respectivo índice, podemos usar seus respectivos métodos individualmente.
Essa é uma abordagem interessante quando conhecemos previamente a quantidade de objetos
que serão utilizados. Mas e quando não sabemos?
Uma solução seria declarar um “megavetor”, com espaços além da capacidade máxima possível.
Mas assim ainda teríamos problemas, como o uso desnecessário de espaço de memória para os
elementos que não forem utilizados e ainda o risco de chegarmos ao limite declarado– mesmo que
isso seja improvável, seria um grande problema se acontecesse.
O ideal, nesses casos, é usar as classes de coleções da linguagem Java, que possibilitam
que criemos objetos containers de outros objetos – ou seja, vetores também, mas com tamanho
dinâmico.Objetos de coleção podem conter N objetos, sem precisar declarar a sua quantidade inicial
de elementos e sem desperdício de espaço.
Existem várias classes de coleções de objetos em Java, mas vamos aprender apenas uma aqui,
a mais usada de todas: ArrayList. A seguir veremos como usá-la para implementar uma outra parte
do sistema bancário.
Pág. 93 de 105
4.1.2. Uso de ArrayList e métodos para manipulação
Vamos praticar o uso das coleções de objetos em Java com ArrayList ao mesmo tempo em que
aprendemos como implementar mais uma parte do sistema bancário. Veja a nova versão do nosso
diagrama de classes na figura 39:
A primeira diferença que você deve ter notado é a inclusão da classe Agencia, para representar
uma agência dentro da rede bancária. Agora veja a linha que liga Agencia a Conta e tente se lembrar
do seu significado.
O losango preenchido na ponta de Agencia indica que ela possui uma relação de composição
com Conta, ou seja, uma agência é composta por várias contas (o asterisco na ponta conectada à
Conta indica essa multiplicidade). Relembrando, a composição indica que um todo (nesse caso, a
Agencia) é composta por várias partes (as Contas).A agência não pode existir sem contas, por isso
temos nesse caso uma composição e não uma agregação.
Como, em Java, vamos saber quais as contas que compõem uma agência? Uma maneira simples
e eficiente é usar um ArrayList de objetos da classe Conta em Agencia.
Pág. 94 de 105
CURIOSIDADE
Importante!
Seguindo as regras exatas da composição, não poderíamos permitir que uma agência existisse sem
contas. Porém ,não vamos implementar aqui esse tipo de controle e validação, visando facilitar o
entendimento do código do sistema.
List<Classe>lista = newArrayList<>();
Classe é o nome da classe de objetos que serão colocados na lista. Você deve importar a classe
java.util.ArrayList e a interface java.util.List no seu código.List é uma interface para a implementação
de listas em Java; ArrayList é uma classe que implementa essa interface. Quando você for apresentado
às interfaces em Java, verá que elas são maneiras de se estabelecer o que uma classe deverá ter
em sua implementação.
lista.remove(objeto);
Conseguimos saber quantos objetos existem no ArrayList usando seu método size():
inttotalDeObjetos = lista.size();
Podemos usar uma versão do comando for que percorre automaticamente os objetos existentes
em um ArrayList, um de cada vez:
Esse laço se repetirá pela quantidade de objetos existentes em lista, percorrendo do primeiro
ao último. Em cada passagem, o objeto representará o elemento atual.
Pág. 95 de 105
4.1.3. Uso de coleções no sistema bancário: exercício prático guiado
Para entender melhor como funciona um ArrayList, vamos implementar a classe Agencia e
modificar a classe Principal para possibilitar a inclusão de múltiplas contas.
Crie um nova classe Java dentro do pacote banco.modelo, chamada Agencia, e escreva seu
código de acordo com a listagem do quadro 42.
Pág. 96 de 105
O código do quadro 42 pode ser assim explicado:
• Linhas 8 a 10: um objeto da classe Agencia possuirá número, nome e uma lista de objetos
da classe Conta, denominada contas.Seguindo o princípio do encapsulamento, todos esses
campos são privados.
• Linhas 12 a 16: a classe Agencia possui um único construtor, que recebe o número e o nome
da agência como parâmetros e inicializa a sua lista de contas vazia.
• Linhas 18 a 28: temos aqui um conjunto de getters para os campos. Repare que não definimos
setters; assim, os valores deles não poderão ser modificados após serem criados com o
construtor. Apenas no caso da lista de contas poderemos acrescentá-las ou removê-las, por
meio dos métodos que serão definidos.
• Linhas 30 a 36: definimos aqui um método para incluir um objeto à lista de contas e outro
para remover. Como são públicos, poderão ser utilizados para adicionarmos e excluirmos as
contas de uma agência.
Na tela Principal, vamos criar um objeto agencia e acrescentar um laço externo no qual o
usuário poderá optar entre incluir nova conta e cliente, listar as contas existentes ou sair do sistema.
Modifique a sua classe Principal, começando pelo trecho mostrado no quadro.
Pág. 97 de 105
QUADRO 43 – Classe Principal: linhas 1 a 28
1 package banco.tela;
2
3 import javax.swing.JOptionPane;
4
5 import banco.modelo.Agencia;
6 import banco.modelo.Cliente;
7 import banco.modelo.Conta;
8 import banco.modelo.ContaCorrente;
9 import banco.modelo.ContaPoupanca;
10 import banco.modelo.PessoaFisica;
11 import banco.modelo.PessoaJuridica;
12
13 public class Principal {
14
15 public static void main(String[] args) {
16
17 Agencia agencia = new Agencia(1, “São Paulo - Centro”);
18 String opcaoPrincipal = “”;
19
20 do {
21 opcaoPrincipal = JOptionPane.showInputDialog(null, “Cadastro
de Contas para a agência “
22 + agencia.getNumero() + “ - “ + agencia.getNome() + “\n”
23 + “\nOPÇÕES:\n”
24 + “1 - Incluir cliente e conta\n”
25 + “2 - Listar contas cadastradas\n”
26 + “3 - Sair do sistema”);
27
28 if (OpcaoPrincipal.equals(“1”)) {
Fonte: elaborado pelo autor
• Nesse início, declaramos e instanciamos agencia na linha 17. Também declaramos uma nova
variável para a escolha do usuário no menu principal (a string opcaoPrincipal, na linha 18).
• Começamos um laço na linha 20 que vai englobar todo o código até a linha 109 (mostrada
adiante, no quadro 44) e que se repetirá enquanto o usuário escolher as opções 1 ou 2 do
menu criado entre as linhas 21 e 26.
• Na linha 28, caso o usuário escolha a opção 1 do menu (criar cliente e conta), caímos em um
bloco que vai até a linha 95 (exibido adiante no quadro 44).
Pág. 98 de 105
O trecho exibido no quadro é o mesmo que tínhamos anteriormente. A diferença fundamental
é que agora ele está contido dentro do laço principal iniciado na linha 20.
Pág. 99 de 105
O programa prossegue como mostra a listagem dos quadros a seguir.
Se a opção do usuário no menu principal, mostrado no início do laço mais externo, for a segunda,
ele deseja visualizar uma listagem das contas cadastradas. São então executados os comandos
contidos entre as linhas 95 e 108.
Na linha 97, usamos o método size() do ArrayList contas para saber se existem contas incluídas
nele. Caso ainda não existam, avisamos o usuário do fato na linha 98.
Se contas possuir objetos, mostramos ao usuário os dados da agência e quantas contas ela
possui (linhas 100 a 102). Em seguida, usando a versão do laço for que conhecemos na seção
anterior desta aula, percorremos todas as contas existentes na lista, mostrando seus dados ao
usuário (linhas 104 a 106).
SAIBA MAIS
Com essa última adição, implementamos boa parte do projeto de sistema bancário, incluindo os
seguintes conceitos:
• Classes e objetos básicos, com seus atributos e ações.
• Encapsulamento, ocultando dados das classes que não devem ser acessados ou modificados e
controlando o uso deles, quando necessário, com getters e setters.
• Generalização e herança, na implementação de Conta, ContaCorrente e ContaPoupanca, assim
como Cliente, PessoaFisica e PessoaJuridica.
• Polimorfismo, na reescrita de métodos herdados, como listarDados() em Conta e ContaCorrente
• Sobrecarga de métodos, nos construtores de PessoaFisica, por exemplo
• Composição, usando ArrayList para fazer com que um objeto Agencia possua uma coleção de
objetos Conta.
Você pôde descobrir como fazer o download, instalar e criar projetos Java no Eclipse, bem como
localizar e corrigir erros, além de testar seus aplicativos.
Fizemos uma revisão rápida de estruturas de controle e decisão, levando em conta as peculiaridades
da linguagem Java e usando uma abordagem de entrada e saída de dados mais visual.
O ponto principal da linguagem Java, uso de classes e objetos, foi explorado implementando
classes do sistema bancário. Com essa abordagem, você pôde ficar conhecendo mais sobre as
classes já existentes na API básica da linguagem Java (como String, Random, Integer, Double e
StringBuilder), assim como pôde descobrir como criar suas próprias classes. É assim que seus
programas orientados a objetos serão compostos: uma mescla de classes preexistentes com
aquelas que você mesmo cria, com base na engenharia de requisitos e a consequente modelagem
do sistema usando UML.
Futuramente você conhecerá outros frameworks e tecnologias utilizados para criação dos mais
diversos tipos de aplicativos em Java. Em todos eles você perceberá que as classes essenciais
do Java SE e os conceitos fundamentais de engenharia de software, orientação a objetos e UML
serão utilizados intensamente.
Prof. Querino
Profª. Elisamara
Concatenado: Ligado a
BARNES, D. J.; KÖLLING, M. Programação orientada a objetos com Java. São Paulo: Pearson
Prentice-Hall, 2004.
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. Rio de Janeiro: Elsevier, 2012.
DEITEL, H.; DEITEL, P. Java: como programar. São Paulo: Prentice-Hall, 2010.
ECLIPSE FOUNDATION. Eclipse. [website]. 2014. Disponível em: <http://www.eclipse.org/>. Acesso em:
13 abr. 2014.
GOSLING, J.; MCGILTON, H. The Java language environment. 1997. Disponível em: <http://www.oracle.
com/technetwork/java/intro-141325.html>. Acesso em: 10 abr. 2014.
QUERINO FILHO, L. C. Desenvolvendo seu primeiro aplicativo Android. São Paulo: Novatec, 2013.