Download - Texto Básico de POO
AULA 1 - Introdução ao Paradigma de Programação Orientada a
Objetos
Atualmente, o Paradigma de Programação Orientado a Objetos – POO é o
mais utilizado no mercado. Saber sobre esse assunto é um requisito quase
obrigatório para os profissionais desenvolvedores de aplicações. As
empresas desenvolvedoras de software estão sempre atrás de bons
programadores especialistas nesse paradigma para fazerem parte de seus
quadros funcionais.
Ao final desta aula você será capaz de compreender os motivos que
propiciaram a grande adesão ao paradigma de orientação a
objetos. Você também verá como foi a evolução desse tipo de
linguagem e os conceitos relacionados a ela, como o de abstração e
de modelos. Além de um breve histórico da linguagem Java, você
também perceberá suas principais características: orientada a
objetos, independente de plataforma, ambiente de programação
multi-thread, case-sensitive e de alto nível. Serão apresentadas as
Edições (Java SE - Standard Edition, Java EE - Enterprise Edition e
Java ME - Micro Edition) e as Ferramentas de Desenvolvimento
(NetBeans e Eclipse). Por fim, os passos necessário à instalação de
um JDK (Java Development Kit).
Abertura
A expressão “Programação Orientada a Objetos” foi criada por Alan Klay
http://pt.wikipedia.org/wiki/Alan_Kay , considerado um dos criadores desse
conceito de programação. Ele também foi inventor da linguagem Smalltalk
http://pt.wikipedia.org/wiki/Smalltalk, uma linguagem totalmente orientada a
objetos, na qual não possui tipos primitivos, todos os tipos são objetos.
Hoje, disponível no mercado existem vários exemplos de linguagens
orientadas a objetos como Java
http://pt.wikipedia.org/wiki/Linguagem_de_programa
%C3%A7%C3%A3o_Java , C++ http://pt.wikipedia.org/wiki/C%2B%2B ,
Object Pascal http://pt.wikipedia.org/wiki/Object_Pascal , Ruby
http://pt.wikipedia.org/wiki/Ruby_(linguagem_de_programa
%C3%A7%C3%A3o) , Python http://pt.wikipedia.org/wiki/Python , entre
outras.
Texto base
INTRODUÇÃO
O aumento da complexidade dos Sistemas de Informação – SI – foi um dos
motivos que propiciou a grande adesão à orientação a objetos. Os SI
modernos estão cada vez mais importante para as organizações pois são
mais rápidos, mais robustos e podem responder a mais questionamentos,
ajudando nas decisões estratégicas e automatizando um grande número de
tarefas.
Por isso, esses Sistemas de Informações não podem ficar a mercê de um
programador apenas. Hoje, as equipes que cuidam dos SI estão maiores,
mais qualificadas e os sistemas são construídos em módulos, para que haja
uma melhor compreensão e para facilitar a sua manutenção. Esses
requisitos são essenciais, principalmente, quando ao se incorpora um novo
programador na equipe.
Manutenção
A atividade de manutenção está cada vez mais presente na vida útil dos SI.
Isso ocorre porque é natural que os sistemas cresçam, que o tempo passe,
que a legislação se modifique, que as necessidades aumentem, que os
requisitos apareçam e desapareçam com maior rapidez. A programação
orientada a objetos permite uma melhor execução da atividade de
manutenção. Na programação estruturada era difícil fazer manutenção
quando o SI alcançava um tamanho considerado grande. Isso porque, entre
outros motivos, a manipulação de dados ficava espalhada pelo código e era
mais difícil encontrar a raiz do problema. No paradigma de Programação
Orientado a Objetos (POO), a gama de informações, a documentação, a
programação padronizada, os recursos de infra-estrutura mais robustos, os
mecanismos de log mais modernos e confiáveis, tudo isso ajuda a se chegar
mais rápido ao ponto exato em que o problema está acontecendo.
1 Evolução
A Programação Orientada a Objetos (POO) é uma evolução do paradigma de
programação estruturada. Todo o conhecimento adquirido com a
programação estruturada não será esquecido, pelo contrário, o aprendizado
será aproveitado com a aquisição de novos conceitos. Agora, você verá que
os SI são abstrações do mundo real, utilizando classes, modelos, objetos,
herança, encapsulamento e polimorfismo. Muitos nomes novos!? Tenha
calma! Veremos tudo isso com detalhes nas aulas seguintes!
Como dito acima, a POO visa aproximar o mundo real do mundo
computacional. A forma de projetar o software é modificada e a
programação adquire uma nova estrutura, para que os seus objetos possam
interagir da mesma maneira como acontece no mundo real. Por isso,
abstrações são necessárias, para que o programador possa pensar o
software da mesma maneira como os objetos se inter-relacionam no mundo
físico em que vivemos.
Dependendo do domínio do problema a ser tratado em um SI, você verá que
poderá haver uma classe (veremos o conceito detalhado de classe na nossa
aula 3) com características e comportamentos totalmente diferentes de
uma outra classe, de mesmo nome, mas com propriedades e
comportamentos distintos, em um outro domínio do problema. Por exemplo:
uma classe de POO que poderia ser chamada de “Pessoa”. Uma “pessoa”,
no mundo real, pode realizar operações como andar, correr, sentar, falar
etc. Já “pessoa”, em um contexto de biblioteca, pode ter o papel de sócio da
biblioteca e ter operações de solicitar empréstimo de livro, devolver livro.
No mesmo contexto, mas com o papel de empregado da biblioteca, a
“pessoa” pode executar as operações de conceder empréstimo de livro,
autorizar reserva, entre várias outras. Esses papéis, operações,
comportamentos e características particulares de uma “pessoa” no mundo
real, também fariam parte da classe “Pessoa” em uma implementação de
sistema orientado a objetos.
Portanto, o jeito ideal para programar é observar como é feito um
determinado processo de trabalho. Deve-se propor melhorias e codificar
computacionalmente os processo percebidos no mundo real, usando a
metodologia de orientação a objetos. Assim, você poderá construir um
software capaz de atender ao problema proposto, da melhor maneira
possível, com todas as características de um bom software. Capaz de atingir
os melhores índices de qualidade e de gerar informações necessárias para
agregar valor ao negócio.
2 Abstração
Abstração é um conceito muito particular da Programação Orientada a
Objetos. No campo teórico é importante o programador abstrair, para
projetar o sistema de forma semelhante ao mundo real. O desenvolvedor
deve imaginar qual seria a melhor solução para atender àquele problema,
para isso, ele precisa abstrair.
Ao se construir um sistema, é muito difícil prever e tratar todas as
possibilidades existentes em uma determinada situação. Por isso, caro
aluno, saiba que seu nível de abstração vai determinar o que deve ser
levado em consideração e o que será desprezado quando determinado
assunto for tratado. De toda sorte, essa é uma atividade um tanto quanto
complexa; quanto mais experiência o programador tiver sobre o tema
proposto e também em projetar sistemas, mais fácil será, para ele,
encontrar a melhor solução.
3 Modelos
Modelos são representações utilizadas para transpor determinado problema
do mundo real para a POO e seu emprego é bastante comum. Antes de
começar a programar é importante planejar o que deve ser feito, esse
planejamento é feito por meio de modelos. Essa modelagem, normalmente
é conhecida como documentação do sistema.
Os desenvolvedores podem assumir vários papéis quando desenvolvem um
software. Dependendo do perfil do sistema, ou do próprio profissional, uma
pessoa pode executar mais de um papel. Entre esses papéis está o de
projetista de software, que é o responsável por receber a demanda e
pensar, antes de desenvolver, como o software vai ser tecnicamente
construído. Após essa reflexão, o projetista faz o modelo do software,
gráficos cujo conteúdo é a representação de como funcionará o sistema
com todas as informações necessárias para o programador entender a
solução e, posteriormente, codificar o software.
O objeto principal desse curso não será a construção desses modelos, e sim
o desenvolvimento efetivo do software, utilizando a metodologia de
orientação a objetos. No entanto, é necessário aprender sobre a
modelagem, utilizada no dia a dia do desenvolvimento de sistemas; por
isso, você acompanhará mais sobre esse assunto na disciplina de
Requisitos e Projetos de Software.
4 Linguagem Java
Usaremos a linguagem Java para exemplificação dos códigos a serem
apresentados neste material. É importante mencionar que poderia ser
utilizada qualquer outra linguagem orientada a objetos. Os conceitos de
programação vistos aqui não se restringem a uma linguagem específica, no
entanto, pela facilidade, e também pela abrangência da linguagem Java no
mercado de trabalho, achamos por bem utilizá-la como ferramenta do nosso
curso.
No decorrer das próximas aulas serão explicadas algumas convenções e
padronizações amplamente utilizadas no Java. Você verá que essa
padronização é fundamental para os programadores, pois facilita o
entendimento do código. A incorporação de um programador novo à equipe
de desenvolvimento é facilitada quando ele já chega no ambiente de
trabalho consciente dessas definições.
4.1 Breve histórico da linguagem Java
No início dos anos 90, um grupo de especialistas da Sun Microsystems
http://pt.wikipedia.org/wiki/Sun_Microsystems – Patrick Naughton, Mike
Sheridan, e James Gosling – iniciou um projeto chamado ‘Green Project’ cujo
objetivo era desenvolver um mecanismo que permitisse a integração de
diversos dispositivos como computadores e eletrodomésticos utilizados no
dia a dia das pessoas.
Depois de vários meses de trabalho desenvolveram um protótipo chamado
*7 (StarSeven), que consistia em uma espécie de controle remoto com
habilidade de controlar diversos dispositivos e aplicações, na época,
objetivando automação de equipamentos e casas inteligentes. Para o
correto funcionamento do aparelho foi necessária a criação de uma
linguagem de programação, inicialmente batizada de Oak
http://pt.wikipedia.org/wiki/Linguagem_de_programa
%C3%A7%C3%A3o_Oak (carvalho em inglês), uma árvore típica do
hemisfério norte, que podia ser observada da janela do escritório enquanto
eles trabalhavam no projeto.
O fato era que o projeto andava de mal a pior, em uma época em que os
visionários da Sun não eram compreendidos pelas empresas de TV a cabo,
primeiro público alvo do projeto, pois a idéia era controlar televisores e
vídeo por demanda, mediante o uso de equipamentos – algo muito comum
hoje em dia, mas ainda incompreendido na época.
Em meados dos anos 90, o avanço da internet permitiu uma reviravolta no
projeto. Uma grande rede interativa estava se formando e os projetistas da
Sun viram uma grande oportunidade de adaptar sua linguagem para ser
utilizada em redes heterogêneas, como a própria internet.
Devido a problemas de direitos autorais, a linguagem teve de ser
rebatizada. Escolheram o nome Java (sugerido por acaso, quando a equipe
visitava uma cafeteria - Java era o nome da ilha de origem de um café
importado) e foi o início do sucesso. Novas aplicações começaram a ser
utilizadas dentro dos browsers de navegação. O Java deu a dinâmica nas
páginas HTML, antes estáticas, à medida que mundo da internet também ia
se modificando rapidamente.
A adesão à linguagem de programação Java foi feita de maneira muito
veloz. Grandes indústrias de software, como a IBM
http://www.ibm.com/br/pt/, começaram a dar suporte à linguagem. Ela se
tornou bastante popular e logo já estava presente em grandes sistemas
coorporativos, sistemas operacionais, celulares, palmtops e várias outras
tecnologias. O número de desenvolvedores cresceu muito rapidamente, por
isso, também foi criada a JCP – Java Community Process
http://jcp.org/en/home/index – responsável por controlar e padronizar a
linguagem. A JCP http://jcp.org/en/home/index envolve as partes
interessadas no Java, de forma que possam ser discutidas definições, suas
funcionalidades e versões futuras da linguagem.
Em abril de 2009, a Sun foi adquirida pela ORACLE
http://www.oracle.com/br/index.html, gigante do setor de banco de dados.
Desde então, o mercado ficou apreensivo com o futuro da linguagem. Mas,
em janeiro de 2010, quando finalizou o processo de aquisição, a ORACLE
http://www.oracle.com/br/index.html anunciou que vários projetos da Sun
iriam ter continuidade, entre eles, o Java, sem qualquer prejuízo a seus
usuários e desenvolvedores.
4.2 Características
Na página de abertura do Java, a ORACLE
http://www.oracle.com/br/index.html define a linguagem como orientada a
objetos, independente de plataforma, ambiente de programação
multi-thread. Outras características da linguagem Java referem-se a ele
ser case-sensitive e de alto nível. Essas peculiaridades são fundamentais
para desenvolvimentos para Web e serviços de rede, aplicações, estações
de trabalho independentes de plataforma, robótica e outros dispositivos
embutidos. A seguir, vamos ver cada uma dessas características. Visite a
página do Java, ela é uma excelente leitura complementar!
http://www.oracle.com/us/technologies/java/index.html
Orientada a Objetos
A linguagem Java é orientada a objetos. Isso significa que ela
funciona com todas as características do paradigma de orientação a
objetos. Usando essa linguagem, o programador pode definir tipos
complexos de dados, denominados classes. Por meio dessas classes,
o programador pode instanciá-las. Quando dizemos que uma classe é
instanciada, significa que um objeto na memória é criado. A interação
desses objetos permite a execução das tarefas designada a eles,
conseqüentemente, o sistema funciona do jeito previsto pelo
projetista e implementado pelo programador. Veremos mais detalhes
sobre classes, objetos e instância nas nossas próximas aulas.
Independente de plataforma (portável)
A linguagem Java é altamente portável, ou seja, independente de
plataforma. Ela utiliza um componente responsável pela
independência de hardware e sistema operacional: a máquina virtual
Java (JVM – Java Virtual Machine). É uma máquina de computação
abstrata. Como uma máquina real de computação, a JVM também
possui uma configuração de instruções que manipulam várias áreas
de memória em tempo de execução, mecanismo conhecido como
interpretação. Porém, a máquina virtual Java não sabe sobre a
“linguagem de programação”, apenas conhece um tipo binário que é
o arquivo “.class”. O arquivo “.class” contém instruções da máquina
virtual – bytecodes – e uma tabela de símbolos, bem como
informações auxiliares. Para se gerar o arquivo “.class” o Java deve
ser compilado.
Portanto, pode-se dizer que Java é uma linguagem híbrida, pois a
máquina virtual interpreta e compila essas classes para que se tenha
uma execução mais otimizada. Maiores detalhes sobre a Java Virtual
Machine, você encontra nesta leitura complementar!
http://java.sun.com/docs/books/jvms/second_edition/html/Introduction
.doc.html#3057
No vídeo abaixo você poderá compreender melhor o funcionamento dos
compiladores, montadores e interpretadores; no processo de tradução
de códigos-fonte para programas executáveis.
VÍDEO CD - AULA 1 – VÍDEO 1 - TRADUTORES E JAVA
Ambiente de programação multi-thread
Programação multi-thread consiste no fato da linguagem Java ser
capaz de executar múltiplos threads simultaneamente. Thread pode
ser entendida como segmento ou linha de execução. Assim, é
possível chamar várias linhas de execução independentes, que
operam seus objetos e valores em uma memória principal
compartilhada. Mais informações sobre Threads podem ser
encontradas em
http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.do
c.html#33308.
Case-Sensitive
A linguagem Java faz diferenciações entre letras maiúsculas e
minúsculas. Veremos que uma variável, nome de classe, método ou
um identificador qualquer, definido com um nome específico, será
diferente de outro, com mesmo nome e diferente apenas no tamanho
das letras. Por exemplo, se uma variável for definida com o nome
“dataNascimento”, será diferente de outra variável com o nome
“DATANASCIMENTO” ou ainda “DataNascimento”. Por questões de
entendimento semântico do código, deve-se evitar o uso de variáveis
com diferença apenas no tamanho das letras, mas a linguagem
entende as denominações acima como variáveis totalmente
diferentes.
Linguagem de alto nível
A linguagem Java possibilita um alto grau de abstração. Fica fácil para
o programador escrever um código em Java. São comandos e
instruções mais entendíveis ao linguajar humano. Uma linguagem de
baixo nível é escrita em código de máquina, que são instruções muito
específicas e pouco convencionais à maioria dos seres humanos. Um
exemplo de linguagem de baixo nível é o “Assembly”
http://pt.wikipedia.org/wiki/Assembly.
4.3 Edições
Cada edição corresponde a uma plataforma tecnológica para utilização da
linguagem. O Java possui três extensões:
Java SE (Standard Edition)
Nessa edição o programador é capaz de desenvolver aplicações
seguras, portáveis e de alto desempenho, para várias plataformas
como Macintosh, Linux, Microsoft Windows e Oracle Solaris. É a
edição padrão. Será utilizada para exemplificar o objeto do nosso
estudo – a POO.
O Java SE é dividido em duas vertentes, o Java Development Kit –
JDK e o Java Runtime Environment – JRE. O JRE contém o software
Java Plug-in e também a Máquina Virtual Java (JVM). Como vimos
anteriormente, a máquina virtual é responsável por interpretar os
bytecodes e executar os programas Java. O JDK é o JRE acrescido do
kit de desenvolvimento, que consiste nas ferramentas e na linguagem
de programação.
O quadro abaixo, retirado da página oficial de documentação da
linguagem Java, representa bem as tecnologias contempladas tanto
na JRE quanto no JDK. Veja mais em:
http://download.oracle.com/javase/6/docs/index.html.
Fonte: http://download.oracle.com/javase/6/docs/index.html
Java EE (Enterprise Edition)
Elaborado para aplicações coorporativas. A edição Enterprise
possibilita a criação de sistemas distribuídos, multicamadas,
executadas em um ou mais servidores de aplicações. É considerado
um padrão de desenvolvimento, uma vez que o fornecedor deve
seguir regras pré-definidas para seu produto ser considerada
compatível com Java EE.
Java ME (Micro Edition)
É a plataforma Java para aplicações embarcadas ou embutidas
(embedded). São aquelas na qual o computador é destinado a um
dispositivo específico. São aparelhos compactos como celulares,
PDA’s, controle remotos, entre outros.
Informações detalhadas sobre cada uma dessas edições, você pode
encontrar na página do Java. Acesse!
http://www.oracle.com/us/technologies/java/index.html.
5 Ferramentas de Desenvolvimento (IDE)
Um Ambiente de Desenvolvimento Integrado (IDE – Integrated
Development Environment) é um programa que permite a criação (ou
desenvolvimento) de novos programas. A IDE dá apoio ao desenvolvimento,
permitindo padronização, agilidade, maior qualidade e produtividade. As
principais IDEs para aplicações em Java são:
NetBeans
O NetBeans é uma IDE bastante popular. Ele tem a chancela da Sun,
e o projeto continua mesmo depois da empresa ter sido adquirida
pela ORACLE. É uma ferramenta gratuita, multiplataforma (pode ser
usada no Windows, Linux, Solaris e Maços), possui código aberto,
totalmente escrito em Java e permite o desenvolvimento em outras
linguagens além do Java, como por exemplo: C/C++, PHP, Groovy,
Ruby entre outras. Para baixar o NetBeans, você pode acessar
http://netbeans.org/downloads/index.html.
Eclipse
A IDE Eclipse – Eclipse Foundation – é bastante encontrada nas
empresas de desenvolvimento de software. Não é exagero afirmar
que é a IDE Java mais utilizada entre os desenvolvedores. O projeto
eclipse foi iniciado pela IBM. Depois de um tempo, a IBM entregou o
Eclipse para a comunidade de software livre. É uma ferramenta
gratuita, de código aberto, multiplataforma e possui várias extensões
(plug-ins) responsáveis por facilitar a vida dos desenvolvedores e
tornar o trabalho muito mais produtivo. Para baixar o eclipse,
acesse: http://www.eclipse.org/downloads/.
ATENÇÃO PROGRAMADOR!
A linguagem Java foi uma das grandes precursoras, uma das responsáveis
pela da popularização dos softwares livres. Por isso, inicialmente, a idéia
dos desenvolvedores era não estarem vinculados a nenhum tipo de
ferramenta de desenvolvimento, nenhum fornecedor, nenhuma IDE
específica. A idéia era liberdade no desenvolvimento! O foco deveria ser o
programa em si, sem qualquer referência a plataformas de
desenvolvimento. A própria Sun, inicialmente, esteve reticente quanto ao
desenvolvimento de uma IDE comercial para o Java. Entretanto, o Java foi
ganhando cada vez mais dimensão, mais popularidade e se tornando
essencial em diversos sistemas. Cada vez mais, tornou-se necessário
aumentar a produtividade e encurtar o tempo de respostas, desde o
levantamento de requisitos até a versão final do programa.
Conseqüentemente, a Sun adotou o NetBeans como sua IDE oficial. Hoje, é
comum o desenvolvimento dos códigos Java através das IDE, que facilitam o
trabalho e aumentam a produtividade.
Por isso, para desenvolver os seus POOs, você poderá escolher entre as
IDEs propostas. Mas, caso seja de seu interesse, você também poderá rodar
seus programas a partir de editores de texto comuns. Neste caso, você
deverá acompanhar a leitura anexa para instalar e configurar o Java e
começar a programar utilizando apenas um editor de texto simples. Nesse
caso, não é preciso você ter uma IDE em seu computador para programar
em Java, Basta possuir o JDK instalado.
JAVA – EXECUÇÃO A PARTIR DO EDITOR CMD
ARQUIVO CD - AULA 1 - Leitura complementar – Java – execução a
partir do editor cmd
Desenvolver programas a partir de editores de texto comuns, como fazem
os mais saudosistas; ou aproveitar a agilidade e a facilidade proporcionadas
pelas IDEs? A decisão é sua!
Agora, que finalizamos toda a parte de instalação e configuração, já
estamos aptos rodar programas Java sem problemas. A partir da próxima
aula vamos começar a ver o conjunto de comandos que nos possibilitará
entrar no mundo da programação Java.
Resumo da aula
Nesta aula você foi capaz de compreender que o aumento da complexidade
dos Sistemas de Informação – SI – foi um dos motivos que propiciou a
grande adesão à orientação a objetos. A programação orientada a objetos
(POO) é uma evolução do paradigma de programação estruturado, pois visa
aproximar o mundo real do mundo computacional. Você também viu que a
JCP – Java Community Process é a entidade responsável por controlar e
padronizar a linguagem, que é definida pela ORACLE como orientada a
objetos, independente de plataforma, ambiente de programação multi-
thread. Além disso, você compreendeu que o Java possui três extensões
(Java SE - Standard Edition, Java EE - Enterprise Edition e Java ME - Micro
Edition). As Ferramentas de Desenvolvimento (IDEs) mais populares são
NetBeans e Eclipse. Ao final da aula você pôde baixar o Kit de
Desenvolvimento Java – JDK e decidir entre elaborar programas a partir de
editores de texto ou de IDEs.
Atividade
1. Explique o que significa POO.
2. Explique com suas palavras o que são modelos.
3. Identifique e relacione as principais características da linguagem Java.
4. Defina o conceito de abstração.
5. Identifique as Edições do Java e resuma as particularidades de cada
uma delas.
6. O que é uma IDE?
7. Faça uma pesquise e identifique as principais IDE’s para a linguagem
JAVA.
Instalação do JDK
Depois que a ORACLE comprou a Sun, tornou-se necessário fazer um
cadastro gratuito para baixar o JDK. Para baixar o Kit de Desenvolvimento
Java – JDK acesse o link abaixo:
http://www.oracle.com/technetwork/java/javase/downloads/jdk6-
jsp-136632.html
Caso esteja utilizando o Windows, instale o JDK como qualquer outro
programa. Clique duas vezes para iniciar a instalação e depois pressione o
botão “Next” até concluir. Abaixo, você encontra a primeira tela desse
procedimento.
No momento de construção deste material, a versão disponível para
download do Java era o jdk1.6.0_21.
Após o procedimento de instalação, basta você pressionar o botão “Finish”
que significa a conclusão dessa etapa.
Depois disso, você deve dizer ao sistema operacional onde estão localizadas
as classes do Java para que você possa compilar e executar seus programas
tranquilamente. Esta etapa caracteriza-se por configurar as variáveis de
ambiente. Novamente, caso esteja utilizando o sistema operacional
Windows, vá ao Painel de Controle e acesse a opção Sistema.
Após isso, vá em “Avançado” e depois “Variáveis de ambiente”.
Na tela “Variáveis de ambiente” clique em “Nova”.
Ao abrir a tela “Nova variável de sistema”, crie uma variável de ambiente
de nome “JAVA_HOME”. Essa variável vai dizer ao sistema operacional em
qual pasta está instalado o Java. No nosso caso, por conveniência,
escolhemos instalar o Java na pasta padrão designada no momento da
instalação, localizada em C:\Arquivos de programas\Java\jdk1.6.0_21.
Logo, a tela ficará assim:
Nome da variável: JAVA_HOME
Valor da variável: C:\Arquivos de programas\Java\jdk1.6.0_21
Depois, você deverá criar outra variável de ambiente, de nome
“CLASSPATH”. Ela indicará ao sistema operacional onde estão localizadas as
classes Java responsáveis por ler, compilar e interpretar o código Java que
você escreveu. A tela ficará assim:
Nome da variável: CLASSPATH
Valor da variável: .;%JAVA_HOME%\lib\tools.jar
Para finalizar, basta editar a variável Path para que o Windows saiba
localizar os comandos Java. É importante lembrar que você não deve apagar
o conteúdo da variável Path mas, sim, acrescentar o valor correspondente
no final dos valores pré-existentes. A tela da variável Path ficará assim:
Nome da variável: Path
Valor a ser acrescentado na variável: ;%JAVA_HOME%\bin
Para garantir o funcionamento dessas implementações, reinicie seu
computador e depois vá ao prompt (console) “Iniciar -> Executar -> cmd” e
digite “javac”.
Quando você for programar, poderá escolher por escrever em um editor de
texto simples ou utilizar uma IDE. Caso sua escolha seja por um editor
simples, então será necessária a compilação de cada uma das classes que
você construir. Utilizando uma IDE, ela já compila as classes, sem precisar
de um comando específico para isso. Em um ambiente coorporativo, no
entanto, você necessariamente usará ferramentas que farão todo este
trabalho pesado.
Veremos mais adiante, quando começarmos a executar nossas aplicações,
um passo a passo bem detalhado sobre como rodar um programa em Java
utilizando o bloco de notas e também utilizando a IDE eclipse. Depois do
primeiro exemplo, para ganharmos tempo, produtividade e também para
facilitar nossa vida, sempre utilizaremos a IDE eclipse.
AULA 2 - CONCEITOS
Compreender os conceitos fundamentais relacionados à programação em
Java é muito importante para que você tenha um bom aproveitamento
nesta disciplina. Apesar dos operadores, das estruturas de controle e de
decisão, serem similares às que você já conhece em programação
estruturada, esta aula é fundamental para que você possa relembrar (e
sedimentar) esses importantes conceitos. Assim, você estará mais seguro
na hora de desenvolver seus programas em Java.
Nesta aula você verá os tipos de referência, as palavras reservadas
e os operadores utilizados na programação Java (atribuição,
aritméticos, lógicos, relacionais e bit a bit). Além disso, você
também revisará as Estruturas de Controle e Decisão, como as
condicionais (if, if / else, if else if, if aninhado,
Operador Ternário – ?, switch) e as de Repetição (for, while,
do/while e break).
Abertura
Até hoje, a plataforma Java já atraiu mais de 6,5 milhões de
desenvolvedores de software. É utilizada em todos os principais segmentos
da indústria, estando presente em uma ampla gama de dispositivos,
computadores e redes.
Sua versatilidade, eficiência, portabilidade de plataforma e segurança
fazem dela a tecnologia ideal para a computação em rede. A tecnologia
Java está em todo lugar! Ela pode ser encontrada em laptops, datacenters,
consoles de jogo, supercomputadores científicos, telefones celulares e até
na Internet.
A tecnologia Java está presente em mais de 4,5 bilhões de dispositivos,
incluindo:
Mais de 800 milhões de PCs
2,1 bilhões de telefones celulares e outros dispositivos
portáteis (fonte: Ovum)
3,5 bilhões de cartões inteligentes
Além de set-top boxes, impressoras, webcams, jogos, sistemas de
navegação para automóveis, terminais lotéricos, dispositivos médicos,
guichês de pagamento de estacionamento etc.
Para conhecer os locais de aplicação do Java in Action em sua vida diária,
explore o site java.com.
Fonte: http://www.java.com/pt_BR/about/
Texto base
1 Tipos
Java é uma linguagem fortemente tipada, ou seja, toda variável deve ser de
um tipo específico conhecido pelo compilador. Para utilizar um tipo o
programador deve colocar o “tipo” seguido de um nome de variável.
Conforme padronização da JCP, ao se declarar uma variável, o nome a ser
utilizado deve ter letras minúsculas; caso seja um nome composto, apenas
a primeira letra dos nomes posteriores deve ser com letra maiúscula. Os
tipos podem ser categorizados como primitivos ou de referência.
Os tipos de referência são, principalmente, as classes utilizadas na
linguagem Java, mas também podem ser arrays ou interfaces (temas que
veremos mais à frente no nosso curso). Você verá que o programador pode
usar classes pré-definidas para linguagem (elaboradas por fornecedores de
componentes, por outros programadores, desenvolvedores e projetistas) ou
pode definir novas classes, sempre que desejar. Na nossa próxima aula
vamos aprender a definir e utilizar essas classes (tipos de referência), pois é
através delas que poderemos, efetivamente, programar “orientado a
objeto”.
Nessa aula, vamos nos concentrar nos tipos primitivos, que podem ser
booleanos (boolean), numéricos (byte, short, int, long, e char), e os
pontos flutuantes (float e double). Abaixo, segue uma tabela com os
tipos primitivos utilizados em Java.
Tipo Tamanho Valores boolean 8 bits true ou false
byte 8 bits com sinal -128 a + 127
short 16 bits com sinal - 32.768 a + 32.767
int 32 bits com sinal - 2.147.483.648 a + 2.147.483.647
long 64 bits com sinal - 9.223.372.036.854.775.808 a + 9.223.372.036.854.775.807
char 16 bits sem sinal 0 a 65535
float 32 bits com sinal - 1.40239846E-45 a + 3.40282347E + 38 *
double 64 bits com sinal - 4.94065645841246544E-324 a + 1.79769313486231570E + 308 *** 9 dígitos de precisão ** 18 dígitos de precisão
Abaixo, veja a definição de um tipo primitivo. Um exemplo de declaração de
variável, com o nome “salário”:
double salario;
Caso a variável possua nome composto como, por exemplo, “imposto de
renda”:
double impostoRenda;
Veja que estamos observando à padronização da JCP!
2 Palavras reservadas
A linguagem Java possui uma gama de palavras reservadas. Essas palavras
reservadas não podem ser utilizadas como identificadores
http://pt.wikibooks.org/wiki/Java/Identificadores , ou seja, nenhuma delas
poderá ser utilizado como nome de classe, objeto, variável, etc. São elas:
abstract continue for new switch assert default if package synchronized boolean do goto private this break double implements protected throw byte else import public throws case enum instanceof return transient catch extends int short try char final interface static void
class finally long strictfp volatile const float native super while
No decorrer das próximas aulas, veremos o significado e a utilização dessas
palavras reservadas, utilizadas na programação Java.
3 Operadores em Java
Por ter sido inspirada nas linguagens C/C++, o Java possui uma sintaxe
muito semelhante a elas, inclusive quanto aos operadores. Muito
provavelmente você já viu linguagem C em Programação Estruturada no
semestre passado, se este for o seu caso, encare esta parte como uma
espécie de revisão. As particulares que, por ventura, vierem a aparecer na
utilização da linguagem Java, serão vistas em momentos oportunos.
Operadores são instruções que realizam transformações e/ou comparações
a partir de dados ou operandos fornecidos no decorrer do programa. Os
operadores podem ser categorizados em: operadores de atribuição,
aritméticos, lógicos, relacionais e bit a bit.
3.1 Operador de atribuição
Operador de atribuição é identificado por um sinal de igual =; sendo o mais
fácil de ser compreendido, pois se restringe a atribuir um valor a uma
variável. Para atribuir um valor a uma variável, basta que a variável seja
seguida do operador = e, posteriormente, indicado o valor a ser atribuído à
variável. Exemplo:
int x = 2;
3.2 Operadores aritméticos
Os operadores aritméticos são aqueles que possibilitam a execução de operações
matemáticas. São eles:
Sinal Especificação+ Possibilita a soma de valores inteiros e de ponto flutuante- Possibilita a subtração de valores inteiros e de ponto flutuante* Possibilita a multiplicação de valores inteiros e de ponto flutuante/ Possibilita a divisão de valores inteiros e de ponto flutuante% Possibilita a obtenção do valor de resto, em formato inteiro, após uma divisão++ Possibilita o incremento de valores inteiros e de ponto flutuante
-- Possibilita o decremento de valores inteiros e de ponto flutuante
Alguns operadores são triviais como, por exemplo: +, – e * . Outros
merecem especial atenção, são eles: /, %, ++ e --. No caso da divisão,
representada por: / ; é importante salientar que, se a divisão for feita entre
números inteiros o resultado virá apenas em formato inteiro.
Por exemplo: se considerarmos duas variáveis inteiras ‘a’ e ‘b’ com os
valores 8 e 3 respectivamente, após efetuarmos a divisão a/b e
colocarmos o resultado em outra variável inteira ‘c’, o valor da variável
‘c’ (resultado) seria 2.
Representando o caso acima temos:
...int a = 8;int b = 3;int c = a / b;Resultado: c igual a 2
Perceba que o valor decimal não aparece, justamente pelo fato de o
resultado ter sido colocado em uma variável do tipo int ‘c’. Caso, no
exemplo acima, a variável ‘c’ fosse declarada como float, o resultado
ainda seria 2 mas, agora, com casas decimais (2,00000...). O resultado
seria 2 porque a divisão ainda seria com dois números inteiros. Como o
resultado seria colocado em uma variável de ponto flutuante, as casas
decimais com valor 0 fariam parte do resultado. Para obter o resultado
2,6666... seria necessário que pelo menos uma das variáveis (‘a’ ou
‘b’) fosse declarada como float. Isso forçaria o compilador a efetuar
uma operação com ponto flutuante e, ao colocar o resultado em uma
variável de ponto flutuante, o valor seria apresentado corretamente com as
casas decimais.
O operador % retorna o resto da divisão. Utilizando os mesmos valores do
nosso exemplo inicial, podemos visualizar um fragmento de programa
contendo a situação acima, da seguinte forma:
Representação da utilização do operador % :
...int a = 8;int b = 3;int c = a % b;Resultado: c igual a 2
Repare que no nosso exemplo, as variáveis ‘a’ e ‘b’ são inteiras e ‘c’
poderia ser inteira ou float. Esse programa vai imprimir como
resultado o valor 2. Todos nós sabemos que 8 dividido por 3, resulta em 2
com resto 2. Portanto, o operador % mostra como resultado o valor de
resto.
Os operadores ++ e -- (cuidado, não há espaço entre os dois sinais
‘+’ e nem entre os sinais ‘-’ ) representam o incremento e o
decremento respectivamente. São considerados operadores unários, pois
modificam a própria variável na qual o operador é aplicado. Se, em uma
variável inteira ‘x’, for aplicado o operador ++, então significa que ‘x’
será incrementado de 1.
Exemplo (++):
x++;é o mesmo que:x = x + 1;
Por similitude, se em uma variável inteira ‘x’for aplicado o operador --,
então, significa que ‘x’será decrementado de 1.
Exemplo (--):
x--;é o mesmo que:x = x – 1;
É importante salientar que esses operadores podem vir antes ou depois da
variável. Caso venham antes, então a variável sofre o incremento ou
decremento e, depois, retorna o valor correspondente. Se vierem depois,
então a variável primeiramente retorna o valor e, só depois, sofre o
incremento ou decremento.
3.3. Operadores Lógicos
São operadores usados em expressões que retornam os valores lógicos
‘verdadeiro’ ou ‘falso’. Seguem os operadores:
Operador Operação lógica&& and (e lógico)|| or (ou lógico)! not (não lógico)
3.4. Operadores Relacionais
São operadores que possibilitam a execução de comparações entre valores. São eles:
Operador
Descrição
> Compara se o operando do lado esquerdo é maior que o operando do lado direito< Compara se o operando do lado esquerdo é menor que o operando do lado direito
>= Compara se o operando do lado esquerdo é maior ou igual ao operando do lado direito<= Compara se o operando do lado esquerdo é menor ou igual ao operando do lado direito== Compara se o operando do lado esquerdo é igual ao operando do lado direito!= Compara se o operando do lado esquerdo é diferente ao operando do lado direito
Logo abaixo, segue a representação de um trecho de código. Um exemplo
de como utilizaremos os operadores relacionais e lógicos no decorrer de um
programa:
...int altura = 182;if(altura < 170)“Altura menor que a média”if((altura >= 170) && (altura < 180))“Altura média”if(altura >= 180)“Altura maior que a média”
Repare que, no trecho de código acima, são feitas comparações entre uma
determinada altura dada em centímetros (182) e valores indicadores de
altura menor que a média (<170), altura mediana (>=170 e <180) e
altura maior que a média (>=180). Repare ainda que, na comparação de
alturas, foram utilizados os operadores relacionais menor e maior igual. Foi
utilizado o operador lógico && (e) para indicar que, quando a altura fosse
mediana, ela teria que ser maior ou igual a 165 cm e menor que 180 cm,
ou seja, teria que atender as duas situações.
Você reparou outro detalhe fundamental nesse trecho de código? Perceba
que foi utilizada a palavra chave if. Esta palavra chave foi utilizada como
uma estrutura de decisão. Veremos mais detalhes sobre essas estruturas
mais à frente.
3.5 Operadores bit a bit
Os operadores bit a bit realizam suas operações sobre os bits de um
determinado número, e não sobre o valor. O operador AND (&) é o de
precedência mais alta. Depois de analisar dois bits ele retorna 1 caso os bits
sejam iguais a 1, caso contrário retorna 0. Em segundo lugar, em relação a
procedência vem o operador bit a bit OR exclusivo (^) cujo resultado é 1
caso os bits sejam diferentes e 0 para o caso de serem iguais. Para finalizar,
o operador OR (|), na qual retorna 0 se os bits forem 0 e 1 caso se os bits
forem 1.
Operador Operação& and
| or
^ or exclusivo (xor)
>> Deslocamento à direita
<< Deslocamento à esquerda
Os operadores bit a bit, quando utilizados, executam uma ação lógica a
cada bit nos argumentos da operação. Por exemplo, imagine uma variável
inteira com nome ‘x’, de 4 bits, de valor 2. Sua representação seria
‘0010’. Caso queiramos a negação desse número, então o resultado seria
‘1101’. Esses operadores só podem ser utilizados nos tipos char, int e
long int. Os operadores de deslocamento funcionam da mesma forma,
se, por exemplo, aplicássemos o operador de deslocamento à esquerda:
<< ; com o valor 2 no mesmo número inteiro. Dessa forma, teríamos como
resultado o valor, em bits, de ‘1000’.
Veja o exemplo:
int i = 2;~i = 13;
i<<2 = 8
4 Estruturas de Controle e Decisão
As estruturas de controle e decisão são essenciais para programação,
independentemente de ser ou não orientada a objetos. Por meio delas
conseguimos implementar as regras de negócio levantadas pela análise de
requisitos. As decisões aplicadas sobre os dados fazem a diferença na hora
de saber se determinado sistema atende ou não a necessidade para a qual
ele foi concebido. Estruturas de controle e decisão dependem fortemente
das operações com operadores lógicos vistos anteriormente.
4.1 Condicionais
4.1.1 if
A estrutura de decisão if é bastante conhecida entre os programadores.
Ela permite que o fluxo da execução seja desviado, assim, trechos de código
podem ser executados ou ignorados, dependendo do resultado de uma
determinada condição. Por exemplo, no caso abaixo, se a condição for
verdadeira, o trecho de código dentro do if é executado, caso a condição
seja falsa, então o trecho dentro bloco de comandos do if é ignorado.
if(condição) { // código executado}
4.1.2 if / else
A estrutura if / else também delimita blocos de acordo com uma
determinada condição. A diferença está localizada no trecho que está
dentro do bloco else, uma vez que esse trecho só será executado caso a
condição estipulada no if seja falsa. Vamos visualizar o trecho abaixo para
esclarecimento. Supomos que a condição comparada retorne um resultado
verdadeiro (true).
if(condição) {/* Código executado caso a
condição seja verdadeira*/
} else {/* Código ignorado caso acondição seja verdadeira*/
}
Em contra partida, caso o resultado da condição comparada seja falso
(false), então os blocos a serem executados serão invertidos.
if(condição) {/* Código ignorado caso acondição seja falsa*/
} else {/* Código executado caso acondição seja falsa*/
}
4.1.3 if else if
A estrutura if else é extensível, pois podem ser colocados outros if
depois do else. Neste caso, as hipóteses serão testadas e, caso satisfaça a
condição, a execução entra no if correspondente e não entra nos outros,
mesmo que satisfaçam a condição, a menos que algum desses outros if
não tenha um else precedido.
if(Condição_Falsa) {
//Instrução ignorada;
} else if(Condição_Verdadeira) {
//Instrução executada;
} else if(Condição_Verdadeira) {
/* Instrução ignorada mesmo sendo verdadeira pelo fato de
já ter sido executada a segunda instrução; */
}
4.1.4 if aninhado
Para finalizar, o comando if também pode ser aninhado. Significa dizer que
pode existir um if dentro de outro if. Enquanto a condição for satisfeita a
execução segue o fluxo normal e entra nos if’s. Quando a condição não
for satisfeita a execução segue o fluxo pelo else correspondente, se
houver.
if(Condição_Verdadeira) {
if(Condição_Verdadeira) {
if(Condição_Verdadeira) {
Instrução 1;
} else {
Instrução 2;
}
} else {
Instrução 3;
}
}
Note que pode, ou não, existir else para cada if. Depende da
necessidade do programa, ter ou não else para cada if. O else não é
obrigatório. É utilizado apenas em caso de necessidade.
4.1.5 Operador Ternário – ?
O operador ternário ? é muito particular, e pode ser encarado como um “if
simplificado”. O seu funcionamento consiste em receber uma operação
booleana para comparação e retornar o valor correspondente dependendo
do resultado ter sido verdadeiro ou falso. Vamos ver abaixo como funciona
esse operador.
int num1=3;int num2=6;int numMaior=0;numMaior = (num1 > num2) ? num1: num2;
(Valor retorno) = (Operação booleana) ? (retorno verdadeiro) : (retorno falso)
No trecho acima, é feita uma comparação entre dois números (num1 e
num2), o maior deles é retornado e alocado na variável numMaior.
4.1.6 switch
O comando switch é outra estrutura de decisão. O switch é mais
limitado em relação ao if, porque os valores a serem testados não aceitam
expressões lógicas. Nele, compara-se apenas uma variável com um valor
fixo. Mesmo assim, se bem empregada, é uma boa estrutura de tomada de
decisões, podendo auxiliar na limpeza, clareza e otimização de código.
Representação do comando switch
switch (variável){ case valor1: //bloco de instruções break;
case valor2: //bloco de instruções break;
case valorn: //bloco de instruções break;}
4.2 Repetição
Sabemos que, em programação, as estruturas de repetição são
extremamente necessárias. Também chamadas de laços ou iterações, são
úteis para vários tipos de situações. É muito comum o programador precisar
das estruturas de repetição para a confecção de um relatório, percorrer uma
lista de produtos em uma nota fiscal, lista de disciplinas por aluno, alunos
por curso, entre outros exemplos.
4.2.1 for
O for é uma estrutura de repetição cuja função é percorrer uma seqüência
de índices e executar uma operação a cada passagem, até que esta
seqüência termine. Cada passagem de índice é chamada de iteração e
comumente conhecida como laço ou “loop”.
for(inicialização; seqüência de execução; incremento/decremento) { //bloco de instruções;}
Para compreender melhor o uso do for, vamos analisar cada parte do
comando:
1° parte: inicialização. A inicialização é a definição de quando começa a
contagem do índice.
2° parte: seqüência de execução. A seqüência de execução é que
determina o limite da iteração, ou seja, até quando o índice irá percorrer.
3° parte: incremento/decremento. Determina a maneira com a qual o
índice percorre a seqüência de execução.
A linguagem Java ainda possui outros tipos de for personalizados. A
funcionalidade é a mesma, apenas a sintaxe é diferente. Existem for
específicos para serem utilizados em iterações e coleções parametrizadas,
por exemplo. No momento oportuno, veremos a utilização dessas
estruturas.
4.2.2 while
O comando while é uma estrutura de repetição que testa uma condição e,
enquanto essa condição for satisfeita, a execução dentro do comando
while continua.
Segue a representação do comendo while:
while(condição) { //bloco de instruções;}
4.2.3. do/while
O comando do/while se diferencia do comando while, pois executa a
iteração pelo menos uma vez, quando, só então, a condição é testada. Se a
condição for verdadeira, a execução continua, caso a condição seja falsa
então o laço é interrompido. Enquanto no while, a execução da iteração
só começa se o teste da condição for verdadeiro, no do/while, é
executado o “loop” logo na primeira vez e depois se testa a condição.
Representação do comando do/while:
...do{ // bloco de instruções} while (condição)...
Não se esqueça que em todas as estruturas de repetição pode ser usado o
comando break, ele tem a mesma função de quando usado no comando
switch, que é a de interromper a execução. No caso de um “loop”, o
break encaminha a execução diretamente para o próximo bloco de
execução, após a estrutura de repetição.
Resumo da aula
Nesta aula você foi capaz de compreender os tipos de referência, as
palavras reservadas e os operadores em Java (atribuição, aritméticos,
lógicos, relacionais e bit a bit). Além disso, você também revisou as
Estruturas de Controle e Decisão, como as condicionais (if, if / else,
if else if, if aninhado, Operador Ternário – ?, switch) e as de
Repetição (for, while, do/while e break), que serão
amplamente utilizadas na sua programação em Java.
Atividade
1. Especifique a diferença entre tipos primitivos e tipos de referência.
2. Identifique a função e cada um dos Operadores de atribuição abaixo:
a. ==
b. :=
c. =
d. +=
e. =+
3. Descreva os tipos de operadores utilizados em Java.
4. Descreva o que é, e qual a função de um operador bit a bit?
5. Especifique o que é um operador ternário?
6. Escreva o que é uma estrutura de controle condicional.
7. Descreva quais são e para que servem as estruturas de controle
condicional.
8. Indique quais são, e para que servem, as estruturas de repetição.
9. Explique para que serve a palavra reservada break.
10.A título de revisão, elabore um programa em linguagem C (ou outra
linguagem estruturada), que solicite ao usuário que digite um
número, apresentando uma resposta que faça com que o usuário
consiga acertar o número pensado pelo programador. Acompanhe um
vídeo com este exercício resolvido! (AULA 2 – VÍDEO 1 - EXERC.
RESOLV. – IF - ADIVINHE O NÚMERO)
11.Desenvolva o mesmo programa acima utilizando os comandos
if/else.
12.Elabore um programa em linguagem C (ou outra linguagem
estruturada), que verifica e imprime como resultado se um número
digitado pelo usuário é par ou impar. Dica: Utilize if e o operador %.
13.Prepare um programa em linguagem C (ou outra linguagem
estruturada), a que leia 5 valores inteiros e diga qual é o maior, o
menor, a soma, a média.
14.Desenvolva um programa em linguagem C (ou outra linguagem
estruturada), que receba 3 notas de um determinado aluno digitadas
pelo usuário (com pesos iguais a 3, 3 e 4), calcule a média e imprima
se o aluno está aprovado ou reprovado sendo que a nota mínima para
passar é 7. Utilize if.
15.Desenvolva um programa em linguagem C (ou outra linguagem
estruturada), que simule uma calculadora simples. Onde o usuário
escolhe uma opção que represente uma operação. Ex: 1 para somar;
2 para multiplicar; 3 para subtrair e 4 para dividir. Após a escolha da
operação o programa recebe dois números e realiza a operação
escolhida com esses dois números. Utilize switch.
16.Elabore um programa utilizando a estrutura for que apresente um
“loop infinito”. O programa somente será interrompido quando uma
tecla específica for acionada. Acompanhe o vídeo com este exercício
resolvido! (AULA 2 – VÍDEO 2 - EXERC. RESOLV. – LOOP INFINITO
- FOR)
17.Elabore o mesmo programa acima utilizando a estrutura de repetição
while.
18.Desenvolva um programa que leia 10 números, mas se entre eles
existir o número 7 então utilize o comando break para sair da
estrutura e encerrar o programa.
AULA 5 - MÉTODOS E ATRIBUTOS
Na aula passada, você viu que os atributos são variáveis que devem ser
definidas dentro das classes. Por meio deles, são alocados os valores que
são manejados no programa. Já os métodos são responsáveis pelo manuseio
dos valores definidos nos atributos. Os métodos são os responsáveis pelo
fluxo da informação sistêmica, pela formatação para correta apresentação
ou pelo tipo de formatação que possibilita o correto armazenamento de
informações, por exemplo. Nesta aula, aprofundaremos um pouco mais
nosso conhecimento sobre esses dois conceitos.
Ao final desta aula você será capaz de compreender o que são
atributos e métodos. Você também verá a função dos modificadores
de acesso (private, protected, public, static e final) e
entenderá os Métodos Construtores. Ao final da aula, você
acompanhará a elaboração de um programa composto por três
classes que identificarão um resumo de compras em um
estabelecimento comercial e uma vídeo-aula com mais alguns
outros exemplos de classes.
Abertura
Vimos que a classe define a estrutura de um objeto. Portanto, uma classe
especifica todos os atributos (propriedades) e métodos (comportamento)
dos objetos que pertencem àquela classe. Abaixo, você pode ver o exemplo
de uma classe Carro e quatro objetos que foram gerados a partir dessa
classe.
Agora, veja a representação do objeto gerado pela classe Carro, Porshe, GT-
3, branco. Portanto a classe Carro tem como atributos: fabricante, modelo e
cor. Já os métodos definidos nesta classe são: ligar, acelerar e desligar;
comportamentos próprios do objeto em questão.
Veja que a classe é um modelo para gerar objetos. Em uma classe, os
atributos representam o estado do objeto. Já os métodos, a interação dos
objetos com o mundo externo.
Texto base
1 Atributos
Atributos são campos agrupados em uma classe. Eles são os responsáveis
pelo armazenamento dos valores utilizados no sistema. Em outras palavras,
são variáveis, que devem ser declaradas dentro das classes. Tecnicamente,
você pode compreendê-los como endereços de memória utilizados para
armazenamento de conteúdos, que dependem do tipo definido para o
atributo.
Um atributo pode ser de qualquer tipo pré-definido, desde os primitivos,
como: int, double, char; até os de referência, como as classes
String, Date ou qualquer outra. No caso dos atributos de classe, eles
deve ser inicializados com algum valor correspondente; caso isso não
ocorra, haverá erro na compilação.
Segundo padronização da Sun os nomes de atributos devem começar com a
letra minúscula, caso seja um nome composto a primeira letra do nome
subseqüente deve iniciar com a letra maiúscula e o restante deve continuar
com letras minúsculas.
2 Métodos
Métodos são operações pertencentes a uma determinada classe. O método
é onde os códigos são efetivamente executados. Um método pode chamar
outros métodos, que podem estar na mesma classe ou em classes
diferentes. A dinâmica de um sistema é feita por meio dos métodos. Eles
ditam o comportamento da aplicação e a seqüência das chamada das
operações é que determina como funciona o sistema. Alguns autores
preferem chamar os métodos de mensagens. Assim, quando dissermos
que há um envio de mensagem significa dizer que determinado método foi
executado.
Os métodos podem receber parâmetros, que por sua vez, podem ser de
tipos primitivos (int, double, char, float, etc) e de tipos de
referência (String, Date, etc). Nos exemplos vistos até agora,
você pôde acompanhar parâmetros definidos para o método main, que
consistiram em um array de strings: main(String[] args). Perceba
que, para se fazer a declaração de parâmetros é necessário colocar o tipo
do parâmetro e depois o nome da variável. Caso haja mais de um deve-se
separá-los por vírgula.
Métodos também podem retornar um valor, ou não. Caso retornem um
valor, eles também podem ser do tipo primitivo ou de referência. Já
conhecemos os tipos primitivos que são os booleanos, numéricos e pontos
flutuantes (todos aqueles vistos no início da nossa aula 2). Portanto, os tipos
de referência serão todos aqueles utilizados no nosso sistema desde que
não sejam os tipos primitivos.
Abaixo, segue a estrutura de um método.
<opcional> <obrigatório>
modificador static final tipo_de_retorno nome_do_metodo(lista_de_parametros) {
} <opcional>
Os parâmetros são opcionais, mas devem existir os parênteses () mesmo
que não haja parâmetros.
3 Modificadores de acesso
Uma característica comum, tanto aos métodos quanto aos atributos,
consiste no uso dos modificadores de acesso. Métodos e atributos podem
ter os seguintes modificadores de acesso: private, protected e
public, além dos static e final.
3.1 private
É quando o método ou atributo é visualizado apenas dentro da
própria classe. Os métodos/atributos privados (private) de uma
determinada classe, não são visualizados em outra classe. Isso ocorre
independente de estarem localizadas no mesmo pacote ou de serem
subclasse de uma classe com métodos/atributos privados. Os
métodos/atributos private são particulares da própria classe.
3.2 protected
É quando o método/atributo pode ser visualizado tanto na própria
classe quanto em suas subclasses. Quando uma classe estende outra
classe, todos os métodos e atributos protegidos (protected)
podem ser visualizados e conseqüentemente utilizados pela classe
filha.
3.3 public
Os métodos e atributos públicos (public) são vistos por todas as
outras classes. Independentemente de serem subclasses ou não,
sempre são visualizados e podem ser acessados por outras classes.
São operações e atributos que podemos usar normalmente nas
classes que construímos.
Vimos que um método ou um atributo declarado na classe é utilizado nas
instâncias daquela classe. Logo, um atributo de um tipo qualquer, como por
exemplo int, terá um valor particular em cada um do objetos daquela
classe. Quando definimos operações em uma classe, apenas objetos
instanciados naquela classe podem executar aqueles métodos. Obviamente,
se não houver um objeto na memória capaz de chamar aquele determinado
comando, não será possível acessar o método declarado na classe.
A linguagem Java aceita a declaração de atributos e métodos sem
modificadores de acesso. Dessa forma, esses atributos e métodos são
enxergados por outras classes, diferentes daquela em que foi declarada,
mas desde que estejam localizadas dentro do próprio pacote.
As melhores práticas de programação orientada a objetos definem que
todos os métodos e atributos devem possuir modificadores de acessos.
Logo, por uma questão de clareza e segurança, devemos evitar a utilização
de atributos e métodos sem modificadores de acessos.
Outra recomendação das melhores práticas de programação diz que todos
os atributos declarados nas classes devem ser privados (private) e
qualquer manipulação desses atributos devem ser feitos por meio de
métodos públicos. São os famosos get e set, que veremos mais à frente.
Além dos modificadores vistos acima, ainda podemos citar também o
static e final, que também são modificadores que agem sobre os
métodos e atributos.
3.4 static
É possível acessar métodos e atributos de classe, não sendo
necessária a criação de instâncias para poder manipulá-los. Para isso,
utilizamos o modificador static. Ao utilizar o static em um
atributo, dizemos que este atributo é, na verdade, da classe, ou seja,
todas as instâncias dessa classe enxergarão o mesmo valor naquele
atributo. O valor será compartilhado por todos uma vez que o atributo
não pertencerá a uma instância específica e sim à classe.
Isso acontece também para os métodos. Ao se fazer um método
estático, o programador está fazendo um método que não precisa de
instância para executar. Pode-se fazer a chamada do método
diretamente sem a necessidade de criar um objeto para isso. É bom
ressaltar que métodos estáticos não terão acesso a atributos e
métodos normais. O acesso pode ser feito somente a variáveis do
próprio método ou outros métodos também estáticos, pelo simples
fato de que não há garantias sobre a existência de memória para tais
métodos e atributos.
3.5 final
O modificador final também é utilizado em métodos e atributos.
Por meio desse modificador é possível restringir a sobrescrita de um
método ou definir uma constante em um atributo. Em outras
palavras, quando declaramos um método como final estamos dizendo
que ele não poderá ser reescrito em subclasses, ou seja, aquela
implementação dele é a última e não poderá ser modificada. Se for
colocado em um atributo, significa que ele não poderá sofrer
alterações em seu valor, ou seja, será constante, imutável.
Agora, acompanhe mais alguns exemplos de modificadores utilizados no
escopo dos programas.
VIDEO CD - Aula 05 - video 1 - modificadores priv prot
4 Métodos Construtores
Métodos construtores são aqueles executados quando se cria uma
instância. Por exemplo, ao se aplicar a palavra reservada new, sabemos
que um objeto é criado na memória, logo o método correspondente –
construtor – é chamado para que essa operação seja feita. Caso o
programador não crie explicitamente o método construtor, ele é criado
automaticamente, da forma padrão – ou seja, sem parâmetros. Caso seja
criado explicitamente pelo programador (com parâmetros ou não) o
construtor padrão não é criado automaticamente pelo compilador.
Em uma classe podem existir vários métodos construtores, a depender da
vontade do desenvolvedor. Obviamente, encher uma classe com métodos
(sejam eles construtores ou não), atributos e objetos desnecessários, não é
interessante para a estrutura do programa.
O método construtor é executado ao se iniciar a classe. Ele não pode ser
confundido com o método main, que é executado ao se iniciar a aplicação,
quando digitada a expressão java Classe, sendo essa classe detentora
do método main.
Abaixo, vamos elaborar um programa com as características expostas. Ele
será composto por classes que identificarão clientes, produtos e nota fiscal;
e apresentará um resumo de compras em um estabelecimento comercial.
Analisando o código acima, primeiramente vimos a classe Cliente com dois
atributos de classe chamados “nome” que é do tipo String, e
“quantidadeProdutos” do tipo int (perceba que os nomes desses atributos
foram definidos de acordo com as melhores práticas). Além disso, veja que
os modificadores de acesso dos atributos foram definidos como privados e
os métodos que acessam esses atributos são públicos. Isso acontece para
ser mantido o encapsulamento, onde o acesso aos atributos deve ser
restrito por meio de métodos e não diretamente.
Outro fator importante a ser verificado no programa acima é o fato dos
métodos que acessam os atributos serem definidos com os prefixos get e
set. Utilizamos o get para obter o valor de um atributo por meio de um
método e set para fixar um valor em um atributo utilizando um método.
Quando utilizamos classes cujos valores dos atributos serão obtidos ou
fixados fora da classe empregamos o get e set.
Não é obrigatório o uso dos prefixos get e set em nomes de métodos que
acessem atributos de classe. Isso é apenas um padrão utilizado pelos
programadores da linguagem, assim fica mais fácil a identificação e a
manutenção daqueles métodos e atributos da classe.
A sintaxe desses métodos costuma ser “get + nome do atributo” e “set +
nome atributo”. Como exemplo, podemos verificar o atributo
quantidadeProdutos da classe Cliente acima. Repare que para obtermos o
valor armazenado no atributo mencionado utilizamos o método
getQuantidadeProdutos. Da mesma forma, usamos setQuantidadeProdutos
para fixar um novo valor no atributo quantidadeProdutos, passando este
novo valor como parâmetro.
Outra característica que podemos ressaltar nessa classe é a utilização da
palavra this. Se pegarmos como exemplo o método
setQuantidadeProdutos(int quantidadeProdutos),
utilizado nesse programa, podemos verificar que o nome do parâmetro
desse método é o mesmo do atributo de classe definido anteriormente. Para
realizarmos a diferenciação entre o atributo da classe e a variável definida
no parâmetro do método, empregamos a palavra reservada this antes do
atributo de classe. Assim, o valor vindo pelo parâmetro é colocado no
atributo. Caso o atributo de classe com o mesmo nome do parâmetro do
método não estivesse precedido pela palavra this, o método só
enxergaria seu próprio parâmetro deixando o atributo da classe sem ser
preenchido.
A palavra reservada this indica que estamos falando da própria classe ao
fazermos referência a um determinado atributo ou método. Portanto,
quando quisermos dizer que um método ou atributo é parte integrante da
própria classe, deveremos colocar a palavra this antes dele.
Podemos observar também a existência de dois métodos construtores, um
sem parâmetro, conforme podemos ver abaixo:
public Cliente(){
}
e outro com dois parâmetros, denominados nome do tipo String e
quantidadeProdutos do tipo inteiro.
public Cliente(String nome, int quantidadeProdutos){
}
Repare na diferença de métodos convencionais e métodos construtores. Os
últimos devem ter o mesmo nome da classe na qual eles pertencem, além
disso, também não possuem tipo de retorno.
No momento de criação de um objeto dessa classe, o programador já pode
preencher os dois atributos da classe em questão com os valores passados
como parâmetro pelo método construtor que contém os parâmetros.
Continuando a construção do nosso programa, veremos agora o
funcionamento da classe Produto.
Veja que a classe Produto, definida acima, é bastante semelhante à classe
Cliente vista anteriormente. Ela possui a mesma estrutura com dois
atributos de classes, métodos de acesso – get e set – e métodos
construtores, sendo um padrão, definido explicitamente pelo programador,
e outro com parâmetros para preenchimento dos atributos. O método
padrão definido explicitamente pelo programador é
public Produto() {
}
O método construtor com dois parâmetros foi definido da seguinte forma:
public Produto(String nome, double valor){
.
}
Abaixo segue a classe NotaFiscal que utilizará as classes definidas acima.
Temos algumas novidades nesta classe NotaFiscal. A primeira delas é a
utilização de uma constante de nome linha. Para isso, bastou
declararmos um atributo com o modificador final e colocarmos ele de modo
estático. Assim, ele é acessado dentro do método main de maneira direta.
Veja que o método também é estático. Caso o atributo não fosse estático
teríamos que instanciar a classe NotaFiscal para poder utilizar o atributo.
Outra novidade está na utilização dos argumentos que são passados como
parâmetros pelo método main. Na classe acima, estamos usando quatro
argumentos do tipo String que são passados no momento em que a
classe é chamada, como veremos na próxima figura – tela de resultado.
Aqui devemos prestar um pouco mais de atenção. Se estivermos utilizando
o modo clássico de compilar e executar – comando javac NomeClasse.java
[ENTER] java NomeClasse – então, para passar os parâmetros, basta
preenchermos os valores no momento de digitar java NomeClasse.
Cada valor, separado por espaço, é considerado um parâmetro
independente. Caso queiramos passar um nome composto, por exemplo,
devemos passá-lo entre aspas para que a máquina virtual entenda que se
trata de apenas um parâmetro. Agora, se estivermos utilizando o eclipse –
que é o nosso caso – devemos colocar os parâmetros na tela específica para
parâmetros. Para isso, devemos ir no menu Run -> Run Configurations....
Na tela de configurações, na aba referente aos argumentos, coloque os
argumentos do programa separados por espaço. No nosso caso, conforme
figura abaixo, colocamos os argumentos: Aderbal 15 Camisetas 30.45
Depois disso, basta clicarmos no botão Apply e depois Run, assim, o
programa será executado com os parâmetros anotados.
Ainda sobre a classe NotaFiscal, podemos observar a criação de objetos
das classes Cliente e Produto cujos valores dos atributos vêm dos
argumentos passados pelo método main. Criamos um método estático cujo
nome é getValorTotal, passando como parâmetros as referências de
cliente e produto criadas anteriormente para que o valor total fosse
calculado baseado na quantidade de produtos dos clientes e no valor desses
produtos. Depois, de posse dos valores, basta que coloquemo-los na tela
utilizando o método println.
Segue abaixo a tela de resultado referente a execução do programa em seu
modo clássico. Este é o modo de chamar um programa com argumentos
quando utilizamos apenas o JDK para confecção dos nossos programas.
Agora, vamos reparar a dinâmica de funcionamento do programa em Java.
Repare que, primeiramente, compilamos a classe Cliente usando o javac,
depois compilamos as classes Produto e NotaFiscal na seqüência.
É importante lembrar que devemos primeiro compilar as classes
independentes, para depois compilarmos as classes que dependem de
outras. No nosso exemplo compilamos primeiramente as classes Cliente e
Produto antes de compilar a classe NotaFiscal, pois em NotaFiscal são
utilizadas as classes Produto e Cliente. Portanto, para ser compilada, uma
classe necessita que as classes da qual ela depende já tenham sido
anteriormente compiladas.
Como o método main só está na classe NotaFiscal, basta executarmos
essa classe para que o programa funcione. Repare que na hora de executar
a classe NotaFiscal passamos os argumentos a serem colocados no array
de Strings utilizados como parâmetro no método main. Assim, o primeiro
parâmetro (com índice 0) é o nome do cliente, o segundo parâmetro (índice
1) é a quantidade de produtos adquiridos pelo cliente, o terceiro parâmetro
(índice 2) é o nome do produto e o quarto parâmetro (índice 3) é o valor de
cada um dos produtos. A execução do método main colocou cada
argumento no seu devido lugar para a execução correta do programa.
Por fim, para executar o programa, devemos acessar o prompt de comando,
ir à pasta correspondente ao projeto, digitar as instruções: javac
Cliente.java, para compilar a classe Cliente, depois javac
Produto.java para compilar a classe Produto e finalmente digitar
javac NotaFiscal.java para compilar a classe NotaFiscal. Depois da
compilação das classes devemos executar o programa digitando a
instrução: java NotaFiscal e mais quatro parâmetros que, no nosso
exemplo, foram: “Joao Neto” 4 Camisetas 30.20, assim o primeiro
parâmetro é o nome do cliente, o segundo parâmetro a quantidade de
produtos adquiridos pelo cliente, o terceiro parâmetro consiste no produto
adquirido e por último o valor unitário de cada produto.
Repare agora, a saída do programa quando utilizamos o eclipse. Colocamos
os argumentos na tela de configurações e o Java utiliza esses argumentos
para execução do programa.
A dinâmica é a mesma, o eclipse apenas encapsula esse mecanismo.
Quando apertamos o botão Run é como se digitássemos a expressão javac
NomeClasse.java e depois java NomeClasse. Para executar com argumentos
o eclipse reserva um espaço específico para esse fim, assim, quando o
botão Run for pressionado ele saberá onde buscar os argumentos e
executar perfeitamente o programa.
No programa acima, vimos todos os conceitos aprendidos nessa aula,
utilizando três classes: Cliente, Produto e NotaFiscal. Agora, veremos outro
exemplo de programa utilizando os métodos construtores. No projeto abaixo
você acompanhará um exemplo que utilizará as classes Construtor e
Principal. Acompanhe!
VIDEO CD - Aula 5 – vídeo 2 – construtores
Agora, veremos outro exemplo de programa, mais completo, utilizando
métodos construtores, método e atributo estáticos. No projeto abaixo você
acompanhará um exemplo que utilizará as classes Cliente, Produto, Linha,
Total e RelacaoCompras. Acompanhe!
VIDEO CD - Aula 05 - video 3 - modificadores static final e
construtores
Resumo da aula
Nesta aula, você pôde verificar que atributos são campos agrupados em
uma classe, pois são responsáveis pelo armazenamento dos valores
utilizados na programação; enquanto os métodos são as operações
pertencentes a uma determinada classe. Você observou que uma
característica comum aos métodos e atributos é o uso dos modificadores de
acesso e que os métodos construtores são aqueles executados quando se
cria uma instância. Você também teve a oportunidade de acompanhar a
elaboração de um programa composto pelas classes clientes, produtos e
nota fiscal, que apresentava um resumo de compras em um
estabelecimento comercial. Por fim, você acompanhou detalhadamente a
dinâmica de funcionamento desse programa, incluindo a execução de cada
uma das classes criadas.
Atividade
Criar Exercícios
1. Especifique quais são os modificadores de acesso.
2. Descreva o significado das seguintes palavras modificadoras: private,
protected, public, static.
3. Elabore uma classe que calcule a média no método main de dois
números passados como argumentos na chamada da classe.
4. Crie uma classe com dois atributos, um String e um inteiro, que sejam
preenchidos com valores passados como argumentos na chamada da
classe.
5. Elabore uma classe que possua um método para calcular a média de
dois números passados como argumentos na chamada da classe. No
método main, deve haver apenas a chamada do método
calcularMédia e, em seguida, a apresentação do resultado. Dica:
Lembre-se que o método main é estático, portanto, para que não haja
problema, instancie um objeto dessa classe no método main para que
não haja erros de compilação.
6. Elabore uma classe específica que calcule a média de dois números
passados como argumentos na chamada da classe principal
(possuidora do método main). No método main da classe principal
deve haver a instanciação da classe específica, a passagem dos
valores obtidos como argumentos para a classe específica por meio
de métodos de acesso (get e set), a chamada do método calcular
média da classe específica e a apresentação do resultado.
7. Elabore mais dois métodos responsáveis por calcular a média na
mesma classe específica acima, sendo que o primeiro realiza o
cálculo da média de 3 algarismos e o segundo realiza o cálculo da
média com 4 algarismos passados como argumentos pelo usuário da
classe. Se achar necessário, crie mais atributos e métodos
assessores.
8. Crie uma classe específica que possua um método construtor com
uma mensagem qualquer. Crie também uma classe principal com o
método main instanciando a classe específica para que a mensagem
seja apresentada no console.
9. Crie uma classe específica que possua uma constante do tipo String e
um método construtor chamando essa constante. Crie também uma
classe principal com o método main instanciando a classe específica
para que a mensagem da constante seja apresentada no console.
10.Crie uma classe específica com métodos responsáveis por calcular a
média, a soma, a subtração, a multiplicação e a divisão de dois
números passados no momento de chamar a classe principal. A
classe principal deve, em seu método main, instanciar a classe
específica e chamar todos os métodos de cálculo dessa classe.
Lembre-se que os atributos devem ser do tipo float ou double para
que a operação de divisão seja feita corretamente.
Desafio: Adapte as classes do exercício 6 para que os valores passados
como argumentos no momento de chamada da classe principal sejam
passados para a classe específica por meio do método construtor dessa
classe específica.
AULA 3 – SINTAXE BÁSICA DA POO
.
Ao final desta aula você será capaz de compreender a sintaxe
básica de uma linguagem OO, bem como os conceitos essenciais de
abstração, herança, polimorfismo e encapsulamento. Logo após
essa parte inicial, você será capaz de rodar o seu primeiro
programa em Java (HelloWorld) e analisará, com calma, cada parte
do código fonte de programa executado. Também será possível
acompanhar vídeos-aula com outros exemplos de programa.
Abertura
Uma das marcas registradas do Java é a sua mascote
Duke, criado ainda no projeto Green por Joe Palrang,
quando a tecnologia Java foi anunciada pela primeira vez.
O Duke pode ser visto em um conjunto de fotos que
explica que sua transformação é livre. Há quem diga que o
mascote da linguagem de programação Java é baseado no
emblema da federação da série de televisão Star Trek. Os
usuários podem incluir sua imagem em sistemas, sites, e
merchandising, de acordo com os termos da licença. Você
poderá ver uma coleção de imagens editadas do mascote
Duke clicando em http://duke.kenai.com/
Texto base
1 Sintaxe básica de uma linguagem OO
Ainda nesta aula, rodaremos o nosso primeiro programa em Java. Portanto,
já é bom que você se atenha a alguns conceitos fundamentais de sintaxe da
linguagem Java, como: classe, atributo, objeto e método. Veremos com
detalhes cada uma dessas definições, mas, por enquanto, vamos passar
rapidamente a idéia principal que cerca cada um desses itens da linguagem
orientada a objetos.
Classes – As classes são as unidades de programação básicas para o
funcionamento de um sistema baseado no paradigma OO. Uma classe
é, antes de tudo, uma abstração, pois serve como um conjunto de
características e comportamentos. Ela pode ser encarada como um
molde, ou seja, um modelo a ser seguido durante o programa,
possuidor de atributos e métodos.
Atributos - Os atributos definem as propriedades (estado,
características) que um objeto pode ter. Geralmente eles funcionam
como variáveis, que devem ser definidas dentro das classes. Por meio
deles são alocados os valores que são manejados no programa. Esses
valores podem vir de usuários (em preenchimentos de formulários via
web, por exemplo), de outro sistema, por meio de processamento
batch, web services, recuperação de informações de banco de dados,
entre muitos outros.
Objeto - Um objeto é uma representação abstrata de uma entidade
do mundo real. Além de possuir um identificador único, o objeto
também tem propriedades embutidas e a habilidade de interagir com
outros objetos e consigo mesmo. As classes são utilizadas para criar
objetos; e são elas definem os atributos e o comportamento dos
objetos.
Métodos – São os responsáveis pelo manuseio dos valores definidos
nos atributos. Os métodos (também conhecidos como operações) são
os responsáveis pelo fluxo da informação sistêmica, pela formatação
para uma determinada apresentação ou pelo tipo de formatação que
possibilita o correto armazenamento de informações. Os métodos
também pertencem a uma determinada classe. Eles ditam o
comportamento da aplicação, manipulam os atributos e estabelecem
a dinâmica dos sistemas de informações.
No decorrer desta aula, veremos informações mais detalhadas sobre classes
e objetos. Nossa próxima aula falará apenas de métodos e atributos.
2 Conceitos Essenciais
Os conceitos que veremos agora também são de extrema importância para
o bom entendimento do paradigma orientado a objetos. No decorrer do
curso, nos aprofundaremos ainda mais nesses conceitos e também a na
forma como eles são implementá-los na linguagem Java. Lembre-se que
estamos usando a linguagem Java como um meio para atingir o objetivo
principal, que é compreender o paradigma OO.
Os conceitos que veremos a seguir são: abstração, herança,
polimorfismo e encapsulamento.
2.1 Abstração
Consiste na habilidade do projetista em se concentrar no que é essencial
para o correto funcionamento do sistema. É importante ignorar o que é
supérfluo!
Na figura abaixo, você pode observar um exemplo de abstração. O objeto
em questão: “viagem”; traz diferentes abstrações para diferentes pessoas.
Para um passageiro, os itens fundamentais são: portão de embarque, hora
de saída, número do vôo. Para a torre de controle, as informações
importantes nesse objeto são: rota a ser definida, tráfego na pista de
decolagem, pista a ser utilizada, código da aeronave, etc.
FIGURA 1 – Exemplo de abstração: VIAGEM
A abstração é particular de cada um, dependendo do foco e da abrangência do tratamento a
ser a determinado problema.
Outra aplicação importante da abstração é a possibilidade de o projetista
prever uma determinada situação e esta poder ocorrer de diferentes
maneiras. Assim, o responsável pelo projeto implementa a parte genérica
da solução corretamente, mas deixa parte dessa solução (aquilo que é
especifico de um determinado domínio, ou ainda que pode ser tratado de
jeito diferente a depender de cada caso ou situação) para a
responsabilidade do desenvolvedor.
Assim, o projetista é capaz de abstrair a solução, embora já tenha deixado a
arquitetura, a parte genérica da solução, pronta. Já o desenvolvedor, apenas
se preocupará com aquilo que será específico, pois a responsabilidade por
essa parte foi delegada a ele.
2.2 Herança
A principal característica da herança é permitir a reutilização de um código.
É possível que uma classe herde outra classe. Nesse caso, a herdeira –
também conhecida como subclasse ou classe filha – recebe todas as
características (desde que não sejam privadas) da classe base – também
comumente chamada de superclasse, classe antecessora, classe mãe ou
classe pai. Assim, todos os atributos e métodos não privados contidos na
superclasse são acessíveis pela classe filha.
Ao se implementar uma subclasse, além de herdar as características de
uma superclasse, você poderá especializar métodos da classe ancestral,
além de especificar novas operações e atributos, para refinar, substituir ou
estender as funcionalidades da superclasse. Portanto, como uma subclasse
estende a superclasse (pois ela possui as características da classe mãe,
além de outras particulares criadas para ela mesma), a classe filha é
sempre maior do que a classe mãe.
Atenção! De acordo com a hierarquia de classes, é necessário saber que
há uma superclasse chamada Object. Portanto, qualquer classe
implementada em Java, implicitamente, herda as características dessa
classe, pois a classe Object é a superclasse de todas as classes
implementadas em Java. Todas as classes implementadas em Java são,
portanto, subclasses da Object.
2.3 Polimorfismo
Esta é a capacidade de um método ter muitas formas. Neste primeiro
momento, basta sabermos que em uma determinada classe podem existir
dois métodos com mesmo nome e assinaturas diferentes, o que caracteriza
polimorfismo de sobrecarga. Outro caso de polimorfismo é o de
sobrescrita, que consiste em um método existente na superclasse com um
determinado comportamento e o mesmo método, com a mesma assinatura,
na subclasse com um comportamento distinto do método da superclasse.
Nossa aula 6 tratará o polimorfismo com maiores detalhes.
2.4 Encapsulamento
Encapsulamento é a técnica de encapsular, ou seja, esconder os detalhes.
Você dirige um carro, acelera, passa marchas, freia, faz todas as operações
necessárias para guiar o carro da maneira correta. Mas, muito
provavelmente, você não saberá de todos os detalhes do funcionamento do
carro, a não ser que você seja mecânico ou então uma pessoa super
curiosa. Do mesmo jeito você assiste televisão, sabe as funções do controle
remoto, mas não precisa saber dos detalhes eletrônicos responsáveis pelo
funcionamento da sua TV e do seu controle remoto.
A idéia é a mesma quando falamos em POO para sistemas de informação.
Você verá que muitos programadores são usuários clientes de classes
anteriormente criadas por outros programadores, projetistas ou
desenvolvedores. Isso acontecerá conosco, quando começarmos a
programar efetivamente. Você verá que também utilizaremos as classes
definidas pela Sun. Nós, programadores usuários, precisaremos apenas
saber a finalidade de uma determinada classe ou método, mas não
precisamos saber os detalhes de como foram implementados. Não será
necessário verificar o código fonte para conhecer o comportamento dos
métodos, apenas analisarmos se atende ou não à nossa necessidade. Será
preciso apenas entender a finalidade da classe ou do método em si.
Nossa aula 5 tratará apenas sobre encapsulamento. Portanto, veremos este
assunto com maiores detalhes.
3 Características Java semelhantes à linguagem C
Como já foi dito em aulas anteriores, a linguagem Java derivou da
linguagem C/C++. Portanto, sua sintaxe é bem parecida com a dessas
linguagens, inclusive na utilização de chaves {} para abrir e fechar
escopos, na utilização do main como nome de método principal, na forma
de fazer os comentários, na utilização dos tipos primitivos comuns como
int, char, float, double, long, entre outras coisas, que veremos à
medida em que formos avançando no conteúdo.
4 Primeiro programa Java
4.1 Programa desenvolvido em Editor de Textos e JDK
Vamos começar então a, efetivamente, rodar programas simples em Java.
Assim, poderemos aprender na prática. Esse primeiro exemplo será em um
editor de texto simples, o bloco de notas. Colocaremos os passos
necessários para os programas Java serem executados via bloco de notas e
prompt de comando. É importante entendermos bem como funciona a
compilação e execução de classes Java, por isso veremos este exemplo.
Depois, faremos o mesmo exemplo utilizando o IDE Eclipse. Para facilitar,
todos os outros exemplos também serão executados diretamente no IDE
eclipse.
A primeira coisa a fazer é dedicar uma pasta em seu computador para os
projetos que serão desenvolvidos. Em meu computador, usei a pasta C:\
Projetos\Java, mas você poderá criar o caminho que desejar! Ali serão
colocados todos os projetos que utilizaremos nessas aulas, como por
exemplo, o nosso primeiro programa: HelloWorld.
Em um editor de texto qualquer, utilizei o bloco de notas (mas você poderá
usar o que desejar), digite o programa abaixo.
public class HelloWorld {
public static void main(String[] args) {System.out.println("Meu primeiro programa Java");
}}
Salve o arquivo acima com o nome “HelloWorld.java” na pasta designada
para o seu projeto. Depois disso, execute o prompt e acesse a pasta em que
seu projeto foi salvo, no meu caso “cd c:\Projetos\Java\HelloWorld”. Ao
chegar lá, digite a seguinte instrução: “javac HelloWorld.java”. Repare que
as letras maiúsculas e minúsculas fazem diferença, pois, como vimos, Java é
case-sensitive.
Com o comando javac, a classe HelloWorld foi compilada. Nesse momento o
compilador criou o arquivo HelloWorld.class na mesma pasta onde está
localizada o arquivo HelloWorld.java. O arquivo HelloWorld.class é o arquivo
HelloWorld.java em formato binário. O interpretador da máquina virtual Java
vai ler esse arquivo.class e executar os comandos a partir desse arquivo
binário.
Para ver o resultado da execução dessa classe digite: “java HelloWorld”.
Assim, você verá a frase “Meu primeiro programa Java” na tela do prompt.
4.2 Programa desenvolvido no Eclipse
Agora, desenvolveremos o mesmo programa acima utilizando as facilidades
da IDE Eclipse. Ao utilizarmos o Eclipse, devemos primeiramente definir um
workspace. Ou seja, um diretório (uma pasta) raiz para os projetos a serem
enxergados pela ferramenta. Para facilitar, podemos usar o diretório padrão
indicado pelo próprio eclipse.
Após a abertura do Eclipse, veremos a tela abaixo.
Para começar, definiremos um projeto. Para isso, basta irmos em File ->
New -> Java Project.
Agora colocaremos o nome do projeto. Outros detalhes como, por exemplo,
localização padrão, JRE a ser utilizada, podemos deixar os que o Eclipse
indicar – default.
Depois disso, podemos pressionar o botão Finish e o projeto ficará
disponível para nós no “Package Explorer”.
Repare que o projeto possui um pacote padrão chamado “src” – source;
fonte –, a partir desse pacote default iniciaremos os nossos pacotes. O
Eclipse só trabalha com classes que possui pacote. Para isso, podemos
selecionar este pacote src, ir em File -> New -> Package e criar um novo
pacote com o nome “primeiroprograma”.
Agora, finalmente, criaremos a nossa primeira classe no Eclipse. Para isso
basta clicarmos com o botão direito do mouse sobre o pacote gerado e
selecionarmos New -> Class, conforme a figura abaixo.
Depois disso, basta preenchermos o nome da classe e, neste início,
podemos deixar os outros dados padrão.
Após apertarmos o botão Finish, veremos a classe disponível para a gente.
Agora sim, podemos colocar o método main na classe HelloWorld.
Atenção, repare que o Eclipse exige o nome do pacote.
Depois que escrevemos o programa, temos que compilar e executar. O
botão “Run” compila e executa o programa, na qual conseguimos
verificar o resultado no console do eclipse localizado na parte inferior da
janela. O console do Eclipse, em seu computador, deverá estar com o fundo
branco e letras pretas. Mas, você pode personalizá-lo de acordo com a sua
preferência. O da figura abaixo, por exemplo, está foi preparado para
apresentar a saída do programa com o fundo preto e letras brancas.
Utilizando os exemplos de código acima, podemos aprender alguns
conceitos e definições importantes utilizadas na linguagem Java. Agora,
vamos analisar com calma cada parte do programa.
Na primeira parte do código vemos:
public class HelloWorld {..}
A palavra class, neste contexto, indica que estamos declarando uma
classe. O nome que escolhemos para esta classe é HelloWorld. Por
padronização, ao declararmos uma classe em Java, colocamos a primeira
letra em maiúscula e as seguintes em minúsculas. Caso o nome seja
composto, como no caso de HelloWorld, a primeira letra da palavra
subseqüente também começa com maiúscula e o restante das letras ficam
minúsculas (conforme padronização Sun).
Já public é um especificador (modificador de visibilidade). Dizemos que
a classe é pública quando ela pode ser acessada/utilizada normalmente por
outra classe. Um arquivo Java deve possuir, obrigatoriamente, uma classe
pública com o mesmo nome do arquivo. Atenção! Um arquivo não pode
possuir duas classes públicas, o mais comum é utilizar um arquivo Java para
cada classe. Por enquanto, guarde esta parte da especificação do primeiro
programa (public class) como o início da declaração de uma classe.
Todas as classes serão declaradas assim por enquanto.
As chaves {} são delimitadoras de escopo. No código, repare que depois da
declaração da classe existe uma chave aberta { para identificar o conteúdo
da classe e, na última linha, uma chave fechada } para indicar que aquela
classe termina ali.
public static void main(String[] args) {System.out.println("Meu primeiro programa Java");
}
Dentro do escopo da classe existe o método main. Este é o método
principal das classes Java. Esse método indica o início da aplicação. Ao
digitar o comando “java HelloWorld”, no caso de executar o programa Java
da maneira tradicional, ou pressionar o botão Run, quando rodamos um
programa pelo eclipse, a máquina virtual procura o método main e, a partir
daí, começa a execução do programa.
Esse public, definido em main, é um qualificador do método, que indica
que este é acessível externamente à própria classe, ou seja, pode ser
enxergado de qualquer lugar da aplicação. Por enquanto, declararemos
nossos métodos como public.
O método também é estático, static. Esta é outra palavra reservada, que
indica que o método deve ser utilizado com um método da classe e não do
objeto. Também veremos essa atribuição mais à frente com mais detalhes.
Em princípio, basta saber que este é um método de classe e que métodos
de classe podem ser executados sem a necessidade da criação de um
objeto.
Todo método deve possuir um tipo de retorno, veremos mais detalhes sobre
esses retornos nas próximas aulas. Por enquanto, saiba que o tipo de
retorno definido para o método main foi void (vazio). Métodos void não
retornam nenhum valor.
O método main ainda possui um parâmetro de nome args, que significa
argumentos. A variável args é um array de objetos do tipo String, uma
classe fundamental para linguagem Java. Basicamente, por meio da classe
String podemos escrever e manipular mensagens utilizadas no programa.
É através do parâmetro (String args[]) que o método main
(conseqüentemente, todo o programa) recebe argumentos da linha de
comando. Veja que esse parâmetro é um array de Strings, inicializado
quando os argumentos são passados por meio da invocação do nome do
programa na linha de comando do sistema.
Portanto a assinatura desse método recebe como parâmetros um array de
strings, nesse exemplo, denominado “args”. Por meio desse array é que são
passados os parâmetros para dentro do programa Java.
Por fim, dentro do método main, delimitado pelas chaves, temos um
conteúdo da execução – System.out.println() – que, neste
primeiro momento, vamos entender como sendo uma maneira de
apresentarmos mensagens no prompt de saída. Então, quando quisermos
apresentar mensagens, basta colocá-las entre aspas dentro dos parênteses.
Se não desejar utilizar as aspas, você também poderia colocar a mensagem
em um objeto da classe String e, posteriormente, passá-lo como parâmetro.
Veremos esse tipo de procedimento nas próximas alunas.
Abaixo, você encontrará um vídeo com outro exemplo de programa simples
em Java, utilizando apenas os conceitos estudados até agora.
VÍDEO CD - AULA 3 – VÍDEO 1 – PRIMEIRO PROGRAMA 2
Resumo da aula
Nesta aula, você percebeu que preparamos um programa utilizando uma
classe pública, de nome “HelloWorld”. Além disso, o método utilizado foi o
main, que também foi definido como public e continha um retorno do
tipo void. Por fim, utilizamos o System.out.println(), que contém
uma instrução para escrever, na saída padrão, a String passada como
parâmetro para o método println, ou seja, a frase: "Meu primeiro
programa Java". Lembre-se: o nome do arquivo fonte deve ser o mesmo
nome da definição do public class com a extenção “.java”.
Atividade
1. Defina quais são os conceitos essenciais de OO.
2. Qual o seu entendimento sobre os termos os termos Abstração,
Polimorfismo, Herança e Encapsulamento?
3. Qual o seu conceito para Abstração, Herança, Polimorfismo e
Encapsulamento?
4. Após visualizar o primeiro programa em Java, cite algumas
características do Java que são semelhantes à linguagem C.
5. Elabore um programa simples, capaz de exibir o seu nome na tela.
6. Elabore um programa Java capaz de imprimir na tela o seu endereço
completo, em múltiplas linhas.
7. Salve o programa abaixo em um arquivo de nome AloMundo.java
public class AloMundo {
public static void main(String[] args) {System.out.println("Ola Mundo");
}}
a. Retire a instrução public da primeira linha e observe a mensagem de erro
que aparece ao executar o programa.
b. Retire a instrução static da linha de declaração do método e observe a
mensagem de erro que aparece ao executar o programa.
c. Mude o nome da classe para HelloWorld e observe a mensagem de erro
que aparecerá ao compilar o programa.
d. Troque o nome do método de main para principal e observe a mensagem
de erro que aparece ao executar o programa.
e. Coloque outras instruções System.out.println a ponto de obter a seguinte
formatação de saída:
---------------
Ola Mundo
---------------
f. Tente montar a seguinte saída:
-------------------
| Meu Primeiro |
| Programa Java |
-------------------
A instrução System.out.println indica que a linha será quebrada ao final da
instrução. Se retirarmos o ln do final da instrução - System.out.print –,
poderemos exibir mensagens sem quebras de linha.
g. Utilize essa instrução ao colocar os | na saída acima.
AULA 4 – CLASSES E OBJETOS
Para um melhor entendimento do paradigma OO, faz-se necessário o
correto aprendizado de alguns conceitos fundamentais, entre eles, os de
classes e objetos. Entendendo estes conceitos você terá um melhor
aproveitamento dos recursos de orientação a objetos, pois eles são vitais
para qualquer sistema construído no paradigma OO e estão presentes em
todas as linguagens OO. Classes e objetos estão refletidos em projetos de
sistemas (onde serão posteriormente implementados) e são os grandes
responsáveis pela disseminação do uso da OO, bem como pelo crescimento
do tamanho e das responsabilidades dos sistemas de informação existentes
hoje
Ao final desta aula você será capaz de compreender conceitos mais
específicos sobre as classes, os pacotes, os objetos, as palavras
reservadas (new, null, this e final), além da classe String e
da API – Java.
Abertura
Como já vimos na aula 01, a linguagem Java é orientada a objetos,
isto é, todos os elementos do mundo real são modelados como
objetos. Os objetos são criados a partir das classes. Uma classe define
a estrutura de um objeto. Uma classe especifica todos os atributos
(propriedades) e métodos (comportamento) que um objeto daquela
classe pode ter. Na Figura 2.1, a seguir, tem-se uma classe automóvel
e três objetos que foram gerados a partir dessa classe automóvel. A
classe automóvel tem como atributos: cor, ano, modelo. Os métodos
são: desligar, acelerar, e ligar. A Figura 2.2 apresenta o objeto gerado
por essa classe, que tem a cor laranja, ano 2007, modelo Punto. Uma
classe é um protótipo que define os atributos e os métodos comuns a
todos os objetos de um determinado tipo e da própria classe, com a
finalidade de servir como molde para a criação de objetos. Dessa
forma, uma classe é um template, um modelo para gerar objetos. Em
uma classe, os atributos representam o estado do objeto, os métodos
e a sua interação com o mundo externo. Um objeto é gerado
(instanciado) por meio de uma classe.
Texto base
1 Classes
A classe é o elemento essencial na programação orientada a objetos. Todos
os elementos do mundo real são modelados como objetos, esses objetos
são criados a partir das classes. Portanto, a estrutura definida na classe
serve como base para a criação de objetos.
Uma classe pode ser encarada como um modelo. Em seu livro Introdução à
Programação Orientada a Objetos usando Java, Rafael Santos, afirma:
“Classes são estruturas das linguagens de programação orientadas a
objetos para conter, para determinado modelo, os dados que devem
ser representados e as operações que devem ser efetuadas com estes
dados. Cada classe deve ter um nome que seja facilmente associável
ao modelo que a classe representa”.
(SANTOS, 2003, p.14)
Exemplificando uma abstração do mundo real, vemos que uma classe
poderia ser, por exemplo, Pessoa, Automóvel, Conta, Livro ou qualquer
outra coisa, dependendo do domínio do problema a ser abordado pelo
programador.
Suponhamos que você seja contratado para a criação de um sistema de
informação em um banco comercial. O banco atenderá clientes no varejo e
fará todas as operações executadas em um banco normal, terá clientes
possuidores de conta corrente, conta poupança, conta investimento, poderá
fazer saques, solicitar emissão de extrato bancário, realizar pagamentos
entre outras operações bancárias comuns. Na especificação acima, de
forma bem simplificada, já podemos identificar algumas classes como, por
exemplo: Cliente, ContaCorrente, ContaPoupanca, ContaInvestimento, etc.
1.1 Nome da classe
Utilizaremos o exemplo acima para esclarecer sobre a escolha dos nomes
das classes. Como já foi dito anteriormente, a linguagem Java possui um
padrão proposto pela Sun para nomes de classes e seguido por todos os
programadores, a primeira letra do nome da classe deve ser escrita com
letra maiúscula seguida pelas demais minúsculas. Caso o nome seja
composto, então a primeira letra do outro nome também deverá conter
letra maiúscula seguida das outras minúsculas.
É importante ressaltar que não se recomenda definir o nome de
identificadores separado por underline ou sublinhado (_), embora isso não
seja proibido. Isso é apenas uma recomendação de boas práticas de
programação, procura-se assim estimular a utilização de padrões, tendo
como finalidade a maior clareza e facilidade de entendimento de código. A
exceção à utilização de sublinhados está na utilização de nomes de
constantes (falaremos de constantes com detalhes quando estivermos
estudando os atributos, na próxima aula).
É importante saber que o compilador rejeita nomes de classes que possuem
acentos e também nomes de classes iniciados por números. Os números
podem ser usados, desde que precedidos por outros caracteres como, por
exemplo, letras, sublinhado ou $. Caracteres especiais como %, #, @ são
considerados como identificadores ilegais, logo devem ser evitados sob
pena de ter a compilação negada pela máquina virtual.
1.2 Criando uma classe
Para definir uma classe, usa-se a seguinte sintaxe: o qualificador de
acesso, a declaração “class”, o nome a classe, as chaves (para a
implementação de todos os métodos e atributos necessários na criação dos
objetos relacionados com essa classe).
A sintaxe da declaração de uma classe, então, é:
QualificadorDeAcesso class NomeDaClasse
O qualificador de acesso determina o acesso a essa classe por outras
classes (por exemplo: public – usado no seu primeiro programa Java). A
palavra class informa que essa declaração refere-se a uma classe e, por
fim, o NomeDaClasse.
Voltando ao nosso exemplo do banco comercial, podemos dizer que o
cliente é essencial para o domínio do problema. Qualquer instituição de
vendas, seja de produtos ou serviços, precisa de clientes. Assim,
identificamos a necessidade de uma classe Cliente. Entretanto, analisando
o domínio do problema, percebemos também a necessidade das classes:
ContaCorrente, ContaPoupança e ContaInvestimento, que são os
serviços oferecidos pelo banco aos seus clientes. Assim, poderíamos
escrever as classes Cliente, ContaCorrente, ContaPoupanca,
ContaInvestimento como se segue:
public class Cliente {
//Conteúdo da classe Cliente
}
Como vimos, a classe pública Cliente deverá estar declarada em um
arquivo de mesmo nome: Cliente.java.
public class ContaCorrente {
//Conteúdo da classe ContaCorrente
}
Classe pública ContaCorrente, declarada em um arquivo
ContaCorrente.java.
public class ContaPoupanca {
//Conteúdo da classe ContaPoupanca
}
Classe ContaPoupanca, declarada em um arquivo ContaPoupanca.java.
public class ContaInvestimento {
//Conteúdo da classe ContaInvestimento
}
Classe ContaInvestimento declarada em um arquivo
ContaInvestimento.java.
O Java possui uma sintaxe similar ao C. Como você já pôde notar, além da
utilização das chaves para delimitar blocos de comandos, podemos também
utilizar duas barras // para efetuar comentários. Além da utilização das
duas barras, o comentário em Java também pode ser feito usando barra
asterisco /* para iniciar e asterisco barra */ para finalizar.
/**
Comentário para
documentação
*/
public class Cliente {
/* Um comentário qualquer
na classe Cliente
*/
}
Outra forma importante de comentário na linguagem Java é a barra e dois
asteriscos /** e para finalizar asterisco barra */. Esse tipo de comentário
é utilizado para documentação da classe. O aplicativo javadoc – existente no
JDK – usa esses comentários e cria uma documentação para a classe nos
moldes da API Java – vista mais a frente na seção 3.10.
Lembre-se que toda classe que definimos na linguagem Java descende, em
última instância, da classe Object. Mesmo que você não defina uma
superclasse – assunto que veremos na aula sobre Herança (aula 7) – ao
declarar a sua classe, por padrão, ela descenderá da classe Object. Na hora
de projetar as classes, é importante termos em mente como funcionará a
hierarquia de classes, pois devemos visar sempre o mínimo acoplamento
entre classes e reutilização de códigos.
2 Pacotes
O crescimento dos sistemas de informação, o aumento da sua
complexidade e a abrangência da sua responsabilidade, gera a necessidade
de maior organização. Assim, faz-se necessário organizar as classes é
classificá-las em pacotes (packages). Esses pacotes agrupam as classes
por assuntos relacionados.
Fisicamente esses pacotes são diretórios ou pastas do sistema operacional
que indicam o caminho da localização de uma determinada classe. Essa
organização facilita o entendimento no momento de se planejar e de se
reutilizar as classes.
Por padrão, os pacotes devem ser definidos com letras minúsculas,
separados por pontos. Na prática, cada ponto representa um sub-nível na
hierarquia de pastas do sistema operacional.
3 Objetos
Um objeto é gerado (instanciado) por meio de uma classe. Portanto, pode-se
dizer que o objeto é a instância da classe. Se a classe é o modelo, o objeto
é a parte física, construída na memória do computador e acessível
por meio de uma referência. Uma classe, por si só (em regra), não é
capaz de receber valores em seus atributos e nem executar seus métodos.
Isso deve ser feito através dos objetos, que são criados por meio da palavra
reservada new.
Por exemplo: se definirmos uma classe Cliente, como visto na seção
anterior, então cada cliente será um objeto diferente, o cliente João será um
objeto, o cliente Pedro será outro objeto e assim por diante. Acontecerá
assim também com os objetos das classes ContaCorrente,
ContaInvestimento e ContaPoupanca, a conta corrente do cliente João é um
objeto, a conta corrente do cliente Pedro é outro objeto. Portanto, a classe
serve de molde, um modelo, para a criação de vários objetos. Não há limite
para número de objetos de uma classe, o limite é a capacidade de memória
da máquina. Segue abaixo, uma representação ilustrativa do funcionamento
de um objeto na memória.
8 Palavras reservadas new, null, this e final
8.1 new
A palavra reservada new é aquela responsável por criar efetivamente o
objeto na memória. Para criar um objeto, inicialmente, você deve declarar a
variável do tipo de referência e depois utilizar a palavra new para dizer à
máquina virtual que você quer utilizar as operações e atributos daquela
classe no objeto. Assim, você usará a referência declarada anteriormente
para manipular o objeto durante o programa.
Devemos ter a certeza de que uma referência sempre aponta para um
objeto criado na memória. Caso contrário, ocorrerá erro de execução, pois a
referência não terá o objeto correspondente para manipular. Vamos
observar um programa com a utilização da palavra reservada new para
criar objetos e referenciá-los.
Analisando o código acima, vemos que a primeira linha indica o pacote na
qual a classe está localizada. Depois, a segunda linha diz que estamos
importando a classe Date, na qual faz parte do pacote java.util, para
ser utilizada em nossa classe.
Esse é um detalhe importante! Anteriormente, vimos que as classes podem
ser definidas pelo próprio programador, mas também podemos utilizar
classes já definidas por outros profissionais ou organizações (as APIs). Nesse
caso, estamos usando uma classe previamente existente, a classe Date.
Na sua programação, para utilizar uma classe anteriormente definida (ou
API), é necessário utilizar a instrução import, seguido do
“nome.do.pacote.NomeClasse” Assim, você avisa ao compilador quais
são as classes pré-existentes que você esta utilizando e que serão
incorporadas à sua própria classe. Ao final desta aula veremos mais
detalhes sobre as APIs.
Após esse procedimento, vem a declaração da classe e do método main,
que já conhecemos. Entretanto, agora cabem mais alguns detalhes sobre a
implementação do método main.
Veja que, primeiramente, declaramos uma referência para a classe Date,
com o nome dataAtual. A referência dataAtual, da maneira como foi
concebida, inicializou valendo null, ou seja, é uma referência nula, pois
não existe um objeto na memória associado a ela. O objeto é criado
somente depois, na outra linha, quando também é associado à referência.
Finalizando a análise do nosso exemplo, vemos que o método main
encerra com a utilização do método println para leitura da referência
dataAtual. Assim, a data é apresentada na tela de saída.
Na figura abaixo, você poderá observar o resultado da execução do
programa acima.
Agora, acompanhe um outro exemplo de programa com entrada de dados.
VÍDEO CD - AULA 4 – VÍDEO 1 – IMPORTA CLASSE – ENTRADA DE
DADOS
8.2 null
A palavra reservada null indica que uma referência não tem um objeto
para manipular, ou seja, a referência aponta para uma área de memória
nula. Dessa forma, não é possível manipular um objeto porque ele
simplesmente não existe na memória.
Você, como programador, pode fazer sempre a operação de perguntar à
referência se esse objeto existe ou não na memória por meio da estrutura
de decisão if. Muitas vezes as referências são criadas em outros métodos
a depender da dinâmica do sistema, assim, para nos resguardarmos de
eventuais erros de execução utilizamos o trecho de código if
referencia == null ou if referencia != null, caso o
objeto não exista na memória, podemos criar um novo objeto do tipo
declarado para a referência e, assim, passamos a manipular os métodos,
atributos e objeto.
Agora,vamos agora acompanhar um programa que utiliza a palavra null
para um melhor entendimento.
Repare que, neste código, fizemos uso da estrutura de decisão if para
verificar se a referência está diferente de null, ou seja, para verificar se
existe um objeto na memória associada a ela. Nesse caso, como
inicializamos a referência na linha anterior, o resultado da verificação, do
jeito que foi projetado, sempre será verdadeiro e o código descrito no bloco
else nunca será executado. Na figura abaixo você poderá observar o
resultado da execução do programa acima.
Abaixo, você encontrará uma vídeo-aula com mais um exemplo de
programa utilizando os comandos new e null.
VÍDEO CD - AULA 4 – VÍDEO 2 –NEWNULL
8.3 final
A palavra final na declaração de uma classe indica que a classe não
poderá ser estendida. Estamos restringindo a descendência de uma classe
ao declará-la como final. Assim, podemos dizer que a herança não ocorrerá
em classes do tipo “final”, ou seja, ela não terá classes filhas ou subclasses,
ficando como última implementação daquela linhagem de classes. A palavra
final também pode ser utilizada em atributos e métodos. Veremos na
próxima aula mais detalhes sobre a incidência deste conceito.
9 A Classe String
A classe String é uma classe especial na linguagem Java, que não precisa
ser inicializada (não precisa da palavra new); apenas a declaração da
referência já é suficiente para sua utilização. Essa classe permite que
possamos colocar um texto dentro de uma referência, servindo para
passarmos mensagens, escrevermos uma seqüência de caracteres, entre
outras opções. É uma classe essencial para qualquer sistema escrito em
Java. Veremos o exemplo de um programa utilizando a classe String.
Observe que, no código acima, a variável str já é preenchida com um
conteúdo de várias seqüências de caracteres. Para juntar mais de uma
seqüência de caracteres em uma única variável do tipo String, utilizamos o
mecanismo da concatenação. Consiste em juntar seqüências com o
operador +. Assim, juntamos strings variadas ao “somarmos” umas com as
outras. Verifiquemos o exemplo abaixo.
.
.
String str1 = “João ”;
String str2 = “Manoel”;
String str3 = str1 + str2;
.
.
O conteúdo da variável str3 será: “João Manoel”.
Repare também que não foi necessário utilizar a palavra new. Essa é uma
característica bastante particular da classe String, quando você quiser
utilizar uma string basta declarar a referência e colocar o conteúdo. Na hora
de apresentar o conteúdo na tela você pode passar a referência da classe
String, no caso str, como parâmetro do método println, como o
exemplo acima. Porém, você também pode colocar a própria seqüência,
como feita nos programas anteriores. Veja abaixo o resultado da execução
deste nosso último exemplo.
Em Java existem caracteres especiais chamados de literais para
manipulação de Strings. Como visto no programa anterior, podemos utilizar
caracteres \n para quebra de linha, entre outros. Abaixo, segue uma tabela com os literais
String.
Literal Significado
\b Backspace (retrocesso)
\t Tabulação horizontal tab
\n Quebra de linha
\f Quebra de página
\r Retorno de carro
\” Aspas
\’ Apóstrofo
\\ Barra Invertida
A classe String é muito rica e permite várias outras operações. Por se tratar
de um array de caracteres é possível percorrer seu conteúdo; dado um
índice, por exemplo, é pode-se encontrar um determinado caractere.
Logo abaixo, você poderá acompanhar outro exemplo de programa em Java,
utilizando a classe String, os comandos println e os literais para a
manipulação de strings.
VÍDEO CD - AULA 4 – VÍDEO 3 – STRING
10 API – Java
Application Programming Interface – API é o conjunto de classes
documentadas disponibilizadas pela Sun (Oracle). Todo desenvolvedor Java
usa as APIs Java para saber qual classe, método, rotina, atributo deve ser
implementado para suprir uma necessidade específica. Um exemplo de
API que usamos nesta aula foi a classe Date, incluída no primeiro
exemplo de programa desta aula!
As APIs estão organizadas por classes, com explicações sobre a finalidade
dessas classes e dos seus métodos. Assim, quando precisar utilizar uma
classe/método para uma resolver determinado problema e não tiver certeza
do resultado esperado para aquela classe/método, vá até a sua API e
verifique. Para verificar as especificações das APIs Java acesse:
http://download-llnw.oracle.com/javase/6/docs/api/.
Logo abaixo, você poderá acompanhar dois vídeos que envolvem a
utilização de APIs. No primeiro, você acompanhará como podem ser
encontradas as classes utilizadas em Java. Nesse caso específico,
pesquisaremos e utilizaremos a classe Calendar, com toda a sua
documentação (classes, atributos, etc). No segundo vídeo, você
acompanhará a utilização desta classe no escopo do programa.
VIDEO CD – AULA 4 – VIDEO 4 - CLASSE CALENDAR – PARTE 1
Agora, acompanhe a elaboração do código utilizando a classe Calendar.
VIDEO CD – AULA 4 – VIDEO 5 - CLASSE CALENDAR – PARTE 2
Resumo da aula
Nesta aula você foi capaz de compreender que uma linguagem orientada a
objetos trabalha com o conceito de classes (unidade básica para o
funcionamento de um sistema baseado no paradigma OO). Além disso, você
viu que os atributos são variáveis de classes e que por meio deles são
alocados valores para serem manejados em sistemas de informações. Você
também verificou os conceitos de abstração, herança, poliformismo e
encapsulamento e conseguiu executar o seu primeiro programa em Java,
analisando e compreendendo cada parte do programa. Por fim, você viu que
os pacotes agrupam as classes por assuntos relacionados, que o objeto é a
instância da classe e estudou as palavras reservadas new, null, this e
final, além de alguns exemplos prático utilizando a Classe String.
Atividade
1. O que são as classes em linguagem Java?
2. O que são os objetos em linguagem Java?
3. Defina para que servem a palavras new e this.
4. Elabore uma classe com o nome MinhaPrimeiraClasse.
5. Na classe acima crie um atributo de nome data do tipo java.util.Date
e inicia-o com o valor null.
6. Utilize o atributo definido acima para imprimir na tela a data atual.
Não esqueça de instanciá-lo.
7. Defina uma variável do tipo String dentro do método main na classe
que você está manipulando. O nome dessa variável deve ser
msgData e o seu valor deve ser “Data atual: ”.
8. Concatene a variável que você acabou de criar com o objeto data
criado anteriormente para observar a data atual impressa na tela.
9. Escreva uma classe que leia dois números de ponto flutuante
digitados pelo usuário e depois imprima a média. Veja, logo abaixo,
um vídeo com este exercício resolvido! (VÍDEO CD – Aula 04 -
video 6 - exercício resolvido 09 valores def)
10.A partir do exemplo demonstrado no vídeo do item 9 desta aula,
sobre a classe string, elabore um programa que retorne o mesmo
cálculo, porém, declarando uma String capaz de imprimir o seu
conteúdo. Veja, logo abaixo, um vídeo com este exercício
resolvido! (VÍDEO CD – Aula 04 - video 7 - exercício resolvido
10 - string)
11.Crie uma classe com o nome Somar. Crie duas variáveis com os
nomes valor1 e valor2 do tipo inteiro e faça-as receber os valores 5 e
3 respectivamente. Depois, imprima o resultado da soma na tela.
12.Crie uma classe com o nome Subtrair. Crie duas variáveis com os
nomes valor1 e valor2 do tipo inteiro e faça-as receber os valores 23
e 9 respectivamente. Depois, imprima o resultado da subtração na
tela.
13.Crie uma classe com o nome Multiplicar. Crie três variáveis com os
nomes valor1, valor2 e valor3 do tipo float e faça-as receber os
valores 3, 5 e 6 respectivamente. Depois, imprima o resultado da
multiplicação na tela.
14.Crie uma classe como nome Dividir. Crie duas variáveis com os
nomes valor1 e valor2 do tipo float e faça-as receber os valores 4500
e 50 respectivamente. Depois, imprima o resultado da divisão na tela.
15.Utilize o vídeo XXX como exemplo e substitua os valores fixos nos
exercícios 9 a 12 por valores escolhidos livremente pelos usuários.
AULA 6 - Encapsulamento
O conceito de encapsulamento não se restringe ao uso do paradigma
orientado a objetos, está presente na vida cotidiana de todos. Em exemplos
anteriores utilizamos o carro que dirigimos sem saber dos detalhes
mecânicos que o fazem funcionar e do controle remoto da TV que obedece
aos nossos comandos, atende aos nossos propósitos e não precisamos
aprender como eles funcionam internamente. É assim com várias outras
coisas do nosso dia a dia, não precisamos saber dos detalhes de
funcionamento dos telefones celulares, das instalações elétricas de nossas
residências ou dos sistemas internos de um computador quando queremos
apenas utilizar um editor de texto ou a internet. Podemos usar tudo isso
sem nos preocupar como foram feitos, bastando apenas utilizar as funções
disponíveis para a gente enquanto pessoas comuns.
Ao final desta aula você será capaz de compreender o sentido de
encapsulamento no âmbito da Programação Orientada a Objetos,
compreendendo o encapsulamento na reutilização de classese a
importância das APIs nesses procedimento. Ao final da aula você
encontrará um exemplo de programa que utiliza o encapsulamento.
Abertura
A técnica de esconder das pessoas, os detalhes sobre o funcionamento das
coisas, em geral, é bastante útil. Imagine o trabalho que seria para os
cidadãos comuns, terem que saber sobre o completo funcionamento de
todos os objetos utilizados diariamente, quanto tempo desperdiçaríamos! E
o pior, quanta coisa errada poderíamos fazer! Além disso, o fator psicológico
que age sobre o ser humano implica na dificuldade de utilização de certos
objetos. Quanto mais difícil for usar um objeto qualquer, menos utilizável
será aquele objeto para a maioria das pessoas. Logo, quanto mais fácil e
padronizada a forma de utilização, mais as pessoas serão propensas a usar
tal objeto ou funcionalidade.
O sucesso de um determinado mecanismo usado constantemente consiste,
entre outras coisas, na facilidade de operação. Um exemplo disso são os
próprios sistemas operacionais dos computadores atuais. Os mais antigos
devem se lembrar o quanto era custoso mexer no computador quando o
sistema operacional mais utilizado era o MS-DOS. Era tedioso, tínhamos que
decorar vários comandos, a tela era pouco amigável e era muito penoso
quando queríamos fazer um trabalho que hoje é considerado simples. Hoje,
o Windows encapsula várias tarefas trabalhosas do MS-DOS, com um
simples clique! Não precisamos nos preocupar como foi implementada tal
funcionalidade. O próprio Linux só se tornou mais difundido entre os
usuários de computadores comuns depois que adicionou um GUI (Graphic
User Interface) amigável para a maioria das pessoas. Os mais nostálgicos
gostam dos comandos e das tarefas feitas via console, mas a maioria das
pessoas prefere interfaces gráficas mais fáceis de usar, sem preocupar de
como foram feitas ou concebidas.
Obviamente, algumas pessoas gostam de mexer e saber dos detalhes de
funcionamento dos mecanismos, vemos crianças que abrem os brinquedos
para saberem de onde vem o barulho ou a luz que eles emitem, pessoas
que gostam de abrir aparelhos mais sofisticados e observarem o
funcionamento, ou programadores que abrem códigos de programas já
escritos com o intuito de aprender, inserir ou consertar alguma
funcionalidade, mas, certamente esse não é o comportamento da maioria
das pessoas!
MS DOS 1.25 for Commodore B Series Computer with 8088 co-processor.
Fonte: http://www.vintagecomputer.net/PACS.cfm
Texto base
Encapsulamento
Ao definirmos padrões de uso, interfaces amigáveis de entrada e saída,
abstração dos detalhes, para que a maioria das pessoas utilize as
facilidades dos produtos e permaneçam preocupadas apenas com os
resultados esperados, não precisando nos aprofundar no detalhamento
responsável pelo funcionamento de cada serviço. Assim, estamos utilizando
o encapsulamento, em prol da facilidade de operacionalização e
conseqüentemente da disseminação dos objetos e produtos na qual
estamos trabalhando.
1 Encapsulamento na POO
Encapsular, no âmbito da Programação Orientada a Objetos, significa
ocultar os detalhes de implementação, deixando poucas interfaces de
entrada, apenas as extremamente necessárias, para os usuários de uma
determinada funcionalidade.
Ao criarmos uma classe temos que pensar em seu funcionamento. Temos
que observar se essa classe a ser escrita realmente atenderá seu propósito,
e mais, temos de nos preocupar em escrever a classe o mais enxuta
possível, obviamente, atendendo à finalidade proposta e imaginando como
a tornar reutilizável. Classes genéricas são aquelas que atingem ao seu
propósito, sendo utilizada nas mais diversas situações. Esse é um dos
grandes benefícios da programação orientada a objetos.
Como fica o encapsulamento na reutilização de classes?
Simples, ao criarmos uma classe sem nos preocupar com o
encapsulamento, deixando uma classe de fora acessar diretamente seus
atributos, uma pequena manutenção que fizermos na classe poderá ter
grandes impactos nos sistemas que a utilizam. Isso é bem prejudicial para
todos; tanto para o responsável pela manutenção, que precisa daquela
classe funcionando de outra maneira, como para os clientes que já a utiliza
de uma determinada forma que, agora, necessitaria ser modificada.
Se, em vez disso, o programador inicial tivesse planejado uma forma de
acessar mais eficiente, de forma encapsulada, ele poderia fazer a
manutenção na classe de modo a não interferir no seu funcionamento e
ainda atender a eventuais novos propósitos demandados pela manutenção.
Encapsulamento na API
Ao utilizar uma classe, o programador não necessita saber como ela foi
projetada, para saber se ela atende ou não a sua necessidade. Também não
é necessário saber quais foram os mecanismos utilizados pelo
desenvolvedor dessa classe. Basta entender a finalidade da classe e, é
claro, do método a ser utilizado. Essas informações próprio programador
consegue via API http://download-llnw.oracle.com/javase/6/docs/api/ –
conceito visto na nossa aula 3 – onde estão expostas todas as
documentações das classes, com seus respectivos métodos, atributos,
formas de entrada de informação e resultados a se esperar.
Já vimos que a utilização da API é de suma importância para os
programadores, principalmente os iniciantes. Ela é uma conveniente fonte
de informações, pois possui conhecimentos essenciais a qualquer
desenvolvedor. É fundamental ressaltar que todos os grandes fornecedores,
quando disponibilizam pacotes com classes, publicam APIs sobre suas
classes. Veja, logo abaixo, um exemplo da API da classe String. Todas as
imagens estão disponíveis em
http://download.oracle.com/javase/7/docs/api/.
Fonte: http://download.oracle.com/javase/7/docs/api/.
Tendo a classe String como exemplo, vamos reparar como funciona a API.
Repare na parte esquerda da tela. Nela, vemos todos os pacotes (na parte
de cima) e as classes (na parte de baixo). Ao selecionarmos uma classe,
vemos no frame principal a hierarquia e a definição da classe. Na figura
abaixo, podemos ver uma breve explicação sobre a classe e, logo abaixo, a
definição dos campos.
Fonte: http://download.oracle.com/javase/7/docs/api/.
A parte mais importante para o nosso assunto vem agora. Podemos ver na
próxima figura uma importante descrição sobre os métodos pertencentes à
classe String. Primeiramente podemos observar a quantidade de
informações sobre os métodos construtores. Veja que, baseado no conceito
de encapsulamento, temos a explicação dos métodos, o que eles fazem e
quais os propósitos, mas, não precisamos saber como esses métodos foram
implementados.
Fonte: http://download.oracle.com/javase/7/docs/api/.
Um detalhe a ser observado sobre os métodos acima é o fato de alguns
possuírem, como primeira informação, no espaço reservado à explicação, a
palavra Deprecated. Isso significa que o método em questão está
depreciado e não deve mais ser utilizado, ele fica neste estado para manter
a compatibilidade com as versões anteriores e não ocorrer problemas com
os sistemas já existentes que utilizam esses métodos.
Continuando nossa análise sobre o encapsulamento, observemos os outros
métodos da classe String.
Fonte: http://download.oracle.com/javase/7/docs/api/.
Veja que, na API, estão as descrições e objetivos dos métodos da classe
String e você, enquanto programador, não precisa ver o código dos métodos
para saber seu objetivo e conseqüentemente o resultado a ser alcançado
com sua utilização.
2 Programando com encapsulamento
Você deve ter percebido que já utilizamos encapsulamento nos programas
que fizemos nas aulas anteriores. Essa questão não foi levantada antes pois
nosso enfoque era outro!
Agora, vamos analisar no programa sugerido abaixo, como podemos
identificar o encapsulamento. Primeiramente, vamos definir uma classe
Calculadora; repare que nela constarão apenas quatro métodos, atendendo
rigorosamente o propósito da classe. Seus métodos simularão uma
calculadora simples com as quatro operações básicas de soma, subtração,
multiplicação e divisão. Cada um dos métodos receberá dois parâmetros do
tipo double e retornarão um valor como resultado da execução da
operação. Acompanhe:
Nas próximas imagens você irá conferir a implementação da classe
Principal. Essa classe é a responsável pela efetivação das operações. Por
meio dela, somos capazes de decidir qual operação iremos executar.
Primeiramente, vimos no método main a declaração de três variáveis do
tipo double e uma do tipo String; três delas – duas do tipo double e
a do tipo String – são preenchidas com valores digitados pelo usuário.
Para fazer isso, pedimos ajuda à classe Scanner, que serve, entre outras
coisas, para ler dados vindos dos usuários.
Depois foram feitas verificações simples para conferir se os valores foram
preenchidos de forma válida. Para isso, os métodos validaNumero(double,
String) e validaOperador(String) foram confeccionados. Neste segundo
método pedimos ajuda a classe HashSet, que implementa a interface Set,
para podermos validar o operador com segurança. Estes assuntos serão
vistos no decorrer do curso, mais especificamente quando falarmos de
interfaces e coleções.
Na seqüência é chamado um método que, baseado no operador passado
como parâmetro, determina a operação a ser chamada por meio do objeto
da classe Calculadora. Esse é o ponto do encapsulamento que devemos nos
atentar.
Quando utilizamos a classe Calculadora não é nossa obrigação saber como
foram implementados os métodos soma, subtração, multiplicação e divisão,
bastar sabermos que eles fazem a operação, e dão o resultado esperado.
Se, por acaso, resolvermos mudar a implementação desses métodos em
Calculadora, muito provavelmente não necessitaremos fazer manutenções
na classe Principal.
Para a execução da classe Principal devemos pressionar o botão Run do
eclipse e preencher as variáveis – dois números e o sinal indicador da
operação – à medida que o programa vai pedindo.
Segue a tela de resultado para conferência.
A seguir, veja mais um exemplo de encapsulamento.
VÍDEO CD - Aula 06 - video 1 - encapsulamento
Resumo da aula
Nesta aula você foi capaz de compreender como funciona o
encapsulamento no âmbito da programação orientada a objetos. Você
percebeu que encapsular significa ocultar os detalhes de implementação,
deixando poucas interfaces de entrada, apenas as extremamente
necessárias, para os usuários de uma determinada funcionalidade. Desta
forma, planejado um acesso encapsulado, pode-se efetuar a manutenção na
classe, de modo a não interferir no seu funcionamento e ainda atender a
eventuais novos propósitos demandados pela manutenção. Por fim, você
percebeu que, na API, estão as descrições e objetivos dos métodos das
classes que possibilitam o encapsulamento.
Atividade
1. Defina o que é encapsulamento.
2. Crie uma classe em Java que contenha os atributos nome e idade
com modificadores de acesso private, crie métodos de acesso com
modificadores public, depois, crie um método main que mostre os
valores que estão nos atributos. Lembre-se que o método main é
estático, assim os métodos só serão acessíveis se também forem
estáticos ou se um objeto dessa classe for criado no método main.
3. Desenvolva uma classe que possua um método que incremente um
valor de um atributo private inteiro e outro método que decremente o
valor do mesmo atributo, depois faça outra classe que chame e
execute a primeira classe pelo método main.
4. Crie uma classe com dois atributos private, que deverão ser
preenchidos por meio dos métodos de acesso públicos com os
argumentos passados no momento da execução da classe e, depois,
crie um método também público responsável por trocar os valores
dos atributos. Depois, crie uma classe principal com o método main
para chamar os métodos da primeira classe.
5. Crie uma classe que calcule a bonificação de final de ano sobre o
salário bruto de um funcionário de acordo com sua função na
empresa segundo a tabela abaixo:
a. Funcionário nível médio: 20%
b. Funcionário nível superior: 35 %
c. Gerente: 50%
d. Diretor: 70%
Crie métodos para encapsular de forma que o cálculo da
bonificação, assim como o preenchimento dos demais atributos
sejam transparentes para o usuário da classe. Veja, logo abaixo,
um vídeo com este exercício resolvido! VÍDEO CD – Aula 06
- video 2 - exercicio resolvido - bonificacao
6. Crie uma classe com um método que calcule o valor recebido depois
da incidência de 15% de imposto sobre o valor bruto. O valor bruto
deverá ser passado no momento da execução por meio de outra
classe que possui o método main.
7. Defina uma classe de nome CalcularQuadrado com um método que
receba um valor como parâmetro e retorne o quadrado desse
número. Depois, outra classe deverá chamar, por meio do método
main, um objeto da classe CalcularQuadrado e apresentar o resultado
da execução do método na tela.
8. Crie uma classe semelhante à classe CalcularQuadrado, mas com a
diferença de calcular qualquer potência. Essa classe deverá possuir
dois atributos na qual um significa um número inteiro qualquer e o
segundo é a potência. Ex: caso passemos como argumentos os
números 2 e 3, o número 2 deve ser elevado a terceira potência (23),
obtendo como resultado o número 8. Essa operação deverá ser
chamada de outra classe principal possuidora do método main. Dica:
Para resolver este exercício utilize o método pow da classe
java.lang.Math. Veja o funcionamento do método na api Java
http://download.oracle.com/javase/6/docs/api/java/lang/Math.html#po
w(double,%20double).
9. Crie uma classe que possua um método responsável por calcular o
salário líquido de um funcionário. Para calcular o salário líquido é
necessário descontar 15% caso o salário seja entre R$ 1501,00 e R$
2500,00, 22% caso o salário seja entre R$ 2501,00 e R$ 3500,00 e
27,5% caso o salário seja mais de R$ 3500,00. O valor bruto deve ser
passado como parâmetro para a função. Os valores referentes aos
salários bruto e líquido deverão ser armazenados em atributos
privados, e deverão ser exibidos na tela por meio de métodos de
acesso públicos. Esses valores deverão ser chamados por meio de
outra classe com o método main.
10.Para caracterizar bem o encapsulamento, modifique o método
responsável por calcular o salário liquido da classe acima para
acrescentar os seguintes descontos:
a. Quando a alíquota a ser cobrada for de 15%, aplicar desconto
de R$ 120,00 no valor cobrado do imposto.
b. Quando a alíquota a ser cobrada for de 22%, aplicar desconto
de R$ 280,00 no valor cobrado do imposto.
c. Quando a alíquota a ser cobrada for de 27,5%, aplicar desconto
de R$ 550,00 no valor cobrado do imposto.
Repare que sua classe responsável por calcular o valor do imposto foi
modificada, mas as classes clientes – aquelas que fazem chamadas a
métodos dessa classe – não sofreram impactos.
AULA 7 - HERANÇA E POLIMORFISMO
Os conceitos de herança e polimorfismo são essenciais para o
desenvolvimento de códigos mais robustos. Com eles podemos re(utilizar)
códigos já definidos em outras classes superiores, economizando tempo e
recursos computacionais.
Ao final desta aula você será capaz de compreender a aplicar os
conceitos relacionados a herança e polimorfismo, observando o uso
da palavra extends. Você também acompanhará a utilização de
polimorfismos de sobrescrita, de sobrecarga e outros tipos de
encapsulamento e polimorfismo; além dos conceitos de assinatura
do método.
Abertura
VIDEO CD – AULA 7 – VÍDEO 1 - HERANÇA
Texto base
1 Herança
Ocorre quando uma classe herda as características de outra classe. Como
visto anteriormente, sabemos que, em última instância, toda classe em Java
herda características da superclasse Object. Mas, podemos explicitamente,
ao projetar nossa classe, fazê-la herdar características de outra qualquer.
Isso é possível desde que a classe genérica, aquela na qual iremos herdar
as características, não tenha sido declarada como final.
Quando herdamos uma classe estamos criando um relacionamento de
especialização, ou seja, estamos estendendo essa classe. Pense nesse
conceito da seguinte forma: uma classe já existente e uma outra classe que,
ao ser construída, irá especializar a primeira, pois irá estender sua
utilização. Essa nova classe será mais específica e possuirá novas
funcionalidades, por isso ela será mais restrita, seu campo de atuação será
mais específico, mais especializado, pois está estendendo as
funcionalidades de sua antecessora.
O mecanismo da herança é caracterizado pela pergunta: “é um...?” Por
exemplo: em uma hierarquia de classes onde a superclasse é Animal e a
subclasse é um Cachorro, podemos perguntar: Cachorro é um Animal? Se a
resposta é positiva então cabe a herança. Se a pergunta fosse: Carro é um
Animal? Essa pergunta não faz sentido, logo, a subclasse carro não pode
descender de uma superclasse Animal. Dessa forma, atestamos que Carro é
um Automóvel e não um Animal. À medida que formos subindo a hierarquia,
não chegaremos a uma classe comum entre Carro e Cachorro.
Da mesma forma, na linguagem Java não existe herança múltipla. Um Carro
é um Automóvel, não é um Animal e um Automóvel ao mesmo tempo.
Embora possamos simular essa situação com a utilização de interfaces –
assunto que veremos na próxima aula – isso não significa dizer que em Java
teremos herança múltipla se utilizarmos interfaces. São propósitos
diferentes.
A herança é um mecanismo muito útil e bastante utilizado na programação
orientada a objetos. Por meio dela conseguimos reutilizar muitos códigos já
definidos em classes superiores, com isso ganhamos tempo, economizamos
recursos e conseguimos mais robustez no nosso código. Um código-fonte já
utilizado significa, em tese, que já foi testado e seu funcionamento atinge o
propósito para o qual foi projetado. Além disso, o código fica concentrado
em um só lugar, ou seja, caso precise sofrer alguma manutenção, podemos
ir direto nele e reestruturar apenas essa parte. Não é necessário percorrer
toda a aplicação para localizar os trechos que trabalham em discrepância
com o que é desejado e nem mudar a implementação em vários lugares.
Não existe limite no número de extensões em uma hierarquia de classes.
Assim, podemos estender classes o quanto quisermos e o quanto for útil
para a aplicação. Mas, devemos nos atentar sempre para o entendimento.
Se algo que fizermos começar a ficar complicado demais para nós ou para
outros programadores, o melhor a fazer é reestruturar ou, melhor dizendo,
efetuar um refactor.
Para entender melhor como funciona o mecanismo da herança, suponha
que você tenha sido contratado para informatizar uma empresa, desde o
sistema de pessoal – RH – até seu sistema fim, que pode, por exemplo,
serviço de vendas de algum produto.
Observando as particularidades do domínio do problema, podemos nos
concentrar em prováveis classes, como a Funcionário, quando tratarmos
do módulo de RH e a Cliente quando o enfoque for o módulo de vendas dos
produtos. Teoricamente, o funcionário não tem nada a ver com cliente, um
trabalha dentro da empresa, tem salário, férias, controle de ponto, entre
outras particularidades, próprias de funcionários. O cliente, por sua vez,
compra, paga, exige nota fiscal, ou seja, tem atribuições diferentes. No
entanto, ao analisarmos de modo mais profundo perceberemos que os dois
podem possuir características comuns! Vamos lá: os dois possuem nome,
data de nascimento, endereço, telefone, número de CPF, carteira de
identidade, entre outras informações compartilhadas.
Portanto, seria muito ruim, do ponto de vista do desenvolvimento, que o
sistema possuísse dois lugares distintos para armazenar informações
semelhantes, poderíamos ter duplicação de dados, uma vez que um
funcionário também poderia ser um cliente, além de várias outras
desvantagens, como o overhead, por exemplo.
Para resolver o problema exposto, podemos utilizar o mecanismo de
herança, disponível na programação orientada a objetos. Primeiramente
colocaríamos as informações comuns entre funcionário e cliente em uma
classe de nome Pessoa. Depois, especializaríamos essa classe com as
informações particulares dos tipos mais específicos Funcionario e Cliente.
Assim, trataríamos da classe genérica, Pessoa, com todas as características
– atributos e métodos – comuns de qualquer pessoa, manipularíamos a
classe Funcionario com todas as suas particularidades e depois
cuidaríamos da classe Cliente com as informações restritas ao âmbito de
atuação de um cliente. Para fazer uma herança em Java basta usar a
palavra reservada extends, como no exemplo abaixo.
class Animal {
...
}
class Cachorro extends Animal {
...
}
Depois de toda essa nossa discussão teórica, vamos agora ver, no código
Java, como ficaria a implementação dessa hierarquia de classes definidas
anteriormente: Pessoa, Funcionario e Cliente. Segue, primeiramente a
definição da classe Pessoa, que possui apenas dois atributos e seus
respectivos métodos de acesso get e set.
Agora a classe Funcionario, que também possui apenas dois atributos e
seus respectivos métodos de acesso get e set. Observe o uso da palavra
extends para indicar a que Funcionario herda de Pessoa.
Nesse momento, observemos a classe Cliente, que também herda de
Pessoa, mas diferentemente das outras possui quatro atributos.
Agora, você pode verificar a classe Compra, responsável por fazer as
chamadas às outras classes e a conseqüente dinâmica dos acontecimentos.
É interessante observamos algumas particularidades dessa classe.
Primeiramente, nós tivemos que criar um objeto de compra no método
main Isso acontece porque o main é um método estático, ou seja, executa
mesmo sem o objeto da classe existir. Entretanto, os outros métodos não
são estáticos, logo, o main não pode chamar diretamente esses métodos,
pelo fato de eles só poderem ser executados se for por meio de uma
referência a um objeto da classe Compra.
Repare que, depois, fizemos os métodos responsáveis pelo preenchimento
das informações nos objetos das classes Funcionario e Cliente. Outra
novidade é o uso da classe Calendar no método getDate(). Essa classe
é bem mais completa para a manipulação de datas do que a própria classe
Date, por isso, ela foi utilizada para fixar a data de início das férias do
funcionário.
Pronto, agora podemos pressionar o botão Run do eclipse e ver o resultado
da execução do programa. Segue a tela de resultado.
Logo abaixo, você encontrará outro exemplo de programa que utiliza os
conceitos de herança. Acompanhe com atenção o desenvolvimento deste
código.
VIDEO CD - Aula 07 - video 2 - heranca
2 Polimorfismo
Na nossa aula 3 vimos em uma pequena definição de polimorfismo que
consiste na capacidade do método possuir vaiadas formas. Um método é
polimórfico quando o seu comportamento varia de acordo com uma
determinada situação.
Neste momento vamos nos concentrar nos tipos mais usuais de
polimorfismo utilizados em métodos. Nesse caso, podemos ver o
polimorfismo de sobrecarga (overload) e o polimorfismo de sobrescrita
(override), ou apenas polimorfismo. Na linguagem Object Pascal é
necessário que você, enquanto programador, especifique para o compilador
quando está usando polimorfismo de sobrecarga e de sobrescrita, já na
linguagem Java não é necessária qualquer especificação em relação a isso.
Antes de definirmos os tipos citados de polimorfismo vamos fixar um
conceito simples, que é a assinatura do método. Podemos dizer que
assinatura é aquilo que identifica o método. Não poderão existir dois
métodos iguais, de mesma assinatura, em uma mesma classe. A assinatura
do método consiste no nome do referido método e dos seus parâmetros,
mais precisamente, na ordem dos tipos dos parâmetros definidos no
método.
Um ponto importante a ser lembrado é que o tipo de retorno do método não
faz parte da assinatura, logo, se você mudar apenas o tipo de retorno em
métodos com a mesma assinatura, o método será considerado igual pelo
compilador Java.
Assinatura do método: nomeMetodo (lista_de_parametros);
2.1 Polimorfismo de Sobrescrita
A sobrescrita de métodos consiste em reescrever, na subclasse, um método
existente em uma superclasse. Deve-se manter a mesma assinatura do
método da classe pai para que haja a sobrescrita. Nesse caso, o método foi
reescrito ou sobrescrito na classe filha e, quando esta for acionada, o
método a ser invocado será esse novo método reescrito. Se a instância for a
da superclasse, o comportamento a ser executado será, obviamente, o da
classe pai.
Um ponto importante a ser levado em consideração é que o modificador de
acesso de um método definido na superclasse não poderá sofrer redução de
acessibilidade, assim, se um método criado na superclasse for definido
como público, não poderá ser redefinido na subclasse como protegido ou
privado.
2.2 Polimorfismo de sobrecarga
Polimorfismo de sobrecarga consiste em existir, na classe, mais de um
método com o mesmo nome, mas com assinaturas diferentes. É importante
ressaltar que apenas os tipos são levados em consideração na lista de
parâmetros para a assinatura, assim, os nomes dos parâmetros são
ignorados na assinatura do método. Por exemplo: suponhamos que ao
definir uma classe você tenha métodos como os definidos no exemplo
abaixo.
somar();
somar(int x);
somar(double y);
somar(double x, double y);
somar(int x, double y);
somar(int x, int y);
somar(double x, int y);
Repare que, embora os métodos possuam o mesmo nome, suas assinaturas
são diferentes, pois os tipos dos parâmetros estão em disposições
diferentes em todos os métodos especificados acima. Independente dos
nomes dos parâmetros, o que realmente importa nesse caso é a ordem em
que estão dispostos os tipos dos parâmetros.
2.3 Outros tipos de encapsulamento e polimorfismo
Um outro tipo de encapsulamento é o chamado Universal de Inclusão, o
qual permite que o programador declare um objeto do tipo superclasse e
instancie uma subclasse. Assim, a referência é do tipo genérico e o objeto
na memória é do tipo específico. Se levarmos em consideração o nosso
exemplo inicial desta aula, sobre as classes Cachorro e Animal, teremos:
class Animal {
...
}
class Cachorro extends Animal {
...
}
Animal cachorro = new Cachorro();
Outra forma de polimorfismo considerado por alguns autores é o Ad-Hoc de
coerção, bem simples. Ocorre quando a linguagem faz conversões
implicitamente, como atribuir um valor inteiro a uma variável float, por
exemplo.
int a = 10;
float b = a;
Existem ainda alguns outros tipos de polimorfismo que veremos no
momento oportuno, são eles: o polimorfismo paramétrico que veremos
quando chegarmos em coleções de objetos e também o polimorfismo em
tipos abstratos que observaremos no capítulo referente a interfaces e
classes abstratas.
Agora, vamos verificar os códigos referentes ao polimorfismo. No nosso
caso vamos utilizar a classe Animal, Gato, Cachorro e UsoPolimorfismo
para podermos observar a utilização desse mecanismo.
A primeira classe que vamos desenvolver é a classe Animal, que possui um
único método denominado alimentar.
Agora, vamos observar a classe Cachorro com uma implementação
simples, caracterizando a sobrescrita.
A seguir, verificaremos a classe Gato com dois métodos alimentar. Um
com a mesma assinatura da superclasse e outro com um parâmetro do tipo
Boolean para caracterizar a sobrecarga.
Um detalhe a ser observado, tanto na classe Gato como na classe Cachorro,
é a utilização da instrução super. Isso significa que a classe herdeira pode
pedir à superclasse que execute o método definido na superclasse para
depois continuar a execução do seu método. Se não desejarmos que essa
execução ocorra, basta não colocarmos a instrução super.
Vamos, agora observar a classe UsoPolimorfismo.
A classe UsoPolimorfismo possui o método main para a execução do
programa. Repare que declaramos as referências com o tipo Animal e as
instanciamos com suas respectivas classes. Ao chamar o método
alimentar, os métodos correspondentes nas classes foram executados. O
ponto importante a ser comentado é o fato da chamada aos métodos
alimentar(Boolean). Esses métodos não puderam ser chamados
diretamente pela referência gato porque eles não foram definidos na classe
Animal e a referência declarada foi da classe Animal. Essa referência não
enxerga o método definido na classe Gato, a não ser que façamos um cast
para a classe Gato.
O cast pode ser entendido como uma adequação para a referência se
comportar da forma do objeto que está instanciado na memória. Com o uso
desse mecanismo estamos dizendo ao interpretador que embora a
referência seja da superclasse o objeto na qual ela aponta é de um tipo
mais especializado e assim podemos utilizar o cast para que a máquina
virtual possa executar as operações desse objeto mais especializado já
existente na memória.
Veja abaixo a tela de resultado de execução desse programa.
A seguir, você encontrará um vídeo com outro exemplo de polimorfismo.
Acompanhe atentamente o desenvolvimento do código e a execução do
programa.
VIDEO CD - Aula 07 - video 3 - polimorfismo
Resumo da aula
Nesta aula, você foi capaz de compreender conceitos de herança e
polimorfismo. Herança ocorre quando uma classe herda as características
de outra classe; nesse caso, estamos criando um relacionamento de
especialização, estamos estendendo uma classe. O polimorfismo consiste na
capacidade do método possuir vaiadas formas. Podemos ver o polimorfismo
de sobrecarga (overload) e o polimorfismo de sobrescrita (override). Outro
conceito importante visto foi o de assinatura do método. Agora chegou a
sua vez de praticar esses conceitos!
Atividade
1. A partir da leitura dessa aula, defina qual o seu conceito de herança?
2. Defina qual o conceito de polimorfismo de sobrecarga?
3. O que é polimorfismo de sobrescrita?
4. Defina uma hierarquia de classes que definam as classes Veiculo,
Carro e Caminhão, na qual existam os métodos ligarMotor(),
ligarMotor(Boolean ligar) e desligarMotor(). Esses métodos devem ser
definidos na classe Veículo e sobrescritos nas subclasses com
exceção do método ligarMotor(Boolean ligar), que deve ter
implementação apenas em Veículo. Veja, logo abaixo, um vídeo
com este exercício resolvido! VIDEO CD - Aula 07 - video 4 -
exercicio resolvido - veículo
5. Crie duas classes com os nomes A e B. Crie os atributos x e y private
do tipo inteiro na classe A. Crie métodos de acesso a esses atributos
com modificadores protected. Faça a classe B herdar de A. Crie os
métodos acessar e obter com modificadores públicos na classe B,
cujas implementações devem conter a chamada aos métodos de
acesso definidos na classe A. Assim, setX(int) e setY(int) deve estar
no conteúdo do método acessar(int) e getX() e getY() deve estar no
conteúdo de obter(). Faça uma terceira classe que contenha o
método main, instancie um objeto da classe B, chame o método
acessar, depois imprima o resultado obtido pela execução do método
obter.
6. Crie a classe Pessoa com os atributos nome do tipo String e idade do
tipo inteiro, ambos com modificadores públicos. Crie métodos de
acesso (get e set) públicos para esses atributos. Crie uma classe
Funcionário que herde de Pessoa. Inclua o atributo salário do tipo
double e modificador private com seus respectivos métodos de
acesso públicos. Crie um atributo privado do tipo String com o nome
cargo e métodos de acesso públicos para esse atributo. Crie uma
terceira classe e no método main instancie um objeto da classe
Funcionário e preencha os atributos nome, idade, cargo e salário por
meio dos métodos de acesso set. Depois imprima o valor dos
atributos na tela chamando os métodos get.
7. Crie uma classe Gerente faça-a herdar de Funcionário. Reescreva o
método setSalario(double) na classe Gerente para o atributo salario
receber o valor que vem do parâmetro acrescido de 25%. Depois, na
classe que instancia um objeto da classe Funcionário, instancie um
objeto da classe Gerente para preencher e posteriormente mostrar os
valores recuperados na tela. Repare que o método setSalario
funciona de forma diferente nas duas classes, embora tenham o
mesmo nome e estão localizados na mesma hierarquia.
8. Utilize os mesmos moldes do exercício anterior e crie a classe Diretor
herdando de Gerente. Reescreva o método setSalario(double) para o
valor do salário ser acrescido de 50%.
9. Crie um método público chamado exibeVantagens() na classe
Funcionário. Coloque as seguintes mensagens no conteúdo deste
método:
- “Auxílio Transporte”;
- “Auxílio Alimentação”;
- “Plano de Saúde”;
Depois disso, crie o mesmo método na classe Gerente e coloque as
seguintes mensagens:
- “Décimo quarto salário”;
- “Telefone Celular Empresarial”;
Continuando, crie o mesmo método na classe Diretor e coloque as
mensagens:
- “Décimo quinto salário”;
- “Participação nos lucros”;
Utilize a instrução super.exibirVantagens() na implementação do
método exibirVantagens() nas classes Gerente e Diretor para você
observar a chamada dos métodos das classes superiores. Por
exemplo, quando chamar o método por meio do objeto da classe
Diretor, as mensagens a serem mostradas são:
- “Auxílio Transporte”;
- “Auxílio Alimentação”;
- “Plano de Saúde”;
- “Décimo quarto salário”;
- “Telefone Celular Empresarial”;
- “Décimo quinto salário”;
- “Participação nos lucros”;
Na classe possuidora do método main que instancia um objeto da
classe Funcionário e Gerente, faça-o instanciar também um objeto da
classe Diretor e depois faça os objetos dessas classes chamarem os
métodos exibirVantagens().
10.Crie um método público chamado exibeVantagens(Boolean
permitirVisualizacao) na classe Diretor. Repare que a existência do
parâmetro diferencia este novo método do criado anteriormente.
Utilize este parâmetro para controlar se o usuário pode ou não ver as
outras vantagens de diretor que você quiser colocar. Não esqueça de
chamar este novo método na classe que possui o método main.
11. Faça um teste na classe que possui o método main e declare um
objeto do tipo Funcionário e instancie com a classe Gerente. Faça-o
exibir na tela as mensagens do método exibirVantagens(). Repita o
teste com a classe Diretor em vez de Gerente. Explique o que
aconteceu nos dois casos.
AULA 8 - CLASSES ABSTRATAS E INTERFACES
Na aula anterior, vimos o mecanismo de herança, que muito facilita a vida
dos desenvolvedores de sistemas baseados em linguagens orientadas a
objetos. Tudo o que vimos lá, foi baseado em classes concretas, ou seja,
classes que permitem serem instanciadas. No entanto, há situações onde
não é de inteira responsabilidade do projetista o “como fazer”, e sim, “o que
fazer”. Nesses casos, o projetista sabe que algo deve ser feito, porém,
existem várias possibilidades de isso ser feito. Nesse caso, teremos a
implementação das Classes Abstratas e as Interfaces.
Ao final desta aula você será capaz de compreender a função das
Classes Abstratas (implementadas através do modificador
abstract) e das Interfaces, que correspondem a uma maneira
genérica de modelar um comportamento.
Texto base
Vamos iniciar esta aula com um exemplo de operação de transferência
bancária. Nesse caso, o projetista deve elaborar um procedimento capaz de
retirar determinada quantia de um lugar e colocá-la em outro lugar; mas
isso pode ser feito entre duas contas correntes, entre conta corrente e conta
poupança, entre conta poupança e fundo de investimento, etc. Portanto, a
correta implementação depende muito de como o processo foi concebido.
E não é só isso, existem inúmeras situações em que o projetista de software
deixa a responsabilidade para o programador porque, dependendo do
módulo em questão, a operação deverá funcionar de um jeito ou de outro.
Nesses casos, temos um artifício bastante poderoso para remediar tal
situação. São os tipos abstratos de dados, as classes abstratas e as
interfaces.
1 Classes Abstratas
Classes abstratas são tipos de dados em que o projetista já estipula uma
regra de tratamento a ser feito em determinadas situações, mas deixa ao
programador a função de fazer aquele tratamento específico funcionar da
maneira com a qual foi concebido. Isso não impede que outro programador
faça aquela mesma operação funcionar de outra maneira, totalmente
diferente, quando se tratar de outro domínio do problema.
Para utilizar a forma abstrata, devemos utilizar o modificador abstract
na declaração do método, como descrito abaixo.
public abstract <tipo_de_retorno> <nome_metodo>();
Suponha que o retorno do método seja boolean e o nome do método seja
executar();
public abstract boolean executar();
Ao se declarar um método como abstract, é fundamental, inicialmente,
declarar também a classe como abstrata. O compilador do Java exige isso.
Assim, se houver um ou mais métodos abstratos na classe, esta, por sua
vez, também se torna abstrata. Isso acontece para evitar que esta classe
seja um tipo concreto. Assim, não há possibilidade de algum programador
querer instanciar a classe e, posteriormente, fazer uma chamada ao método
abstrato.
Outra ação importante ocorre quando você ou outro programador desejar
criar uma subclasse dessa classe abstrata. O método abstrato deve ser
obrigatoriamente implementado, mesmo que não aconteça nada no
método, ele deve possuir as chaves de abrir e fechar { } para que seu
escopo seja delimitado.
public boolean executar(){
}
Nada impede que as classes abstratas contenham métodos que não sejam
abstratos (com implementações concretas), que podem ser utilizados pelas
classes dependentes ou por ela própria. O método concreto da classe
abstrata também pode fazer chamadas aos métodos abstratos sem prejuízo
algum para o correto funcionamento do programa. Isso ocorre porque o
compilador obrigará a subclasse a implementar o método abstrato, assim,
na hora que esse método for chamado a execução desviará para o método
da subclasse.
A classe abstrata é uma classe normal com a única restrição de não poder
ser instanciada, mas pode possuir atributos, bem como métodos estáticos,
desde que estes não sejam abstratos. Veremos agora um programa com
utilização de classe abstrata. Repare que a classe possui métodos abstratos
e um concreto.
A seguir, perceba a classe Carro que estende da classe abstrata
denominada Motor. Repare que há um atributo de classe chamado Estado
ao qual é atribuído um valor verdadeiro quando o motor é ligado e um valor
negativo quando o motor é desligado. Existe também a implementação dos
métodos definidos na classe abstrata Motor. Veja que estes métodos estão
marcados com a anotação @override, significando que são métodos
sobrescritos.
Agora, segue a classe Motocicleta, que também herda a classe abstrata
Motor.
Na classe Motocicleta também existe o atributo Estado, que não tem
nada a ver com o atributo Estado da classe Carro. As classes Carro e
Motocicleta têm em comum com a classe abstrata Motor as declarações
dos métodos, mas as implementações das classes são diferentes.
Na classe UsoAbstrato é mostrada a utilização da classe abstrata Motor.
O método imprimirDadosMotor(Motor) apenas chama os métodos
abstratos, independente de qual seja a classe concreta instanciada na
memória.
O método imprimirEstado(Motor) exige um cast para o tipo
correspondente na memória para que imprima o resultado do método
estadoMotor(), isso porque este método não faz parte da interface
Motor. Veja abaixo o resultado da execução deste programa. Perceba que,
como não sabemos qual será a classe concreta a chegar ao parâmetro do
método, utilizamos a instrução instanceof que pergunta ao objeto se
ele é de determinada classe retornando “verdadeiro” ou “falso” para
satisfazer a condição.
Assista mais uma vídeo-aula que contém exemplos de exercícios de classe
abstrata.
VIDEO CD - Aula 08 - video 1 – abstrato
Agora, uma adaptação do vídeo de polimorfismo da aula 07 para ser
utilizado com classe abstrata.
VÍDEO CD - Aula 08 - video 2 – PeriodoAbstrato
2 Interfaces
Interface corresponde a uma maneira genérica de modelar um
comportamento, você pode usar deste artifício para especificar algo que
deve acontecer de uma maneira esperada. A interface determina o que
fazer, por meio dos métodos declarados em seu escopo. Ao projetar uma
interface, o programador prevê a estrutura para resolver um determinado
problema, ditando quais são os passos que devem ser seguidos para que a
solução aconteça. Interfaces são úteis em diversas situações. Sua utilização
é quase (para não dizer totalmente) obrigatória quando utilizamos objetos
distribuídos, web-services, entre outras funcionalidades presentes no dia a
dia do desenvolvimento de sistemas.
O sistema se torna mais flexível com o uso de interfaces. Pode-se dizer que
Interfaces são como classes totalmente abstratas. Isso porque a abstração
dos métodos da interface é feita de maneira implícita pelo compilador. Ao
declarar uma interface o programador não precisa especificar o modificador
abstract na declaração de cada método.
Uma interface pode ser estendida como uma classe comum, mas não pode
haver métodos implementados, nem atributos, a não ser que sejam
constantes, com os modificadores static ou final para poderem ser
acessados, sem que haja uma instância e também indicar que não podem
ser modificados. Essa forma de utilização permite que, em muitos sistemas,
sejam feitas bibliotecas de constantes em interfaces. Esse procedimento é
um facilitador, porque essa estrutura força a utilização de apenas esse tipo
de atributo, além de não permitir a existência de métodos implementados.
Outra característica da interface é que todos os seus métodos devem ser
declarados como públicos, assim, a interface atinge seu propósito de
permitir a conexão entre as entidades.
Vimos no capítulo anterior que não existe herança múltipla em Java
(diferentemente de C++, por exemplo), mas as interfaces tornam nossos
programas muito flexíveis, robustos e sem a confusão conceitual de herança
múltipla. Uma classe implementa uma interface, isso quer dizer que uma
classe vai dizer como será executado aquele comportamento previsto na
interface. Quando uma classe implementa uma interface ela tem a
obrigação de codificar todos os métodos previstos naquela interface. Mesmo
que o programador não queira colocar nenhuma implementação, ele deve
declarar o método e abrir e fechar chaves { } para delimitar seu escopo.
Veja como declarar uma interface abaixo no exemplo abaixo.
public interface IExemplo {
}
Agora, veja como declarar uma herança de interface.
public interface IExemplo extends ISuperExemplo {
}
A utilização da interface por uma classe pode ser feita como especificado
abaixo.
public class Classe implements IExemplo {
}
Agora, vamos ver o mesmo exemplo de código acima, porém, com
utilização do mecanismo de interface.
A classe Carro é a mesma do exemplo abstrato acima, com a única
diferença de usar a instrução implements em vez de extends.
A classe Motocicleta também é a mesma do exemplo abstrato acima,
mudando apenas a declaração de extends para implements.
Abaixo, segue a classe UsoInterface.
A classe UsoInterface mostra a utilização da interface Motor. O método
imprimirDadosMotor(Motor) apenas chama os métodos da
interface, independente de qual seja a classe concreta instanciada na
memória. Assim, não é necessário saber se o objeto é Carro ou Motocicleta,
pois será executado o método da classe que é apontada pela referência.
Segue a execução do programa.
Para fazermos uma ligação com a aula anterior, podemos dizer que tudo o
que vimos nesta aula está intimamente ligado com os conceitos de herança
e polimorfismo. Quando definimos o molde, utilizando tanto classe abstrata
quanto interface, e não nos preocupamos com o “como” isso será
implementado, estamos utilizando os conceitos de polimorfismo, sem deixar
de lado a abstração, a herança e o encapsulamento. Com isso, vemos na
prática todos os conceitos da orientação a objetos sendo utilizados em
conjunto.
Com essa aula nós aprendemos a manipular classes abstratas e interfaces.
Abaixo, você encontrará mais um exemplo de programa utilizando esses
conceitos. Observe com atenção!
VIDEO CD - Aula 08 - video 3 – interface
A seguir: adaptação do vídeo de polimorfismo da aula 07 para ser utilizado
com interface – outro exemplo.
VIDEO CD - Aula 08 - video 4 – PeriodoInterface
Resumo da aula
Nesta aula, você foi capaz de compreender que Classes Abstratas são tipos
de dados em que o projetista estipula uma regra de tratamento a ser feito
em determinadas situações, mas deixa ao programador a função de fazer
aquele tratamento específico funcionar da maneira com a qual foi
concebido. A classe abstrata é uma classe normal com a única restrição de
não poder ser instanciada, mas pode possuir atributos, bem como métodos
estáticos, desde que estes não sejam abstratos. Você também
compreendeu que a Interface corresponde a uma maneira genérica de
modelar um comportamento, podendo-se usar deste artifício para
especificar algo que deve acontecer de uma maneira já esperada. Pode-se
dizer que Interfaces são como classes totalmente abstratas. Utilizando esses
artifícios, o sistema se torna mais flexível.
Atividade
1. Defina qual o seu conceito de classe abstrata?
2. Defina qual o seu conceito de interface?
3. Defina uma interface com o nome Jogo. Crie os métodos iniciar(),
jogar() e finalizar().
4. Crie uma classe abstrata com o nome JogoComBola e faça-a
implementar a interface Jogo. Crie um método abstrato denominado
setNomesEquipes(String equipe1, String equipe2).
5. Crie uma classe com o nome Futebol e faça-a herdar da classe
JogoComBola. Repare que, por se tratar de uma classe concreta, você
será obrigado pelo compilador a implementar os métodos da classe
abstrata e também os métodos definidos na interface. Coloque
implementações simples nestes métodos como mensagens, por
exemplo.
6. Para treinar, crie uma classe com o nome Vôlei nos mesmos moldes
da classe Futebol.
7. Crie um mecanismo com interfaces e classes abstratas a respeito de
uma operação de contas bancárias. Veja, logo abaixo, um vídeo
com este exercício resolvido! VIDEO CD - Aula 08 - video 5 -
exercicio resolvido - conta bancária
8. Crie uma classe abstrata com o nome JogoDeCartas e faça-a herdar
da interface Jogo. Crie um método abstrato qtdCartasDistribuidas()
com o retorno do tipo inteiro. Crie outro método abstrato com o nome
numeroParticipantes() também com retorno inteiro.
9. Crie uma classe concreta denominada Truco herdando de
JogoDeCartas. Implemente de maneira simples os métodos da
interface Jogo e da classe abstrata JogoDeCartas.
10.Para treinar, crie uma classe com o nome Buraco nos mesmos moldes
da classe Truco.
11. Crie o método exibirRegras() na interface Jogo e depois implemente-
o nas classes concretas que implementam esta interface.
AULA 9 - COLEÇÕES DE OBJETOS
Quando fizermos uma consulta a um banco de dados, o retorno será uma
lista de elementos na qual teremos que escolher uma das opções. Isso
acontece ao se pesquisar um aluno ou produto pelo nome ou categoria, um
automóvel pela marca, um curso pelo departamento, um livro por assunto,
entre outras opções de pesquisa. Essa lista de elementos é chamada de
coleção de objetos.
Ao final desta aula você será capaz de compreender o conceito de
Polimorfismo Paramétrico e o funcionamento de Arrays. Você
também verá a utilização das interfaces e classes do grupo
Collection e a implementação das interfaces Set e List.
Texto base
Coleções são grupos de objetos que possibilitam o acesso a cada elemento
contido na coleção. Sempre necessitaremos de coleções ao desenvolver
sistemas comerciais. Pode ser uma lista de cursos, turma, alunos, produtos,
itens de qualquer natureza, sempre haverá uma coleção para ser
manipulada.
1 Polimorfismo Paramétrico
A partir da versão 5 do Java, foi adicionado à linguagem o que alguns
autores chamam de polimorfismo paramétrico. O polimorfismo paramétrico
refere-se à capacidade de, por exemplo, definir uma coleção e dizer ao
compilador que aquela coleção é de um tipo determinado.
Suponha que você crie uma coleção e resolva preenchê-la com objetos do
tipo Pessoa. O simples fato de você inserir objetos desse tipo na coleção
não deixará claro ao compilador que aquela é uma lista de tipos Pessoa, no
entanto se você especificar ao compilador que aquela coleção é desse tipo,
ele não deixará outro tipo – objetos de outra classe – fazer parte da lista.
Segue um exemplo básico.
class Pessoa {
}
//Antes do Java 5 a coleção era iniciada assim:
Collection col = new collection ();
col.add(new Pessoa());
//Após Java 5
Collection<Pessoa> col = new collection<Pessoa>();
col.add(new Pessoa());
É importante ressaltar que não ocorre erro caso o programador não tipifique
sua coleção, no entanto com o uso do polimorfismo paramétrico as
restrições ficam mais evidentes o que obriga outros programadores a
tomarem mais cuidado ao utilizar métodos com especificações desse tipo.
2 Arrays
Ainda não falamos de arrays na linguagem Java, nem é nossa pretensão
dizer que array é a solução ao tratarmos de coleção. A saber, arrays são
agrupamentos de objetos, uma lista, cujos elementos são acessíveis por
meio de um índice.
int[] arrayInt = new int[3];
Arrays são tratados como objetos na linguagem Java, mas seus recursos
são bastante limitados, o que praticamente impossibilita a confecção de um
sistema comercial apenas com a utilização de arrays. É muito caro,
computacionalmente falando, fazer as várias manipulações que um sistema
de informações precisa apenas com o uso de arrays. Para começar, seu
tamanho é estático e se quisermos acrescentar mais elementos no array
teremos que criar outro array com novo tamanho, copiar os elementos um
a um do array antigo para o novo para, só então, poder utilizar o novo
array. Imagine se a cada elemento a ser acrescentado tivermos que fazer
tal operação, seria inviável.
No programa abaixo, repare que o array é considerado um objeto em java,
tanto que, para iniciá-lo, usamos o comando new.
Esse programa, na classe ColecaoArray, foi elaborado apenas para
mostrarmos como podemos fazer uma coleção utilizando array. Repare que
Java dá opções de como utilizar a estrutura de repetição for. Pode ser um
tradicional como no array de int, ou um personalizado que retorna o
elemento de acordo com o tipo do array. Repare que o for pode ser
utilizado em qualquer coleção, veremos mais a frente este novo for,
denominado for each (para cada) ou enhanced-for.
Agora, veremos a tela de resultado com as iterações explicitadas acima.
3 Collection
O Java fornece um mecanismo bastante eficiente para o tratamento de
coleções. Consiste na utilização das interfaces e classes do grupo
Collection. Segundo a própria API disponibilizada pela Oracle, que trata da
interface Collection (http://download.oracle.com/javase/7/docs/api/), essa
interface é a principal da hierarquia. Algumas coleções permitem elementos
duplicados e outras não. Algumas são ordenadas e outras desordenadas. No
pacote de classes disponibilizadas pelo JDK não há classe que implementa
diretamente a interface Collection, são disponibilizadas implementações
para interfaces mais específicas como Set e List. A interface Collection é
utilizada tipicamente para a passagem de parâmetros, retornos de métodos,
ou seja, são utilizadas quando o programador desejar que as manipulações
sejam feitas de maneira mais genérica.
Geralmente, as classes que implementam Collection – de maneira indireta
por meio de suas subinterfaces – apresentam dois construtores, um vazio,
sem parâmetros e outro recebendo outra Collection como argumento. Na
realidade a nova coleção copia a antiga, passada como parâmetro no
momento que esta é instanciada.
Algumas coleções possuem restrições quanto aos elementos por ela
manipulados. Por exemplo, algumas implementações proíbem elementos
nulos ou a algum tipo específico. Quando isso ocorre são lançadas algumas
exceções – assunto tratado na nossa próxima aula.
Os métodos disponibilizados pela interface Collection são bastante úteis
para a manipulação de elementos presentes nesses grupos de objetos. As
operações mais utilizadas nas coleções são:
- Adicionar objetos na coleção;
- Remover objeto da coleção;
- Pesquisar um objeto determinado dentro da coleção, por meio de uma chave de pesquisa.
- Iteração, que significa percorrer os objetos de uma coleção.
4 Set
É uma coleção que não pode conter elementos duplicados, e no máximo um
elemento nulo. Algumas implementações da interface Set possuem
restrições nos elementos nela contida. Por exemplo, proíbem o uso de
elementos nulos. Outras podem restringir alguns tipos em seus elementos.
Ao se tentar adicionar algum elemento não permitido, a depender da classe
que implementa Set, pode ocorrer de ser lançada uma exceção ou,
simplesmente, retornar falso.
A seguir, vamos analisar um programa que utiliza a classe HashSet, classe
de coleção que implementa a interface Set. Para este programa, vamos
precisar de 3 classes: Pessoa, ColecaoPessoa e ColecaoSet.
A classe Pessoa possuirá apenas dois atributos, nome e data de
nascimento, e seus respectivos métodos de acesso.
A classe ColecaoPessoa instancia cinco objetos da classe Pessoa e os
coloca em uma coleção HashSet. Lembrando, as classes que implementam
a interface Set não permitem que haja objetos repetidos dentro da coleção,
assim, mesmo forçando a inclusão de dois objetos iguais na coleção –
pessoa2 – veremos, na tela de resultado, que o referido objeto só
aparecerá uma vez.
Por fim, a classe ColecaoSet. Sua única função será instanciar a classe
ColecaoPessoa para obter os objetos pessoa e imprimir suas informações
na tela. Segue a classe Pessoa.
Agora, vamos ver a classe ColecaoPessoa.
Repare que o detalhe destacado nos mostra a inclusão do objeto pessoa2
na coleção. A seguir, vamos conferir a classe ColecaoSet.
Analisando o programa, vemos outra instrução for personalizada da
linguagem Java, na qual basta iniciarmos obtendo o iterator da coleção.
Utilizamos o método hasNext(), que retorna verdadeiro caso ainda tenha
objetos a serem percorridos no iterator e também o next() que
efetivamente retorna o objeto encontrado na coleção. Estes dois métodos
next() e hasNext() são os principais quando manipulamos uma coleção
por meio de seu iterator.
Também podemos fazer o for each para percorrer essa coleção. É como
dizer: Execute esta operação para cada elemento desta coleção, no caso
relatado acima o elemento é um objeto do tipo Pessoa.
Vamos ver abaixo como ficaria o mesmo programa acima com o for each
em vez de utilizar o for com iterator.
Segue, abaixo, a tela de resultado da execução da classe ColecaoSet.
Veja que o objeto Pessoa, com o nome “Joao Augusto”, aparece apenas
uma vez, mesmo tendo sido colocado duas vezes na coleção. Os objetos
pessoa3 e pessoa5, embora possuam os mesmos valores, referem-se a
dois espaços de memória diferentes, por isso foram adicionados na coleção.
5 List
List é uma interface que apresenta uma coleção ordenada, como uma
seqüencia. O programador sabe onde os elementos da lista foram inseridos.
A interface List permite acesso aos elementos por meio de índices inteiros,
responsáveis pelas posições desses elementos. Assim, podemos acessá-los
diretamente ou percorrer a lista para encontrá-los. Ao contrário da interface
Set, a List permite que a lista possua objetos duplicados, e também vários
elementos nulos.
Acompanhe mais este exemplo abaixo.
Vimos a classe Carro com seus atributos e métodos de acesso. Agora,
vamos observar a classe ClasseLista com a responsabilidade de preencher
os objetos da classe Carro e, posteriormente, colocá-los na coleção que
implementa a interface List. A coleção também é parametrizada, a principal
diferença em relação ao programa anterior é que, nesta coleção da
interface List, podemos colocar dois ou mais objetos repetidos, como
podemos ver na listagem a seguir.
Repare que, nesse caso, a gente apenas criou um método na classe
possuidora do método main, em vez de criar outra classe para isso. Repare
também no detalhe que mostra a inclusão do objeto carro3 na mesma
coleção.
Veremos agora, a tela de resultado da execução dessa classe. Na tela
abaixo você pode observar que, na listagem, o objeto carro3 aparece duas
vezes, pelo fato de ter sido colocado de forma duplicada na coleção.
Agora, acompanhe uma vídeo-aula com mais um exemplo de programa que
agrega as informações vistas nesta aula.
VIDEO CD - Aula 09 - video 1 – coleções
Resumo da aula
Nessa aula vimos sobre coleções, semelhanças, diferenças, como montá-las,
entre outras práticas relacionadas aos objetos. Vimos que Coleções são
grupos de objetos que possibilitam o acesso a cada elemento contido na
coleção e que o Polimorfismo Paramétrico se refere à capacidade de
definirmos uma coleção e dizer ao compilador que aquela coleção é de um
tipo determinado. Já os Arrays são tratados como objetos na linguagem
Java, mas seus recursos são bastante limitados. Além disso, o Java fornece
um mecanismo bastante eficiente para o tratamento de coleções, que
consiste na utilização das interfaces e classes do grupo Collection. Por fim,
vimos que Set é uma coleção que não pode conter elementos duplicados
(além de, no máximo, um elemento nulo) e que, ao contrário da interface
Set, a List permite que a lista possua objetos duplicados, e também vários
elementos nulos. Agora, chegou a sua vez de praticar!
Atividade
1. Crie uma classe que, no método main, instancie um objeto da classe
LinkedList, acrescente 10 strings neste objeto e depois imprima o
conteúdo dessa lista na tela.
2. Crie um programa que possua 3 classes – Aluno com os atributos
nome, matrícula, nota 1 e 2, Turma com o método que retorna uma
coleção de alunos e RelatorioAlunos que calcule a nota final do aluno
e apresente sua respectiva menção. Veja, logo abaixo, um vídeo
com este exercício resolvido! VIDEO CD - Aula 09 - video 2 -
exercicio resolvido - lista alunos
3. Modifique a classe feita anteriormente para excluir todos os
elementos da coleção de uma vez. Dica: Utilize o método clear()
http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html
#clear() para realizar esta operação. Depois disso, verifique se os
elementos foram realmente excluídos da coleção, observando a
quantidade de elementos da coleção por meio do método size()
http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html
#size(), que deve retornar o valor 0.
4. Crie uma nova classe que possua uma coleção que implemente a
interface List com os valores 10, 20, 25, 36, 84, 50, 60, 15, 20 e 25.
Depois, crie um mecanismo que percorra a coleção, acumule o
somatório desses valores e seja apresentado na tela o valor
acumulado, a quantidade de elementos e a média aritmética. Utilize
um for com Iterator.
5. Crie uma nova classe que possua uma coleção que implemente a
interface Set com os valores 10, 20, 25, 36, 84, 50, 60, 15, 20 e 25.
Depois, crie um mecanismo que percorra a coleção, acumule o
somatório desses valores e seja apresentado na tela o valor
acumulado, a quantidade de elementos e a média aritmética. Utilize o
for each.
6. Refaça os exercícios anteriores 3 e 4 utilizando a estrutura de
repetição while e verifique se isso interfere nos valores de média.
7. Explique com as suas palavras porque houve diferença entre os
valores percebidos no exercício 3 e no exercício 4.
8. Crie uma classe Pessoa com os atributos nome, RG e CPF. Crie os
métodos de acesso para estes atributos e depois crie um método
responsável por instanciar 5 pessoas com valores diferentes em seus
atributos e os adicione em uma coleção. Recupere esta coleção no
método main e imprima os valores dos objetos na tela.
9. Crie uma classe Aluno com os atributos matricula e nome curso. Faça
essa classe herdar da classe Pessoa do exercício anterior. Preencha
os atributos nome, RG, CPF, matrícula e nome do curso de 7 alunos e
inclua-os em uma coleção. No método main recupere esta coleção e
imprima seus valores na tela.
10.Modifique o exercício anterior para criar uma classe Turma com os
atributos nome do curso e número da turma. Retire o atributo nome
do curso da classe Aluno do exercício 8. Associe uma classe Turma a
classe Aluno. Crie dois objetos Turma e associe-os aos 7 objetos da
classe Aluno. Crie uma classe com o método main para imprimir os
dados na tela.
11.Crie uma classe Automóvel com os atributos cor, marca, modelo e
ano de fabricação. Coloque os métodos de acesso, instancie 5 objetos
da classe Automóvel, preencha os atributos com valores distintos,
adicione os objetos em uma coleção e no método main imprima-os na
tela.
AULA 10 - TRATAMENTO DE ERROS E DE EXCEÇÕES
Tratando as exceções o nosso sistema ficará mais robusto, se tornará mais
seguro, mais confiável e bem estruturado. Essas são características
importantes para qualquer sistema, um software que responda bem as
ocorrências adversas e consiga tratar falhas de forma eficiente acaba por se
tornar um software de alta qualidade.
Ao final desta aula você será capaz de compreender o
funcionamento das rotinas para tratamento de exceções,
implementadas em Java.
Abertura
VIDEO CD – AULA 10 – VIDEO 0 – ERROS E EXCEÇÕES
Fonte: http://camilolopes.files.wordpress.com/2009/02/hierarquiaexcecoes.jpg
Texto base
Exceções
Quando falamos em sistemas de informações, podemos dizer que exceção é
uma situação adversa, na qual a seqüência da execução normal do
programa é alterada, deixando o sistema em uma condição anormal. A
capacidade de tratamento de exceções é um importante mecanismo da
linguagem Java, e tem a finalidade de resolver problemas ocasionados por
desvios no fluxo de execução dos programas. É importante lembrar que
esse mecanismo não é de exclusividade da linguagem Java; outras
linguagens de programação orientadas a objetos, como C++, Object Pascal,
Python, .NET, por exemplo, também o possuem suporte à tratamento a
erros e exceções.
1 Classificação das Exceções
As exceções podem ser classificadas como verificadas e não verificadas.
As exceções verificadas são aquela às quais o programador deve tratar.
São situações que devem ser previstas e atendidas pelos desenvolvedores.
Todas as exceções dentro dessa categoria, com exceção de
RuntimeException, derivam (são subclasses) da classe Exception. Essas
exceções devem ser tratadas dentro do método ou lançadas para que outro
método as trate.
As exceções de RuntimeException são as não verificadas. Indicam erros,
mas não são causados diretamente pela lógica do programador, nem erros
de sintaxe, são erros relacionados à máquina virtual Java, geralmente,
algum problema no ambiente que roda o programa.
2 Hierarquia das classes de Exceções
Por meio do diagrama abaixo, podemos verificar como é a hierarquia das
classes de exceção. Assim, de maneira mais clara, poderemos compreender
como funciona esse mecanismo. Você pode reparar, por exemplo, que as
classes Error e Exception descendem de Throwable – superclasse de
todas as exceções – enquanto as outras são subclasses de Exception.
As instruções para tratamento de exceções são bastante simples. Você deve
colocar as palavras try catch, e eventualmente finally. Assim, todo
o código que estiver dentro desse escopo será denominado de “rotina de
tratamento de exceção”. Caso ocorra uma exceção, esta será capturada e
devidamente tratada.
try {
...
// Bloco de código que lança a exceção
}
catch () {
...
// Exceção tratada
}
finally {
...
// Bloco opcional que sempre é executado quando chamado
}
Agora, vamos ver na prática como tratar uma exceção. O primeiro exemplo
que vamos utilizar é a classe SimpleDateFormat. Essa classe pode ser
iniciada com o construtor vazio ou com o formato de data, em String,
passado no momento de instanciar a classe. A utilização do método parse
que transforma uma String em data no formato passado anteriormente
exige o tratamento da exceção como se segue.
Repare que a primeira vez não houve erro porque a string com a data
15/11/1889 foi passada de maneira correta, do jeito que a referência da
classe SimpleDateFormat estava esperando. Na segunda vez que o
método parse foi chamado, o erro aconteceu porque a String com data 07-
09-1822 não estava no formato esperado pela referência. Veremos agora a
tela de resultado da execução desse programa.
Apenas a título de curiosidade, essa tela está diferente das outras em
relação às cores apresentadas apenas por questões de leitura e clareza.
Podemos também criar classes de exceções específicas. Nesse caso, vamos
criar uma classe que trata a exceção quando determinado atributo do tipo
String for vazio, impossibilitando a correta execução do fluxo. Segue a
figura com a classe StringVaziaException subclasse de Exception.
Agora, vamos ver a execução de um programa com uma classe que utiliza
esta StringVaziaException.
Repare que podemos tratar a exceção ou fazer com que o método a lance
utilizando a cláusula throws. Assim, a responsabilidade de tratar a
exceção pode ser delegada até o nível mais alto da requisição. Observando
o programa acima, o método main, que chamou o método
verificaArgumentos(String[]), trata a exceção StringVaziaException. Caso
existissem outros métodos que chamassem o verificaArgumentos(String[]),
esses poderiam tratar ou jogar a responsabilidade para cima até chegar no
primeiro método que desencadeou todas as chamadas.
Veja, logo abaixo, como fica a tela de resultado da execução do programa
acima.
Perceba que executamos a classe UsaExcecao duas vezes. Na primeira,
não passamos argumentos para forçar a ocorrência do erro e a conseqüente
utilização da classe StringVaziaException. Na segunda vez, nós passamos
um argumento, com isso a execução não foi desviada a ponto de ocorrer a
exceção.
Vamos agora analisar o emprego do bloco finally. Utilizamos a mesma
classe UsaExcecao declarada acima, apenas com a diferença do bloco
finally, declarado após o bloco catch. Como já mencionado, esse é
um bloco opcional, mas, caso seja declarado, ele sempre será executado.
Para vermos o resultado é necessário compilar a classe UsaExcecao
novamente. Isso, porque ela sofreu modificações e o arquivo .class ficou
desatualizado. Toda vez que alteramos uma classe ela precisará ser
compilada novamente para o programador poder ver a nova execução.
Muitas vezes, nós programadores, esquecemos de compilar novamente a
classe que sofreu modificação e começamos a achar que as coisas não
estão funcionando. Na dúvida, basta compilar o projeto mais uma vez. A
classe StringVaziaException não precisa ser compilada de novo pois,
esta, por sua vez, não sofreu modificações. Acompanhe a tela de resultado
para ver a execução do bloco finally na classe UsaExcecao.
Veja que, independente do lançamento ou não da exceção, o trecho de
código presente no bloco finally foi sempre executado.
Repare no quadro abaixo, algumas das classes de exceção mais comuns da
linguagem Java.
ArrayIndexOutOfBoundsException
Tenta de acessar uma posição inexistente em um array.
ClassCastException
Tenta executar um cast em uma referência que não é classe ou subclasse daquela esperada.
NullPointerException
Acesso a um objeto que não foi instanciado anteriormente, ou seja, seu valor é nulo (null).
NumberFormatException
Tenta converter uma String em número, na qual essa String possui um formato diferente de
um número.
NoClassDefFoundError
A JVM não localizou a classe para a execução do programa.
Agora, acompanhe mais exemplos de programas implementando rotinas de
tratamento de exceções.
VIDEO CD - Aula 10 - Aula 10 - video 1 - TratamentoExcecoes
VIDEO CD - Aula 10 - video 2 - Excecao
Resumo da aula
Nesta aula, vimos que exceção é uma situação adversa, na qual a
seqüência da execução normal do programa é alterada. As exceções podem
ser classificadas como verificadas e não verificadas. As instruções para
tratamento de exceções consistem em colocar as palavras try catch, e
eventualmente finally. Podemos tratar a exceção ou fazer com que o
método a lance, assim, a responsabilidade de tratá-la passa a ser do
método que a chamou, denominado lançador da exceção.
Atividade
1. Crie uma classe que instancie um objeto da classe
java.text.SimpleDateFormat. Utilize o método parse para transformar
uma data em String passada como parâmetro no formato dd/MM/yyyy
em um objeto java.util.Date. Tente compilar e executar esse
programa sem utilizar a instrução try catch. Explique o erro
acontecido baseado na mensagem exibida pela JVM
2. Agora, adapte seu programa para utilizar a instrução try catch para
tratar a exceção lançada pelo método parse.
3. Utilize o exercício resolvido da aula 8, que trata da operação de
transferência entre contas bancárias e acrescente o tratamento de
uma exceção no lugar da mensagem de saldo insuficiente. Veja,
logo abaixo, um vídeo com este exercício resolvido! VIDEO CD
- Aula 10 - video 3 - exercicio resolvido - conta bancária com
excecao
4. Crie uma classe na qual o método main receba um objeto da classe
Exception dentro de um bloco try. Passe um argumento String ao
construtor da classe Exception. Capture a exceção dentro de uma
clausula catch e imprima o argumento String.
5. Modifique o exercício anterior, adicione uma clausula finally e
imprima uma mensagem para observar que a execução sempre
passa por essa cláusula.
6. Crie sua própria classe de exceção herdando de Exception. Escreva
um construtor para esta classe que possua um argumento String e
armazene-o em um atributo. Escreva um método que exiba a String
passada como argumento
7. Crie uma classe com o método main que possua uma clausula try-
catch para exercitar a utilização da classe confeccionada no exercício
anterior.
8. Crie uma classe que tenha um método que lance a exceção criada
por você no exercício 5. Depois, crie outra classe que possua um
método main que chame o método que lança a exceção criada por
você e trate essa exceção.
9. Crie uma classe com o nome LimiteException que herde de
Exception. Crie um construtor com a seguinte mensagem: “O valor
acumulado estourou o limite.”
10.Crie uma nova classe que possua uma coleção que implemente a
interface List com os valores 10, 20, 25, 36, 84, 50, 60, 15, 20 e 25.
Depois, crie um mecanismo que percorra a coleção, acumule o
somatório desses valores e, caso o somatório atinja o valor 300 o
programa deve lançar a exceção criada no exercício anterior.
11.Adapte as classes utilizadas no exercício anterior para que a
mensagem exposta na classe LimiteException seja impressa com o
valor que causou o lançamento da exceção. Por exemplo, se o
somatório chegou ao valor 305, a mensagem exibida deve ser: “O
valor acumulado – 305 – estourou o limite”.