Escolar Documentos
Profissional Documentos
Cultura Documentos
UNIDADE I....................................................................................................... 5
Programação Orientada a Objetos
UNIDADE II.................................................................................................... 42
Trabalhando com os Métodos e suas Referências
UNIDADE III................................................................................................... 68
Pilares da Orientação a Objetos e seus Comandos
Plano de Estudo:
Objetivos de Aprendizagem:
5
INTRODUÇÃO
Caro (a) aluno (a), iniciaremos a primeira unidade do livro Programação Orientado
a Objetos (POO) com uma breve introdução sobre o Paradigma Orientado a Objeto e
a importância da elaboração de um código elegante dentro do projeto de produção de
software.
Também poderíamos usar um nome que não fosse “insert” para o método ou alterar
a ordem ou o número de parâmetros. Por exemplo, poderíamos sobrecarregar o método
para que dois valores pudessem ser inseridos ao mesmo tempo. Também poderíamos ter
vários tipos de retorno. O método poderia ter void como tipo de retorno ou, por exemplo,
retornar informações indicando se foi bem sucedido na inserção do novo valor. Qual dessas
opções seria a melhor? Voltaremos continuamente a esse exemplo nesta seção do capítulo
e, no processo, responderemos a essa pergunta e a pergunta mais geral sobre o que torna
um método elegante.
Segundo Tucker (2009), vários princípios da criação de software pode nos ajudar a
comparar e julgar as abordagens mencionadas no parágrafo anterior. Um princípio é usar
nomes que revelem a finalidade. Ele será examinado com mais detalhes porque não se
aplica só aos métodos. Pode ser aplicado a qualquer parte do software que use nomes,
inclusive métodos, variáveis, classes e interfaces. Um nome de método deve indicar a
finalidade do método, isto é, o que o método deverá fazer. O nome não deverá indicar como
o método atingirá seu objetivo e sim qual será o objetivo. Um método que não retornar um
valor (um método com tipo de retorno void) deverá ter um nome composto por um verbo
ou um verbo e seu complemento, como print( ) ou setName( ). Nomes vagos como doIt(
) são inadequados. Um método que retornar um valor deverá ter um nome que reflita o
valor que estará sendo retornado, por exemplo, length( ) ou name( ). Esse tipo de método
também poderia ter um verbo e seu complemento como nome. Como convenção pode-se
utilizar a palavra “get” seguida do valor retornado. Por exemplo, um método que retorne o
tamanho de alguma estrutura de dados poderia receber o nome size( ) ou getSize( ). Com
relação ao nosso exemplo DataHolder, o nome insert( ) será satisfatório, pois descreverá
sucintamente o que o método deverá fazer.
Para concluir, as variáveis têm que ser nomeadas apropriadamente para melhorar
a legibilidade. Considere um programa com uma variável chamada nT. Um argumento a
favor de um nome assim seria que ele é curto e, portanto, economiza tempo de digitação
e ajuda a encurtar as linhas de código. Contudo, o nome não é significativo no que diz
respeito a indicar a função da variável e o leitor é forçado a memorizá-la. Por outro lado,
chamar a variável de numberOfThreads ou NumThreads ou até mesmo numThrds em vez
de nT, aumenta drasticamente a facilidade de entender o código.
Uma variável boolean deverá ter um nome apropriado para o valor que representa.
Geralmente não deverá representar a negação de um valor, então, por exemplo, não
deveremos chamar nossa variável de notYetDone, que poderia resultar na necessidade de
expressões como a negativa dupla !notYetDone. Em vez disso, seria melhor chamá-la de
done e usar a expressão !done sempre que notYetDone tivesse de ser usada. É claro que
o nome done também não é ideal, já que a palavra não contém informações suficientes
para ajudar o leitor a entender o papel da variável. O nome da variável deverá informar
que atividade é ou não executada. Por exemplo, se essa variável estiver sendo usada para
indicar que uma imagem gráfica acabou de ser carregada e já pode ser vista, um nome
melhor seria doneLoading. Lembrem-se, nomes ruins não levam apenas a enganos; eles
tornam o sistema inteiro mais difícil de entender, o que vai contra nosso desejo de ter um
software legível conforme trata Tucker (2009) em seu livro de princípios e paradigmas.
Esse método está claramente tentando fazer duas coisas e usando o flag para
determinar qual delas fazer. Seria melhor termos dois métodos auxiliares separados, como
doThis( ) e doThat( ), nenhum deles precisando de um flag. Uma vez que tivermos esses
métodos, poderemos reescrever o método acima conforme a Figura 02.
Agora esse código será aceitável (exceto pelos nomes flag, this e that, que não
revelam a finalidade), já que o método está apenas agindo como uma central de despachos
e, portanto, está fazendo apenas uma coisa e fazendo-a bem.
Aqui, ainda citando Tucker(2009), está outro princípio relativo a métodos elegantes:
“um método não privado deverá manter um objeto em um estado bem formado”. Por
exemplo, suponhamos que você tivesse uma classe com duas variáveis de instância: um
array de inteiros data e um inteiro max, que armazenam o valor máximo do array data. Você
deverá tomar cuidado para não ter métodos na classe que modifiquem o array sem atualizar
também a variável max. É a esse tipo de coerência interna que nos referimos quando
dizemos que uma classe é “bem formada”. Como formular os requisitos de coerência dos
objetos de uma classe? Isto é, como saber se a instância de uma classe está bem formada?
Uma boa maneira é criar uma lista das invariantes da classe. Uma invariante de classe é
uma declaração que fornece os requisitos sobre o estado de instâncias da classe entre
chamadas de método públicas. Um exemplo de invariante de classe é a declaração “O valor
de max e o maior valor do array data deverão ser iguais”. Como outro exemplo, considere a
implementação, apresentada na Figura 03, da classe DataHolder discutida anteriormente.
Observe que o array data está sempre repleto de dados que foram inseridos.
Isto é, nunca haverá locais não usados no array. Essa é uma invariante para objetos
da classe DataHolder. Se a invariante for rompida, poderá ocorrer um comportamento
inesperado. Para evitar isso, os três métodos auxiliares increaseCapacity( ), shift( ) e put( )
foram construídos como privados. Como resultado, os objetos desta classe, poderão ficar
temporariamente mal formados. Por exemplo, após increaseCapacity( ) ter sido chamado,
mas serão restaurados para um estado bem formado, antes de algum método público
retornar. Se increaseCapacity( ) ou shift( ) fossem públicos, qualquer usuário do objeto
poderia chamá-los isoladamente, causando a má formação do objeto.
Serra (2003) apresenta a noção de Tipo Abstrato de Dados (TAD), iniciando pela
especificação de um tipo de dado com as suas propriedades fundamentais, de maneira
independente da implementação da linguagem utilizada.
São três passos envolvidos para implementar um tipo abstrato de dados (TAD):
● O primeiro passo será a definição de uma API Java (Application Programming Inter-
face), ou simplesmente interface, que descreverá os métodos que o TAD suportará
e como eles serão declarados e como serão utilizados.
● O segundo passo será a escolha da representação Concreta do TAD que será utili-
zada na implementação. Assim, basicamente dois tipos de representação são intro-
duzidos:
○ Estrutura Estática (com a utilização de arrays);
○ Estrutura Dinâmica (com a utilização de listas ligadas/encadeadas, pilhas,
árvore, etc.).
● E o terceiro passo será a implementação da interface através de uma classe e le-
vando em consideração a representação escolhida no segundo passo.
1.5.1. Estruturas
Para facilitar a compreensão de vocês, meus caros leitores, será apresentado uma
implementação, na Figura 05, de uma interface denominada estruturaLinear por meio de
uma determinada classe chamada ArrayCircularList. Esta implementação está baseada
na utilização de uma Estrutura Estática, que servirá para guardar os elementos de uma
determinada coleção. A opção foi a utilização de uma estrutura circular.
Figura 05. Exemplo de implementação uma estrutura estática. Elaborado pelo autor.
Serra (2003) indica que poderá ser vista como uma ligação ou apontador para
outro nó a referência Próximo dentro de um nó. Serão chamados, respectivamente, de
Cabeça e Cauda da lista o primeiro Elemento (nó) e os últimos Elementos (nós) de uma
lista. A cauda será o Elemento (nó) que terá a referência Próximo igual à null, indicando
o fim da lista. O deslocamento de um Elemento (nó) para outro seguindo a referência
Próximo será conhecido como percorrer a lista ou caminhar na lista. Será conhecida como
uma lista simplesmente encadeada, uma lista encadeada que for definida desta maneira.
Uma lista simplesmente encadeada, diferentemente de uma tabela, não terá tamanho fixo
pré-determinado e alocará ao número de Elementos, os espaços proporcionais a cada
um deles. Na Figura 07, será definida uma classe No, para implementação de uma lista
simplesmente encadeada na linguagem de programação Java.
Figura 08. Implementação de uma Lista Simplesmente Encadeada. Elaborado pelo autor.
Figura 09. Antes da inserção de novo nó na Cabeça da Lista. Baseado em Serra (2003).
Figura 11. Depois da inserção de novo nó Cabeça da Lista. Baseado em Serra (2003).
Figura 12. Código para a inserção de novo nó na Cabeça da Lista. Elaborado pelo autor.
Nesta situação Serra (2003) indica que teremos que percorrer todos os elementos
a partir do ponteiro da cabeça até chegar no último Elemento, caso não tenha a referencia
para o último Elemento da lista (ponteiro Cauda). A representação escolhida para a lista,
como nosso exemplo, possui uma variável com a referência para o último Elemento (Cauda).
Esta operação será descrita nas Figuras de 13 a 15.
Figura 13. Antes da inserção de novo nó na Cauda da Lista. Baseado em Serra (2003).
Figura 16. Código para a inserção de novo nó na Cauda da Lista. Elaborado pelo autor.
1.5.3.4. Remoção do Nó
Serra (2003) trata essa situação da seguinte forma - o elemento (nó) da cabeça
ou da Cauda da lista poderá ser removido. A implementação do método seguinte permitirá
remover o Elemento da Cabeça da lista.
Figura 17. Método para a remoção do elemento da Cabeça da Lista. Elaborado pelo autor.
Deverá existir para cada Elemento (nó) da lista duplamente encadeada, uma
ligação não somente para o próximo Elemento, mas também para o Elemento anterior
da lista. Com esta variante, da lista simplesmente encadeada, permitirá a inserção e a
remoção o Elemento (nó) na cabeça e na cauda da lista. Para implementação deste tipo
de lista, Devemos especificar a classe NoD, composta por Elemento (nó) referência para
o Elemento (nó) seguinte e referência para o Elemento (nó) anterior. Estes são os passos
descritos por Serra (2003) para o tratamento de lista duplamente encadeadas. Além disso,
o código desta classe poderá ser visualizado na Figura 18.
Assim o código para lista dupla é apresentado nas Figuras 19, 20 e 21.
Figura 19. Método para inserção e a remoção de elementos da Lista Duplamente Encadeada. Elaborado
pelo autor.
Figura 21. Método para inserção e a remoção de elementos da Lista Duplamente Encadeada. (Continua-
ção). Elaborado pelo autor.
As interfaces de nível superior definidas por java.lang são as mostradas na Tabela 02.
Segundo Pereira (2017), será fornecido pela biblioteca AWT todas as classes para a
criação de interfaces com o usuários, imagens e pintará gráficos. Ela é uma interface gráfica
de usuário ( Graphical User Interface - GUI). Ela delegará para a Interface Gráfica de Usuário
(GUI) da plataforma nativa (Windows, Linux, Mac) a criação, estilo e comportamento.
Com o seu lema “Write once, run anywhere” (“Escreva uma vez, execute em
qualquer lugar”), o estilo será o mesmo da plataforma, se fizermos uma caixa de texto,
por exemplo, no Windows ou Linux, que atenderá à promessa de portabilidade do Java,
conforme apresenta Schildt (2013).
Figura 22. A sequência dos exemplos import java.awt.*; import java.awt.event.*; import java.awt.event.*;
import javax.swing.*; Elaborado pelo autor.
“Os applets diferem dos tipos de programa mostrados nos exemplos anterio-
res. Eles são programas pequenos projetados para transmissão pela Internet
e serem executados dentro de um navegador. Já que a máquina virtual Java
se encarrega da execução de todos os programas Java, inclusive applets,
oferecem uma maneira segura de baixar e executar dinamicamente progra-
mas pela Web.”( SCHILDT, 2015, p.499).
Ainda conforme Schildt (2013), java foi projetada para atender às necessidades
do ambiente de programação da Internet. Portanto, não deve surpreender o fato que a
linguagem dá amplo suporte à rede em sua biblioteca de APIs. O principal pacote de rede
de Java é o java.net. Ele fornece classes que permitem que um aplicativo acesse recursos
de rede de maneira conveniente e eficaz.
O método está escrevendo onde? Não será necessário saber e isso também não
importará, porque quando o sistema realmente precisar escrever em um arquivo ou em um
soquete, bastará chamar esse mesmo método, já que ele aceitará qualquer classe “filha”
de OutputStream.
o pacote java.util define classes e interfaces que atendem várias tarefas comumente
encontradas quando se programa. Por exemplo, ele contém o Collections Framework. O
Collections Framework é um dos subsistemas mais poderosos do Java e dá suporte a uma
sofisticada hierarquia de interfaces e classes que gerenciam grupos de objetos. O pacote
java.util também fornece várias classes utilitárias, inclusive as que formatam dados para
saída, leem dados formatados e trabalham com data e hora. Como java.util dá suporte a
um conjunto tão amplo de funcionalidades, é um pacote muito extenso.
Um carro, além de ter a capacidade de realizar tarefas, também tem atributos, como
cor, número de portas, quantidade de gasolina no tanque, velocidade atual e registro dos
quilômetros totais dirigidos (isto é, a leitura do odômetro). Assim como suas capacidades,
os atributos do carro são representados como parte do seu projeto nos diagramas de
engenharia (que, por exemplo, incluem um odômetro e um medidor de combustível). Ao
dirigir um carro real, esses atributos são incorporados a ele. Cada carro mantém seus
próprios atributos. Cada carro sabe a quantidade de gasolina que há no seu tanque, mas
desconhece quanto há no tanque de outros carros.
Um objeto, da mesma forma, tem atributos que ele incorpora à medida que é usado
em um programa. Esses atributos são especificados como parte da classe do objeto. Por
exemplo, um objeto conta bancária tem um atributo saldo que representa a quantidade de
dinheiro disponível. Cada objeto conta bancária sabe o saldo que ele representa, mas não
os saldos de outras contas bancárias. Os atributos são especificados pelas variáveis de
instância da classe.
Nesse caso, quando você criar uma conta, seus atributos já estão “populados”
com esses valores colocados. Imagine que comecemos a aumentar nossa classe Conta e
adicionar nome, sobrenome e CPF do cliente dono da conta. Teríamos muitos atributos. E
se você pensar bem, uma Conta não tem nome, nem sobrenome nem CPF, quem tem esses
atributos é um Cliente. Então podemos criar uma nova classe e fazer uma composição.
Seus atributos também podem ser referências para outras classes. Suponha as seguintes
classes Cliente e Conta apresentado nas Figuras 25 e 26.
Figura 27. Exemplo de referência de atributos dentro do main da classe de teste. Elaborado pelo autor.
Você pode realmente navegar sobre toda essa estrutura de informação, sempre
usando o ponto: Cliente clienteDaMinhaConta = minhaConta.titular; clienteDaMinhaConta.
nome = “Luke”; Ou ainda, pode fazer isso de uma forma mais direta e até mais elegante:
minhaConta.titular.nome = “Luke”;
No contexto de uma atribuição, e conforme Deitel (2008), o operador new tem esta
forma geral: var_classe = new nome_classe(lista_arg); O operador new é o responsável
pelo processo de instanciação do objeto, representando uma forma extremamente simples
de atribuir valores default a um objeto.
A declaração: Televisor tv = new Televisor(); pode ser lida como: construa o objeto
tv (do tipo Televisor) com valores default. Como o próprio nome diz, o método construtor é
o responsável por construir um objeto com determinados valores.
Se uma classe não definir seu próprio construtor, new usará o construtor padrão
fornecido por Java. Logo, new poderá ser usado para criar um objeto de qualquer tipo de
classe. O operador new retornará uma referência ao objeto recém-criado, que (nesse caso)
será atribuído a var-classe.
Já que a memória é finita, e conforme Deitel (2008), é possível que new não
consiga alocar memória para um objeto por não existir memória suficiente. Se isso ocorrer,
haverá uma exceção de tempo de execução. Para os exemplos de programa deste livro,
não precisamos nos preocupar em ficar sem memória, mas temos que considerar essa
possibilidade em programas do mundo real que escrevermos ou quando desenvolvemos
para dispositivos embarcados com baixa quantidade de memória.
Figura 28. Exemplo de referência de objeto utilizando new. Elaborado pelo autor.
O correto aqui é dizer que c1 se refere a um objeto. Não é correto dizer que c1
é um objeto, pois c1 é uma variável referência, apesar de que, depois de um tempo, os
programadores Java falarem “Tenho um objeto c do tipo Conta”, mas apenas para encurtar
a frase “Tenho uma referência c a um objeto do tipo Conta”. Basta lembrar que, em Java,
uma variável nunca será um objeto. Não há, no Java, uma maneira de criarmos o que é
conhecido como “objeto pilha” ou “objeto local”, pois todo objeto em Java, sem exceção, é
acessado por uma variável referência, assim como Deitel (2008) trata em seu livro.
Agora vamos definir outro conceito em OO, assim como menciona Jacobi (2006):
mensagens entre objetos. Já aprendemos que um objeto pode possuir diversos métodos
definidos em sua classe. Em uma aplicação real é muito comum que existam diversos tipos
de objetos e que um objeto necessite realizar uma tarefa que já está definida em outro
objeto, ou seja, numa aplicação poderá haver comunicação e interação entre objetos por
meio de mensagens. Em outras palavras, um objeto X pode necessitar de um procedimento
(método) já definido em um objeto Y. Para realizar esse processo, o objeto X solicita ao
objeto Y que execute o método, ou seja, uma mensagem nada mais é do que o fato de um
objeto chamar um método de outro objeto (ou ainda um método estático de uma classe).
Vamos tentar elucidar com um exemplo. Digamos que um objeto “gerente” precise
enviar um e-mail. Ele não sabe como fazer isso, porém o objeto “email” sabe. Então, o
objeto “gerente” solicita ao “email” que faça isso por ele. Em orientação a objetos, quando
um objeto X solicita a um objeto Y que execute um de seus métodos, diz-se que o objeto
X enviou uma mensagem ao objeto Y. Uma mensagem pode conter parâmetros que são
valores enviados de um objeto a outro, quando um método for invocado. Observe a Figura
29, em que o objeto “gerente” envia uma mensagem ao objeto “email” (invocando o método
enviar). Serão enviados quatro parâmetros: de, para, assunto e mensagem. Esse padrão
do envio de mensagens é definido pela UML e pode ser encontrado, por exemplo, em
diagramas de comunicação e sequência.
Como você sabe, e tratado por Jacobi (2006), um método será invocado por uma
chamada de método e quando o método chamado terminar sua tarefa, ele retornará o
controle e possivelmente um resultado para o chamador. Uma analogia a essa estrutura de
programa é a forma hierárquica de gerenciamento, ilustrado na Figura 30 e apresentado
a seguir: Um chefe (o chamador) solicita que um trabalhador (o método chamado) realize
uma tarefa e informe (retorne) os resultados depois de completar a tarefa. O método chefe
não tem conhecimento sobre como o método trabalhador realiza suas tarefas designadas.
O trabalhador também poderá chamar outros métodos trabalhadores, sem que o chefe
saiba. Essa “ocultação” dos detalhes de implementação promove a boa engenharia de
software. A Figura 30 mostra também o método chefe se comunicando com vários métodos
trabalhadores de uma maneira hierárquica. O método chefe divide as responsabilidades
entre os vários métodos trabalhadores. Aqui, trabalhador1 atuará como um “método chefe”
para trabalhador4 e trabalhador5.
REFLITA
Referência: https://citacoes.in/citacoes/1923990-alan-kay-our-job-is-to-remind-us-that-
-there-are-more-contex/
Como pode ser qualificado um software? É muito simples definir isso pelo tempo de de-
senvolvimento ou pela excelência na programação. Existem casos de desenvolvimento
de softwares em que o analista ouve todas as informações e apresenta uma solução,
quase que “surreal”. Algo que poderá resolve perfeitamente o que foi solicitado. Olhando
assim, a sensação que temos parece que o atendimento foi excepcional, contudo, na
maioria das vezes, os programas feitos neste formato não atendem a real necessidade
dos clientes.
Não devemos julgar o cliente por não apresentar de forma assertiva as suas necessida-
des. E a consequência disso tudo é a perda de investimento financeiro e de tempo em
um projeto que não vai atender as suas necessidades. Casos assim são muito comuns
de acontecer, é muito provável que você já tenha vivenciado ou ouvido falar sobre isso.
Esse tipo de problema não é exclusivo do desenvolvimento de softwares, é algo que
ocorre com frequência no mercado, em geral. Para provar isso, basta surgir a necessi-
dade de um serviço, em sua casa ou trabalho, em que não tenha nenhum conhecimento
do processo, como consertar uma porta, uma janela ou uma infiltração na parede. A
solução só vem quando um profissional qualificado está mais preocupado em satisfazer
o cliente do que resolver exclusivamente o problema apresentado. Os profissionais que
mantêm esse tipo de procedimento de atendimento vão sendo substituídos aos poucos.
Na rotina diária de um programador, normalmente, o início do projeto vem de um conver-
sa informal e só lá na primeira apresentação, depois de um grande tempo de dedicação,
é que o cliente consegue esclarecer ainda de forma abstrata com frases como “não é
bem isso que eu queria”. Outro caso comum que acontece, pela falta de alinhamento,
são as solicitações do cliente, ir aumentando durante o processo de desenvolvimento
e como nada está estabelecido de forma clara no início do trabalho, você poderá até
prolongar o projeto, mas, possivelmente, não atenderá todas as necessidades do seu
cliente.
Lembrando que cliente não tem obrigação de entender de programação e que a preo-
cupação deverá ser do programador, de atender o cliente e não o contrário. Um bom
profissional deve fazer uso de uma excelente interpretação às necessidades do cliente
e oferecer não o que ele está pedindo, mas sim o que realmente vai suprir sua neces-
sidade.
(Fonte o autor)
Nesta unidade, aprendemos que o Paradigma Orientado a Objeto (OO) nos propicia
a elaboração de um código elegante dentro de um projeto de produção de software. Já o
projeto é o resultado do refinamento da análise e considerar os detalhes da implementação,
tal como a linguagem de programação a ser utilizada, que poderá ser Java, CSharp, C++,
Python, ASP.NET, dentro do contexto OO.
Juntos pudemos nos familiarizar com o conceito de Orientação a Objetos, que
é um paradigma para o desenvolvimento de aplicações, ou seja, é uma estratégia de
desenvolvimento de software que organiza o software como uma coleção de objetos, que
contém tanto a estrutura dos dados como o comportamento deles.
Você pode verificar que os métodos coesos, dentro de um projeto orientado a
objetos, devem fazer apenas uma coisa e fazê-la bem. Isto é, um método não deve executar
duas ou mais tarefas, a menos que façam parte de uma mesma ação coesa. Outro princípio
relativo a métodos elegantes que você pode verificar foi que um método não privado deverá
manter um objeto em um estado bem formado.
Você pode verificar as características dos principais métodos OO e foi possível
verificar os tipos abstratos de dados, os dois tipos de estruturas que permitem guardar uma
coleção de elementos: Estrutura Estática e Estrutura Dinâmica.
Você pode verificar os principais métodos, visualizar as suas características e entrar
em contato com os conceitos de OO, em que pode aprender sobre objetos, abstração,
classes, operações, atributos, instância, dentre outros.
Por fim, você pode verificar que um objeto pode possuir diversos métodos definidos
em sua classe. Em uma aplicação real é muito comum que existam diversos tipos de
objetos e que um objeto necessite realizar uma tarefa que já está definida em outro objeto,
ou seja, numa aplicação poderá haver comunicação e interação entre objetos por meio de
mensagens.
A partir dos conceitos que foram abordados nesta unidade, você pode ter uma
visão geral sobre a Programação Orientada a Objetos.
Estaremos juntos na próxima unidade.
Até lá!
LIVRO
• Título: Java como Programar.
• Autor: Paul Deitel e Harvey Deitel.
• Editora: Pearson Education do Brasil Ltda.
• Sinopse: Java: como programar, 10ª edição, fornece uma
introdução clara, simples, envolvente e divertida à programação
Java com ênfase inicial em objetos. Destaques incluem: rica
cobertura dos fundamentos com exemplos reais; apresentação
com ênfase inicial em classes e objetos; uso com Java™ SE
7, Java™ SE 8 ou ambos; Java™ SE 8 abordado em seções
modulares opcionais; lambdas, fluxos e interfaces funcionais
usando métodos padrão e estáticos do Java SE 8; Swing e GUI do
JavaFX: elementos gráficos e multimídia; conjunto de exercícios
“”Fazendo a diferença””; tratamento de exceções integrado;
arquivos, fluxos e serialização de objetos; concorrência para
melhor desempenho com multiprocessamento; o livro contém
o conteúdo principal para cursos introdutórios; outros tópicos:
recursão, pesquisa, classificação, coleções genéricas, estruturas
de dados, multithreading, banco de dados (JDBC ™ e JPA).
FILME/VÍDEO
• Título: Curso de Java SE
• Ano: 2018
• Sinopse: Neste curso de Java avançado irá nos aprofundar em
tópicos de programação que ajudam você a entender os conceitos
mais avançados de Java. Isso significa que o programador já
precisa ter conhecimentos prévios da linguagem Java, bem como
dos seus recursos, lógica de programação, depuração de código,
IDEs, dentre outros conceitos básicos de programação. Dentre
os tópicos avançados que iremos cobrir neste curso, destacam-
se: Java Avançado; programação genérica, estruturas de dados
sequenciais e associativas, estruturas de dados clássicos,
classificação e pesquisa, tratamento de exceções, programação
de GUI com acesso a rede usando Swing e uma visão geral de
multithreading. Você também vai explorar os Applets Java, entrada
e saída avançadas, strings mais avançadas, expressões regulares,
gráficos Java, manipulação de arquivos e, finalmente, fechando
com um olhar mais crítico e profundo sobre a IDE Eclipse.
• Link do vídeo:
https://www.devmedia.com.br/curso/curso-java-se/423
Plano de Estudo:
Objetivos de Aprendizagem:
42
INTRODUÇÃO
Caro (a) aluno (a), iniciaremos a segunda unidade do livro Programação Orientado
a Objetos. Nesta unidade iremos nos aprofundar mais ainda sobre os conceitos OO e
v. poderá estudar o uso da palavra reservada this. Poderá também ver como a palavra
reservada this será usada para a autorreferência, com atributos e métodos estáticos.
Em seguida, será apresentada uma visão geral dos operadores e suas estruturas.
Você verá que para tratar situações em que o fluxo de execução do programa deverá
ser alterado, Java fornecerá um amplo conjunto de estruturas condicionais, de exceção
e repetição. Você poderá estudar as estruturas condicionais usados em Programação
Orientada a Objetos, que são if-else e switch-case. Essas duas estruturas de desvio
existentes na linguagem possibilitam executar diferentes trechos de um programa com
base em certas condições.
Segundo Goodrich (2013), o this é uma palavra reservada que é usada para a
autorreferência. Esta situação ocorrerá quando quisermos referenciar a métodos e atributos
da própria classe e objeto. Embora seja possível usar o this com atributos e métodos
estáticos, será mais usual utilizá-lo com membros de instância. Mais especificamente ainda,
com atributos.
Cada objeto poderá acessar uma referência a si própria, com a palavra chave this
(às vezes chamada de referência this). Quando um método de instância for chamado para
um objeto particular, o corpo do método utilizará implicitamente a palavra-chave this para
referenciar as variáveis de instância do objeto e outros métodos. Isso permite que o código
da classe saiba qual objeto deve ser manipulado. Você também poderá usar a palavra
chave this explicitamente no corpo do método de uma instância, assim trata Deitel (2017).
O método buildString (linhas 29 a 34) retorna uma String criada por uma instrução
que utiliza a referência this explícita e implicitamente. A linha 34 usa-a explicitamente
para chamar o método toUniversalString. A linha 32 utiliza-a implicitamente para chamar
o mesmo método. Ambas as linhas realizam a mesma tarefa. Em geral, você não utilizará
this explicitamente para referenciar outros métodos dentro do objeto atual. Além disso, a
linha 44 no método toUniversalString utiliza explicitamente a referência this para acessar
cada variável de instância. Isso não é necessário aqui, porque o método não tem variáveis
locais que sombreiam as variáveis de instância da classe.
Toda a classe Java deverá ter um construtor. Quando não declaramos o construtor,
default será inicializado automaticamente pelo Java. Mas existem casos que se faz
Esta sintaxe pode ser vista na Figura 32 e um exemplo dessa declaração na Figura
33.
Figura 33. Exemplo de sintaxe de um construtor na classe Mamifero. Elaborado pelo autor.
Ainda seguindo a técnica de Silveira (2006), existe outro motivo para a utilização
desta técnica, a facilidade para sua implementação. Poderemos criar um construtor que
receberá diversos argumentos para que o usuário de uma classe não seja obrigado a
chamar diversos métodos do tipo set().
Quando implementamos uma classe com todos os seus atributos privados, seus
métodos getters() e setters() e um construtor default (vazio), na verdade nós estaremos
criando um Java Bean, que não deverá ser confundido com o EJB, que é Enterprise Java
Beans. Para saber mais acesse: http://java.sun.com/products/javabeans/
Schildt (2013) ainda trata sobre o if, em conjunto com o else, formando uma
estrutura que permite a seleção entre dois caminhos distintos para execução, dependendo
do resultado (verdadeiro ou falso) de uma expressão lógica (condição). Nesse tipo de
estrutura, se a condição for verdadeira, serão executadas as instruções que estiverem
posicionadas entre as instruções if/else. Sendo a condição falsa, serão executadas as
instruções que estiverem após a instrução else. A sintaxe para a utilização do conjunto if
else será demonstrada em seguida. Observe, na Figura 35, que a condição sempre deverá
aparecer entre parênteses, item obrigatório na linguagem Java.
Figura 35. Exemplo de sintaxe para a utilização do conjunto if else. Elaborado pelo autor.
Figura 37. Representação gráfica da instrução if sem else. (FURGERI, 2015, p.43).
Figura 38. Representação gráfica da instrução if com else. (FURGERI, 2015, p.44).
Figura 41. Tela de execução da Figura 40 com seleção de Feminino. (FURGERI, 2015, 46).
O Exemplo da Figura 42, mostra um uso prático do if-else para validar a entrada do
usuário. Serão realizadas três validações: em primeiro lugar, verifica se o usuário realmente
entrou com um valor na caixa de diálogo, depois verifica se o valor digitado é numérico, logo
a seguir verifica se esse valor está entre 1 e 12 (a faixa de valores possíveis, uma vez que
um mês deverá assumir apenas valores entre 1 e 12).
O Exemplo 44, mostra como é possível criar uma estrutura em que cada instrução
else realiza a abertura de um novo if. Ao analisar essa estrutura, podemos notar que existe
um (ou mais) if dentro de um else.
Figura 48. Tela de execução da Figura 47 com seleção do mês 2. (FURGERI, 2015, p.50).
“Os laços de repetição (looping) formam uma importante estrutura nas lin-
guagens de programação por possibilitarem a repetição da execução de um
bloco de instruções em um programa. Eles determinam que um certo bloco
seja executado repetidamente até que uma condição específica ocorra. A re-
petição é uma das estruturas mais usadas em programação, possibilitando a
criação de contadores, temporizado- res, rotinas para classificação, obtenção
e recuperação de dados. A criação de laços de repetição em Java é feita a
partir das estruturas for, while e do-while” (FURGERI, 2015, p.56).
Tucker (2009) trata uma instrução de repetição como uma especificação que um
programa deverá repetir uma ação enquanto alguma condição permanecer verdadeira.
A instrução de pseudocódigo descreve a repetição durante uma viagem de compras. A
condição “enquanto houver mais itens em minha lista de compras” poderá ser verdadeira ou
falsa. Se ela for verdadeira, então a ação “Compre o próximo item e risque-o de minha lista”
será realizada. Essa ação será realizada repetidamente, enquanto a condição permanecer
verdadeira.
Tucker (2009) ainda detalha a instrução while, apresentada na Figura 49, avaliando
o resultado da expressão (condição) antes de executar as instruções do bloco { }. Assim,
será possível que as instruções nunca sejam executadas, caso a condição seja inicialmente
falsa. Um problema típico, relacionado à avaliação da condição while, é o laço infinito. Caso
a condição nunca se torne falsa, o laço será repetido infinitamente. Um exemplo do laço
While está presente na Figura 50.
Há outro tipo de laço condicional, o chamado do-while, que é bem parecido com
o while, porém o conjunto de instruções será executado antes da avaliação da expressão
lógica. Isso faz com que essas instruções sejam executadas pelo menos uma vez, conforme
apresenta Furgeri (2015). Veja como a sintaxe do do-while é bem parecida com a do while
Embora as chaves não sejam necessárias quando houver apenas uma instrução
presente, elas serão usadas com frequência para melhorar a legibilidade da estrutura do-
while, evitando, assim, confusão com while. O laço do-while será executado enquanto a
expressão condicional for verdadeira. O programa apresentado na Figura 52 demonstra o
uso do do-while ficando em laço até você adivinhar a letra.
Ainda temos Knudsen (2005) tratando sobre a instrução for como um tipo de contador
finito, isto é, ela realiza a contagem de um valor inicial conhecido até um valor final também
conhecido. Uma possível representação gráfica da estrutura de funcionamento de um laço
de repetição for poderá ser visualizada na Figura 53. No início da execução da estrutura
será inicializada uma variável. Após isto, o valor dessa variável será verificado na condição,
na representação gráfica do losango, e enquanto essa condição for verdadeira o bloco
de instruções será executado dentro da estrutura. Somente quando a condição se tornar
falsa é que a execução será desviada para o final da estrutura do laço. O incremento ou
decremento do valor da variável será essencial para que o laço tenha uma saída (encerre),
caso contrário, a execução nunca sairá do laço.
A instrução for muitas vezes poderá ser representada com uma while equivalente
da maneira descrita na Figura 56.
Figura 56. Sintaxe da instrução de repetição for representada por while. Elaborado pelo autor.
Figura 58. Saída do código apresentado no exemplo da Figura 57. Elaborado pelo autor.
Caro (a) aluno (a), com a finalidade de ampliar o conhecimento voltado à programação
orientada a objetos, ofereço a você como sugestão para leitura este artigo que trata dos
quatro pilares da programação orientada a objetos, que são a abstração, encapsulamen-
to, herança e o polimorfismo. Estas são as bases da programação orientada a objetos,
quando se tem a perfeita compreensão sobre elas, você poderá ter um desenvolvimento
de software melhor e com maior facilidade na hora de programar.
Link do site:
https://www.devmedia.com.br/os-4-pilares-da-programacao-orientada-a-objetos/9264
REFLITA
“Algumas pessoas acham que foco significa dizer sim para a coisa em que você vai se
focar. Mas não é nada disso. Significa dizer não às centenas de outras boas ideias que
existem. Você precisa selecionar cuidadosamente.” (Steve Jobs).
Inspirado em uma das maiores mentes da computação, Steve Jobs, hoje é o dia certo
para estudar, trabalhar, buscar algo novo. Mas, não devemos fazer isso tentando abra-
çar o mundo, ou seja, tentando fazer tudo ao mesmo tempo, mas sim, um de cada vez,
porém de forma completa e totalmente envolvida. Assim, priorizar será a competência
que você deverá aprimorar, somente assim será capaz de ir além e fazer coisas que
outros não podem.
Hoje é o dia!
Faça o hoje valer a pena, fazendo boas escolhas!
Referência:
https://www.tecmundo.com.br/internet/3145-frases-impactantes-sobre-tecnologia-e-in-
formatica.htm
LIVRO
Título: Estruturas de Dados & Algoritmos em Java
Autor: Michael T. Goodrich, Roberto Tamassia.
Editora: Bookman | ARTMED Editora.
Sinopse: Este livro oferece uma introdução a estruturas de dados
e algoritmos, incluindo projeto, análise e implementação. Em
um texto simples e claro, os autores utilizam recursos visuais e
cenários do mundo real, focando as funções mais populares na
análise de algoritmos.
FILME/VÍDEO
Título: Os pilares da Programação Orientada a Objetos.
Ano: 2018.
Sinopse: A Orientação a Objetos é um dos paradigmas de análise
e desenvolvimento de softwares mais utilizados na atualidade.
Ele se baseia na representação dos elementos do mundo real e
nas interações entre eles, que se refletem no projeto na forma de
classes e métodos. Para que isso seja possível esse paradigma
conta com quatro pilares que serão explicados neste DevCast:
abstração, herança, polimorfismo e encapsulamento.
Link do vídeo: https://www.devmedia.com.br/os-pilares-da-
programacao-orientada-a-objetos/38384
Plano de Estudo:
Objetivos de Aprendizagem:
68
INTRODUÇÃO
Esta unidade inicia os estudos com uma breve introdução ao conceito e a utilização
dos comandos de uma linguagem orientada a objetos. Você verá nesta unidade que a API
String torna a codificação de caracteres transparente para você. O Unicode também é
compatível com ASCII. Você poderá se aprofundar no conceito sobre o sistema de tipos de
uma linguagem de programação, descrevendo como seus elementos de dados (variáveis e
constantes) estão associados ao armazenamento real.
Uma das maneiras pelas quais o Java suporta acesso internacional é através da
codificação de caracteres Unicode. Unicode usa uma codificação de caracteres de 16
bits. É um padrão mundial que suporta os scripts (conjuntos de caracteres) da maioria dos
idiomas.
Ainda segundo Kalinovsky (2004), o código-fonte Java pode ser escrito usando a
codificação de caracteres Unicode e armazenado em seu formato completo de 16 bits ou
com valores de caracteres Unicode codificados em ASCII. Isso torna o Java uma linguagem
amigável para programadores que não falam inglês, que podem usar seu alfabeto nativo
para nomes de classes, métodos e variáveis, no código Java. O tipo char de Java e os
objetos String também suportam Unicode.
Mas se você está preocupado em ter que trabalhar com caracteres de dois bytes,
pode relaxar. A API String torna a codificação de caracteres transparente para você. O
A maioria das plataformas não pode exibir todos os caracteres Unicode, atualmente
definido. Como resultado, os programas Java podem ser gravados com sequências de
escape Unicode especiais. Um caractere Unicode pode ser representado com essa
sequência de escape:
\ uxxxx
1.2. Comentários
Figura 59. Exemplo de comentários em bloco e em linha única. Elaborado pelo autor.
1.4. Tipos
Schildt(2013) trata uma classe como um código que descreve um tipo específico
de objeto. Ele especificará os dados que um objeto poderá conter (os campos de objetos) e
as ações que um objeto poderá executar (os métodos do objeto). Você poderá pensar em
uma classe como um projeto de código que poderá ser usado para criar um tipo específico
de objeto. Ela serve a um propósito semelhante ao do projeto de uma casa.
O projeto em si não é uma casa, mas uma descrição detalhada de uma casa. Quando
usamos o projeto para construir uma casa real, poderíamos dizer que estamos construindo
uma instância da casa descrita pelo projeto. Se assim o desejarmos, poderemos construir
várias casas idênticas a partir do mesmo projeto. Cada casa é uma instância separada da
casa descrita pelo projeto. Exemplo este apresentado na Figura 61.
Então, uma classe não é um objeto, mas uma descrição de um objeto. Quando um
programa está em execução, ele pode usar a classe para criar, na memória, tantos objetos
de um tipo específico quanto necessário. Cada bate-papo de objeto é criado a partir de uma
classe é chamado de instância da classe.
2.1. Objetos
Se você já dirigiu um carro, sabe que um carro é composto por muitos componentes.
Com uma linguagem orientada a objetos, como o Java, você poderá criar programas
que transmitem a programação. No entanto, em um dispositivo IMM (Integrated Management
Module - Módulo de Gerenciamento Integrado), como um volante ou um pedal de freio. É
um componente de software que existe na memória do computador e executa uma tarefa
específica. No software, um objeto tem dois recursos gerais:
Até agora, os objetos que você usou em seus programas são criados a partir de
classes na API Java. Por exemplo, toda vez que você criar um objeto Scanner, você criará
uma instância de uma classe chamada Scanner, que está na API Java. Da mesma forma,
quando você cria um objeto Random, está criando uma instância de uma classe denominada
Random, que está na API Java. O mesmo é verdadeiro para o objeto do PrintWriter. Quando
Observe a Listagem de código da Figura 62, um programa que usa todos esses
tipos de objetos.
1. Na linha 18, ele está criando uma instância da classe Scanner e atribuindo o
• Na linha 28, o método nextlnt do objeto Scanner é chamado para ler a entrada
do usuário (que é a quantidade de números aleatórios a serem gerados). O
valor retornado do método será atribuído à variável maxNumbers;
• Na linha 35, o método nextlnt do objeto Random será chamado para obter um
inteiro aleatório. O valor retornado do método será atribuído à variável numérica;
• Na linha 38, o método println do objeto PrintWriter será chamado para gravar o
valor da variável numérica no arquivo;
• Na linha 41, o método close do objeto PrintWriter é chamado para fechar o
arquivo.
Uma declaração com o modificador public poderá ser acessada de qualquer lugar
e por qualquer entidade que possa visualizar a classe a que ela pertença.
A classe e/ou seus membros serão acessíveis somente por classes do mesmo
pacote, na sua declaração não será definido nenhum tipo de modificador, sendo este
identificado pelo compilador.
Tucker(2009) também trata sobre a criação de uma variável que poderá ser acessada
por todas as instâncias de objetos desta classe como uma variável comum, ou seja, a
variável criada será a mesma em todas as instâncias e quando seu conteúdo é modificado
numa das instâncias, a modificação ocorre em todas as demais. E nas declarações de
métodos ajudam no acesso direto à classe, portanto não é necessário instanciar um objeto
para acessar o método.
Tucker(2009) ainda trata sobre o modificador final e descreve que o mesmo confere
«terminalidade” ao processo de herança, isto é, uma classe ao receber o modificador final
representará que chegou ao nível máximo de especialização e não poderá mais ser
especializada. Um exemplo clássico de classe final é a java.lang.String. A classe String,
por se tratar de um tipo de dado, foi definida como uma classe final. Outro motivo para o
uso do modificador final é a segurança, dado que quando a classe for identificada como
sendo a String, se trata da classe java.lang.String propriamente dita e não de uma possível
classe herdeira, a qual pode ter sofrido alterações e apresentar funcionalidades alteradas.
Por sua vez, quando aplicado aos métodos, o modificador final garante que este
não será sobrescrito, o que implica que o método declarado como final terá o seu protótipo
mantido tal qual foi definido e, quando for chamado por um dos objetos da classe (ou
de classes herdeiras), seu código é que será executado. Dessa forma, nenhuma classe
herdeira será capaz de sobrescrever um método definido como final.
Os atributos finais que não foram inicializados em sua declaração devem ser
inicializados no método construtor, como descrito nas linhas 8, 9, 10, 14, 15 e 16. Neste
Quando uma variável volatile sofrer qualquer mudança de valor por algum thread,
tal alteração será realizada diretamente na memória principal. Em um bloco ou método
sincronizado, qualquer alteração de valor de uma variável será realizada na memória cache
da JVM. Esta ação, em algumas situações, pode levar a uma inconsistência de dados
quando um thread realizar a leitura em uma variável compartilhada. Para exemplificar o
efeito do uso do modificador volatile, a Figura 71 apresenta um exemplo da ausência deste
operador em uma variável num, à qual é compartilhada entre dois threads. Por outro lado,
a Figura 73 exibe o mesmo código, porém fazendo uso desse modificador.
Figura 72. Saída da execução do código da Figura 70. Elaborado pelo autor.
Pode-se notar que os valores exibidos pela Thread1 e pela Thread2 são 10 e 20,
respectivamente. Isto ocorre porque a modificação será realizada apenas no cache local
dos threads. Para que ambas as threads leiam e escrevam na mesma variável num alocada
na memória principal, é preciso adicionar o modificador volatile na declaração da variável.
Deste modo, ao executar o código da Figura 73, obterá um resultado semelhante ao
apresentado na Figura 74.
Figura 74. Saída da execução do código da Figura 73. Elaborado pelo autor.
Segundo Furgeri (2018), na linguagem Java se um construtor não for definido, será
assumido um construtor default da própria linguagem, em que as variáveis serão inicializadas
com os conteúdos default, onde as variáveis numéricas receberão zero, valores lógicos
receberão false e objetos receberão null. O construtor deverá possuir sempre o mesmo
nome de sua classe e será sintaticamente semelhante a um método, quando for declarado.
Uma classe poderá conter de 0 a N construtores declarados ou definidos, dependendo
das suas necessidades. Usaremos normalmente, um construtor para fornecer valores
iniciais para as variáveis de instâncias definidas pela classe ou para executar algum outro
procedimento de inicialização necessário à criação de um objeto totalmente formado.
Será possível declarar seu próprio construtor a fim de especificar como objetos
de uma classe devem ser inicializados. A seguir, demonstraremos uma classe com vários
construtores sobrecarregados que permitem que objetos dessa classe sejam inicializados
de diferentes maneiras. Para sobrecarregar construtores, simplesmente forneça múltiplas
declarações de construtor com assinaturas diferentes.
A classe Time2 das Figuras 76, 77, 78 e 79 contém cinco construtores sobrecarregados
que fornecem maneiras convenientes de inicializar objetos. Nesse programa, quatro dos
construtores invocam um quinto, o qual, por sua vez, garante que o valor fornecido para
hora está no intervalo de 0 a 23, e os valores para minute e second estão, cada um, no
intervalo de 0 a 59. O compilador invoca o construtor apropriado correspondendo o número,
tipos e a ordem dos tipos dos argumentos especificados na chamada do construtor com o
número, tipos e a ordem dos tipos dos parâmetros especificados em cada declaração de
construtor. A classe Time2 também fornece os métodos set() e get() para cada variável de
Figura 76. Classe Time2 com construtores sobrecarregados. Elaborado pelo autor.
Figura 77. Classe Time2 com construtores sobrecarregados (continuação). Elaborado pelo autor.
As linhas 47 a 51, na Figura 77, declaram um construtor Time2 que recebe uma
referência para outro objeto Time2. Os valores do argumento Time2 são passados para o
construtor de três argumentos nas linhas 30 a 44 para inicializar hora, minuto e segundo.
A linha 50, na Figura 77, poderia ter acessado diretamente os valores de hora, minuto e
segundo do argumento time com as expressões time.hora, time.minuto e time. segundo,
mesmo que hora, minuto e segundo sejam declarados como variáveis private da classe
Time2. Isso se deve a um relacionamento especial entre objetos da mesma classe. Veremos
mais adiante por que é preferível usar os métodos get.
O método setTime() nas linhas 56 a 70, nas Figuras 77 e 78, lança uma
IllegalArgumentException nas linhas 59, 62 e 65, na Figura 77, se quaisquer argumentos
do método estiverem fora do intervalo. Do contrário, ele definirá as variáveis de instância de
Time2 como os valores de argumento (linhas 67 a 69 da Figura 78).
Figura 81. Saída da listagem do código da Figura 80. Elaborado pelo autor.
Quando uma classe herda características de outra classe, ela poderá implementar
partes específicas não contempladas na classe original - superclasse - tornando-se
especializada em algum processo.
No mundo real, você poderá encontrar muitos objetos que serão versões
especializadas de outros objetos mais gerais. Por exemplo, o termo inseto descreve um tipo
muito geral de criatura com numerosas características. Porque gafanhotos e abelhas são
insetos, eles têm todas as características gerais de um inseto. Além disso, eles possuem
características especiais próprias. Por exemplo, o gafanhoto tem sua habilidade de saltar, e
o zangão tem seu ferrão. Gafanhotos e abelhas são versões especializadas de um inseto.
Isso é ilustrado na Figura 82.
Além das características comuns dos insetos, o zangão tem suas próprias
características únicas, como a capacidade de picar e o gafanhoto tem suas próprias
características únicas, como a capacidade de pular.
Figura 84. Saída da listagem do código da figura 83. Elaborada pelo autor.
Figura 85. Sintaxe de uma declaração class que herda uma superclasse. Elaborada pelo autor.
Você só poderá especificar uma única superclasse para qualquer subclasse que
criar. A linguagem de programação Java não dá suporte à herança de várias superclasses
na mesma subclasse. Você poderá criar, no entanto, uma hierarquia de herança em que
uma subclasse passe a ser uma superclasse de outra subclasse. Nenhuma classe poderá
ser a superclasse de si mesma.
Com frequência a variável de instância de uma classe será declarada como private
para não poder ser usada sem autorização ou adulterada. Quando for herdada uma classe,
não invalida a restrição de acesso private. Mesmo que uma subclasse inclua todos os
membros de sua superclasse, não poderão ser acessados os membros declarados como
private. Por exemplo, largura e altura foram tornadas privadas, em DuasDimensoes,
Figura 86. Membros privados de uma superclasse não podem ser acessados por uma subclasse. Elaborada
pelo autor.
Figura 88. Atribuindo referências de superclasse e subclasse a variáveis de superclasse e subclasse. Elabo-
rada pelo autor.
Figura 89. Saída para listagem de código da Figura 88. Elaborada pelo autor.
Para reforçar o estudo dos conceitos sobre programação orientada a objetos, trazemos
um artigo para você da DevMedia, onde serão mostrados os três principais conceitos do
paradigma da programação Orientada a Objetos, que são o encapsulamento, herança
e o polimorfismo.
https://www.devmedia.com.br/encapsulamento-polimorfismo-heranca-em-java/12991
REFLITA
“A pessoa que chega mais longe é geralmente aquela que está disposta a fazer e ousar.
O barco seguro nunca vai muito longe da margem”. (Dale Carnegie)
Com base neste pensamento de Dale Carnegie, um dos maiores escritores e pensado-
res, que ajudou e ainda ajuda centenas de milhares de pessoas a se desenvolverem
com seu legado deixado a mais de 74 anos, deixo essa mensagem como reflexão para
que você possa chegar mais longe, buscando novos conhecimentos e se desenvolven-
do continuamente.
Referência:
https://citacoes.in/citacoes/608433-dale-carnegie-a-pessoa-que-chega-mais-lon-
ge-e-geralmente-aquela/
Caro(a) aluno(a)!
Nosso objetivo foi trazer os conceito e exemplos para facilitar o entendimento de
um dos mais usado paradigma de programação na atualidade, a orientada a objetos.
Com uma rápida introdução aos conceitos e suas aplicações, você pôde ver uma breve
a utilização dos comandos de uma linguagem orientada a objetos e mesclando a estes
comandos tratamos sobre os conceitos envolvidos. Você pôde ver nesta unidade que a API
String possibilita a codificação de caracteres mais transparente.
Foi apresentado um estudo mais aprofundado e específico sobre os conceitos
avançados sobre classes e seus modificadores de acesso a classes e seus membros. Pôde
ver também que uma Classe é um código que descreve um tipo específico de objeto. Pôde
ver que ele especifica os dados que um objeto poderá conter e as ações que um objeto
poderá executar, através do estudo de sua estrutura com exemplos práticos demonstrados
nesta unidade.
Com a utilização de estudos dirigidos, você pôde analisar os exemplos apresentados
que os modificadores de acesso são padrões de visibilidade de acessos às classes, atributos
e métodos. Você pôde verificar que os modificadores são palavras reservadas que não
poderão ser usadas como nome de métodos, classes ou atributos.
Outro ponto importante nessa unidade foi uma abordagem mais aprofundada a
respeito dos construtores e que é possível declarar seu próprio construtor a fim de especificar
como objetos de uma classe devem ser inicializados.
Além disso, também foi apresentada uma abordagem sobre herança com a
generalização e especialização. Você pôde constatar que linguagem de programação Java
sempre dará suporte à herança permitindo que uma classe incorpore outra classe em sua
declaração.
Neste livro, da disciplina de Programação Orientada a Objetos, veio acompanhada
de exemplos na linguagem de Programação Java. Recomendamos que você aprofunde
seus conhecimentos dessa linguagem através das dicas das leituras complementares, pois
a prática conduz ao aperfeiçoamento. Portanto estude e pratique constantemente! Somente
com dedicação ao estudo e a prática, você se tornará um excelente profissional.
Na próxima unidade vamos estudar sobre os Encapsulamento de Propriedades, a
utilização de Interfaces, Captura e Tratamento de Erros e Exceções e muito mais.
Não fique parado, e entre nesse mundo da Programação Orientado a Objetos com
a gente!
Até a próxima unidade!
LIVRO
• Título: Programação orientada a objetos: Conceitos e técnicas
• Autor: Sérgio Furgeri
• Editora: Editora Érica
• Sinopse: Esta obra explica conceitos básicos de POO e
apresenta à instanciação de objetos, encapsulamento, escopo de
classe e instância, construtores e pacotes. Fornece visão geral
sobre recursos da orientação a objetos como herança, classes
abstratas e concretas, polimorfismo e interfaces. Discorre sobre
os elementos essenciais à compreensão da modelagem de
sistemas. Aborda recursos e ferramentas necessários em projetos
de sistemas orientados a objetos. Descreve os gerenciadores
de banco de dados e a linguagem SQL. Mostra as arquiteturas
em camadas, lógica e física. Contempla recursos de segurança
que devem estar presentes no desenvolvimento de sites, como
a validação de formulários, autenticação com login, sessões,
criptografia e arquivos de log. Comenta ainda a segurança de
transações na web, analisando algumas tecnologias importantes,
como certificação digital, OTP e IPT. O conteúdo pode ser
aplicado para os cursos técnicos ou de tecnologia em Informática,
Informática para Internet, Manutenção e Suporte em Informática,
Programação de Jogos Digitais, entre outros. Possui material de
apoio.
FILME/VÍDEO
Título: Design Patterns: Soluções para Problemas em Projetos
Orientados a Objetos.
Ano: 2018.
Sinopse: Nesse pocket vídeo abordaremos os padrões de
projetos na sua essência. Não é o objetivo deste pocket ensinar
a implementar os padrões de projetos em uma determinada
linguagem de programação, pelo contrário, a proposta é justamente
esquecer linguagem ou mesmo código e focar no que realmente
os padrões de projeto se propõe a ser. Iniciaremos conhecendo
um pouco da história da programação orientada a objetos e na
sequência a história dos padrões de projeto. Conheceremos um
pouco sobre o GOF (Gang of Four) e qual a sua parcela de “culpa”
na criação destes padrões. Em seguida veremos os 23 padrões e
sua classificação em criacionais, estruturais e comportamentais. É
fato que ninguém se torna um especialista em padrões de projetos
com apenas 45 minutos de vídeo por este motivo encerramos
nosso pocket com uma lista de referências para dar continuidade
aos estudos, algumas destas referências são leituras obrigatórias
para todo aquele que quer de fato se tornar um desenvolvedor
especializado em orientação a objetos, independente da linguagem.
Link do vídeo:
https://www.devmedia.com.br/design-patterns-solucoes-para-
problemas-em-projetos-orientado-a-objetos/31266
Plano de Estudo:
1. ENCAPSULAMENTO DE PROPRIEDADES
2. UTILIZANDO INTERFACES
3. CAPTURA E TRATAMENTO DE EXCEÇÕES
4. DESENVOLVIMENTO EM CAMADAS
5. CONSIDERAÇÕES FINAIS
6. REFERÊNCIAS
Objetivos de Aprendizagem:
● Conceituar e contextualizar a importância da utilização do encapsulamento de
propriedades.
● Compreender os tipos de interfaces que podem ser usadas em uma aplicação.
● Estabelecer a importância da captura e tratamento das exceções.
● Conhecer o desenvolvimento em camadas e alguns padrões de Desenvolvimento.
114
INTRODUÇÃO
Esta unidade inicia os estudos com uma breve introdução ao conceito e a utilização
do encapsulamento dentro da linguagem orientada a objetos. Você verá nesta unidade que
o encapsulamento é um mecanismo de programação que vincula o código e os dados que
ele trata, e isso mantém os dois seguros contra a interferência e a má utilização externa.
Com o estudo mais aprofundado sobre a utilização de interfaces. Você verá que
elas funcionam de maneira bastante similar a classes abstratas, porém não permitirão
implementações de nenhum método, contendo apenas a especificação deste.
E verá também que captura e tratamento das exceções indica um problema que
ocorre quando um programa for executado. O nome “exceção” sugere que o problema
ocorrerá com pouca frequência, se a “regra” é: uma instrução normalmente executará
corretamente, então o problema representará a “exceção à regra”.
Para determinar o nível de acesso dos elementos de uma classe, serão usados os
qualificadores de acesso, já citados em unidade anteriores:
• public: um nível sem restrições, equivalente a não encapsular, ou seja, se uma
variável for definida como pública, não será possível realizar o encapsulamento;
• private: o nível de maior restrição em que apenas a própria classe poderá ter
acesso às variáveis e/ou métodos;
• protected: um nível intermediário de encapsulamento em que as variáveis e
métodos poderão ser acessados pela própria classe ou por suas subclasses;
• package: nível em que a classe poderá ser acessada apenas por outras classes
pertencentes ao mesmo pacote.
Por meio das restrições de acesso é possível assegurar que certas variáveis de
instância tenham valores restritos que só poderão ser acessados a partir da própria classe,
mantendo certa segurança com relação à integridade do valor armazenado.
Conforme demonstrado até aqui, as variáveis declaradas na classe foram
acessadas diretamente pelos objetos por meio da sintaxe nome_do_objeto.nome_da_
variável ou diretamente por meio da classe quando o atributo era estático. Considerando
Para identificar algum erro relacionado à manipulação dos salários dos funcionários,
será necessário verificar o código de todos os arquivos da pasta onde a classe Funcionario
estiver definida. Quanto maior o número de arquivos, menos eficiente será a manutenção
da aplicação. Poderemos obter um controle centralizado tornando o atributo salario privado
e definindo métodos para implementar todas as lógicas que utilizam ou modificam o valor
desse atributo.
Figura 92. Exemplo de uma classe Funcionario com o atributo privado salario. Elaborada pelo autor.
Um atributo privado só poderá ser acessado ou alterado por código escrito dentro
da classe na qual ele foi definido. Se algum código fora da classe Funcionario tentar acessar
ou alterar o valor do atributo privado salario, um erro de compilação será gerado.
Para garantir que métodos auxiliares não sejam chamados por código escrito fora
da classe na qual eles foram definidos, poderemos torná-los privados, acrescentando o
modificador private.
Figura 96. Exemplos de alteração das propriedades de um objeto com métodos get e set.
Elaborada pelo autor.
Veja que existe a palavra reservada “interface” no lugar de “class”, mas o arquivo
deverá ser salvo da mesma forma que uma classe. Vamos elaborar um exemplo mais
real para entendermos melhor. Veja o diagrama da Figura 98. Ele mostra duas possíveis
representações para uma interface de acordo com a UML:
• Uma representação similar à de uma classe (veja a interface DAO) contendo o
estereótipo <<interface>>. Isso permitirá diferenciar visualmente uma interface
de uma classe, já que a representação gráfica é a mesma. Essa representação
Figura 98. Diagrama das interfaces DAO e Estoque. Elaborada pelo autor.
Observe na linha 1 a forma utilizada em Java para vincular uma classe a uma
interface: trata-se do uso da palavra “implements”. Quando o compilador analisar essa linha,
ele identificará que a classe Cliente precisará implementar todos os métodos definidos na
interface DAO, inclusive seguindo a mesma assinatura. Se qualquer um dos métodos não
existir na classe Cliente, o compilador apresentará um erro. Em outras palavras, você poderá
interpretar a linha 1 como se fosse um contrato: “Eu, classe Cliente, aceito implementar
Uma vez que tanto a classe Cliente quanto a classe Fornecedor precisam
implementar os mesmos métodos (com os mesmos nomes), é possível construir um código
mais padronizado. Imagine se para inserir dados num banco de dados a classe Cliente
definisse o método inserir(), a classe Fornecedor definisse o método inclui() e outra classe
qualquer definisse o método inserirRegistro(). Veja que bagunça seria!
Como já dissemos, uma classe poderá implementar mais de uma interface ao mesmo
tempo. Esse é o caso da classe Produto, que implementará os métodos das interfaces DAO
e Estoque. O princípio será o mesmo; bastará adicionar todas as interfaces após a palavra
“implements”, separadas por vírgulas. Veja o exemplo na Figura 102.
Kalinovsky(2004) indica que uma exceção indica um problema que ocorre quando
um programa for executado. O nome “exceção” sugere que o problema ocorrerá com pouca
frequência, se a “regra” é: uma instrução normalmente executará corretamente, então
o problema representará a “exceção à regra”. O tratamento de exceção ajudará a criar
programas tolerantes às falhas que poderão resolver (ou tratar) exceções.
Kalinovsky(2004) também trata sobre exceções. E para lidar com elas, coloque
qualquer código que possa lançar uma exceção em uma instrução try (linhas 17 a 26 da
Goodrich(2013) cita que o MVC não foi criado para ser somente um padrão de
projeto, ele na verdade é uma arquitetura de projeto onde seu objetivo é separar seu código
em três camadas fazendo com que cada área só trabalhe com itens que competem à elas.
Trocando em miúdos, cada um só faz o que foi desenvolvido para fazer. Com o MVC você
facilmente transformará seu código de modo a ficar muito mais legível. Para utilizá-lo você
terá que ter em mente que haverá uma separação em seu código, as regras de negócio
ficarão separadas da lógica e da interface do usuário.
4.2.1. M de Model
4.2.2. V de View
O controle faz exatamente o que o nome diz: controla. Ele é o responsável por fazer
o intermédio entre o modelo e a visão. É o responsável também por toda lógica do sistema.
Retornando somente os itens necessários para a comunicação entre o modelo e a visão.
Entre o usuário e a aplicação.
A linguagem Java possui classes que permitem a conexão com bancos de dados,
as quais fazem parte do pacote JDBC (Java Database Connectivity), uma API (Aplication
Program Interface) que permite a comunicação com diversos Sistemas Gerenciadores de
Bancos de Dados, como Oracle, MySQL, SQL Server, PostgreSQL, entre outros. Existe
também a possibilidade de se utilizar uma bases de dados relacional open source chamado
Java DB, um banco criado a partir do projeto Apache Derby. Independentemente do banco
de dados usada, a linguagem padrão para manipulação dos dados é a SQL (Structured
Query Language).
Ainda conforme Jacobi(2006), a JPA (Java Persistence API) define uma maneira
padrão de mapear as classes Java para seus pares de bancos de dados relacionais. Esse
O JPA permite que você especifique e execute consultas e atualize dados sem
precisar gravar instruções SQL. A Java Persistence API permite mapear classes Java
para tabelas de banco de dados usando metadados e executar operações de criação,
recuperação, atualização e exclusão (CRUD) usando Java Persistence Query Language
(JPQL), Persistence Criteria API e consultas de banco de dados nativas na linguagem SQL.
A ideia é criar um modelo de domínio específico do aplicativo como um conjunto de classes
Java inter-relacionado e mapeá-lo para o armazenamento de dados correspondente (o
RDBMS).
Se uma classe Java marcada com a anotação @Entity não tiver um construtor de
argumento, você poderá chamá-la de entidade. Cada instância da entidade corresponde a
uma linha em uma tabela de banco de dados, conforme mostrado aqui: @Entity public class
Employee {
...
}
Se você iniciar com um banco de dados vazio, as ferramentas JPA permitem criar
tabelas de banco de dados baseadas em entidades Java. Você também poderá mapear
entidades Java para as tabelas de banco de dados existentes. Assim como as tabelas do
banco de dados, as entidades Java podem ter relacionamentos um-para-um (como uma
entidade Employee com uma entidade OfficeAddress correspondente), relacionamentos
um-para-um (como um cliente com muitos pedidos), muitos-para-um (o oposto de
relacionamentos um-para-muitos) e relacionamentos muitos-para-muitos (por exemplo,
uma UniversityClass tem muitos alunos matriculados, mas cada aluno pode se inscrever
em várias classes).
Embora o JPQL forneça uma sintaxe semelhante a SQL baseada em string para
trabalhar com entidades, a mais recente API Criteria permite que você construa consultas
dinamicamente a partir de objetos fortemente tipados.
Jacobi(2006) também trata sobre o Java Server Faces como uma grande evolução
na época de sua criação. o JSF chegou pela primeira vez no estágio de tecnologia da Internet
em meados de 1999 como o novo padrão para a criação de aplicativos da Web baseados
em Java, ele recebeu grande atenção da comunidade de desenvolvimento da Web Java EE
na época. As interfaces de usuário para esses aplicativos da Web, são geralmente criadas
com tecnologias como HTML, CSS, JavaScript e o DOM. Essas tecnologias não foram
desenvolvidas tendo em mente os aplicativos corporativos e, com uma pressão crescente
dos consumidores para fornecer aplicativos com recursos não totalmente descritos
ou suportados por essas tecnologias, os desenvolvedores estão procurando soluções
alternativas ou para estender os padrões.
O Java Server Faces (JSF) é uma estrutura de interface com o usuário (UI) para
aplicativos da Web Java. Ele foi projetado para aliviar significativamente a carga de gravar
e manter aplicativos executados em um servidor de aplicativos Java e renderizar suas
interfaces de usuário para um cliente de destino.
O diferencial que o JSF traz, é que outros frameworks semelhantes não possuem
o suporte de uma especificação padrão. Como o JSF faz parte da especificação padrão
J2EE, será uma prioridade para todos os principais fornecedores de ferramentas J2EE no
mercado (incluindo Oracle, IBM, Borland e Sun) suportá-lo, o que, por sua vez, garantirá
uma ampla adoção e boas ferramentas de apoio.
https://www.devmedia.com.br/design-patterns-na-teoria-e-na-pratica/32168
REFLITA
“Algumas pessoas acham que foco significa dizer sim para a coisa em que você vai se
focar. Mas não é nada disso. Significa dizer não às centenas de outras boas ideias que
existem. Você precisa selecionar cuidadosamente.” (Steve Jobs).
Inspirado em uma das maiores mentes da computação, Steve Jobs, hoje é o dia certo
para estudar, trabalhar, buscar algo novo. Mas, não devemos fazer isso tentando abra-
çar o mundo, ou seja, tentando fazer tudo ao mesmo tempo, mas sim, fazendo uma coi-
sa de cada vez, porém de forma completa e totalmente envolvida. Assim, priorizar será
a competência que você deverá aprimorar, somente assim será capaz de ir além e fazer
coisas que outros não poderão fazer.
Hoje é o dia!
Faça o hoje valer a pena, fazendo boas escolhas!
Referência:
https://www.tecmundo.com.br/internet/3145-frases-impactantes-sobre-tecnologia-e-in-
formatica.htm
Você pôde ver e estudar nesta unidade uma introdução ao conceito e a utilização
do encapsulamento dentro da linguagem orientada a objetos. Além de um estudo mais
aprofundado sobre a utilização de interfaces.
Você pode ver e estudar também que captura e tratamento das exceções indica
um problema que ocorre quando um programa for executado. Você teve também uma
abordagem mais aprofundada a respeito de desenvolvimento em camadas.
Caro (a) Aluno (a), mais uma vez gostaria de parabenizá-lo pelo esforço e a
dedicação para chegar até aqui. Desejo a cada um vocês todo o sucesso que a vida pode
lhes proporcionar.
LIVRO
Título: Padrões de Projetos: Soluções Reutilizáveis de Software
Orientados a Objetos
Autor: Erich Gamma, Richard Helm, Ralph Johnson, John
Vlissides.
Editora: Bookman Companhia Editora.
Sinopse: Capturando uma vasta experiência sobre o design de
software orientado a objetos, quatro designers de primeira linha
apresentam um catálogo de soluções simples e sucintas para
problemas comuns de projeto. Anteriormente não documentados,
esses 23 padrões permitem que os designers criem designs
mais flexíveis, elegantes e, por fim, reutilizáveis, sem precisar
redescobrir as próprias soluções de design.
Os autores começam descrevendo quais são os padrões e como
podem ajudá-lo a projetar software orientado a objetos. Em seguida,
eles nomeiam, explicam, avaliam e catalogam sistematicamente
projetos recorrentes em sistemas orientados a objetos. Com o
Designs Patterns como seu guia, você aprenderá como esses
padrões importantes se encaixam no processo de desenvolvimento
de software e como você pode aproveitá-los para resolver seus
próprios problemas de design com mais eficiência.
Cada padrão descreve as circunstâncias em que é aplicável,
quando pode ser aplicado em vista de outras restrições de projeto,
e as consequências e desvantagens de usar o padrão dentro
de um design maior. Todos os padrões são compilados a partir
de sistemas reais e são baseados em exemplos do mundo real.
Cada padrão também inclui código que demonstra como ele pode
ser implementado em linguagens de programação orientadas a
objetos, como C ++ ou Smalltalk.
FILME/VÍDEO
• Título: Introdução a Design Patterns
• Ano: 2017
• Sinopse: Neste curso conheceremos os Design Patterns: teremos
uma visão geral sobre padrões de projetos e princípios de design.
Também iniciaremos a construção de um código funcional em Java
no NetBeans para reservas de quartos, justificando a necessidade
de utilização do princípio de programar para uma interface e não
para uma implementação. Conheceremos os 23 Design Patterns
descritos no livro GOF, que serve de base para esse curso.