1.
Java — Geralzão
Marta Laís
Aug 19, 2018·11 min read
Java é complicado, isso é fato. Sair de Python (saudades) para Java é um senhor pulo. Decidi reunir todos os
meus 1.000 resumos em apenas um.
Esse resumo do assunto de Java, com foco na Orientação à Objetos, é bem geral, como o título já insinua.
Coloquei os pontos que julguei mais importantes e, claro, memes, como boa jovem dinâmica que sou.
Resolvi disponibilizar no medium, vai que é útil para mais alguém — além dos ex-feras de CC@UFCG, hahaha.
Tópicos
1. Introdução — Conceitos
2. Métodos Básicos
3. Testes
4. Coleções
5. GRASP — Design
6. Composição
7. Herança
8. Polimorfismo
9. Interface
Introdução — Conceitos
Classe: Um espaço para ter código.
Método: Uma funções a ser executado.
Valor: Dado/Informação bruta.
Tipo: Identifica o valor, semântica.
Public: Determina a visibilidade.
Static: Determina que o que está sendo criado não precisa de contexto.
Void: Determina que não haverá retorno.
Main: Identifica qual código deverá ser invocado quando executado.
Visibilidade: Define explicitamente quem pode acessar o que.
Tipagem estática: É preciso definir os tipos de cada das entidades. Permite a segurança dos testes desse tipo.
Tipagem dinâmica: O tipo de uma entidade é definido pelo tipo atual do valor que ela tem. Permite a
flexibilidade da mudança dinâmica de tipos.
Compilar: Converter um código fonte em código de máquina. É compilado em bytecode pelo javac.
2.
Interpretar: Um interpretador recebe um código linha-a-linha, converte e executa comandos na máquina nativa.
JVM: Um código .class pode rodar em qualquer interpretador java. Existe uma JVM própria para Windows,
outra para Mac, outra para Linux — todas elas são capazes de executar o mesmo .class.
Variáveis: São valores atribuídos no código. Int, double, char…
Tipos estáticos: O tipo é definido.
Tipos primitivos: int, double, char… os tipos mais básicos de java. Todo tipo primitivo é avaliado e comparado
para um valor.
Condicionais: if (condição) {}
Loops: for (inicialização, condição de permanência, incremento) {}
Funções: Trecho de código para ser executado.
Modularização: Isolam um bloco de código pela sua responsabilidade.
Testabilidade: Facilidade em testar cada função de forma isolada.
Arrays: Uma sequência de elementos. Não é uma lista. São alocados de forma contínua, ou seja, cada elemento
existe exatamente após do anterior. É rápido acessar elementos em sequência. Não mudam de tamanho.
Listas: São alocadas de forma não-contínua, cada elemento contém o seu valor e o endereço pro próximo. Para
achar o elemento, passa por mais uma camada de indireção. Tamanho dinâmico.
3.
Objetos: Todo objeto pode ser apontado por várias variáveis ao mesmo tempo e é comparado se apontador para o
mesmo objeto. Modularidade; Plugabilidade; Ocultação e Reuso. Podem ter um determinado estado e ações.
Imports: Pacotes prontos com funções.
Pacotes: Permitem organização do código.
Objetos de Valor: Apenas armazenam o valor.
this: Referência ao atributo/objeto.
Construtor: Método especial chamado para criar o objeto.
Atributo público: Qualquer objeto que use esse atributo, tem controle sobre ele. Isso é ruim pois o controle
sobre o atributo deve ser da própria classe onde ele está inserido. Geram encapsulamento ruim.
Atributo privado + get e set: Isso é bom! Pois sempre que outro código quiser acessar/definir, o método
executado será o get/set. Geram encapsulamento bom.
Escondendo elementos: Ocultação é mostrar apenas o necessário.
Null: Valor especial, aponta para nada.
JUnit: Biblioteca para produção de testes de unidade.
Métodos Básicos
public String toString(){}
Usado para gerar uma representação textual do objeto. Todo objeto tem um toString padrão, mas que pode ser
subscrito.
public boolean equals(Object obj){}
Usado para comparar o objeto atual com outro. Todo objeto tem um equals por padrão, mas você pode
sobrescrever.
public native int hashCode(){}
Representação numérica de um objeto, é um valor que representa o espaço na memória.
Testes
Teste pode ser definido como a investigação que busca gerar informção sobre a qualidade do código. Existem três
grandes áreas: DEVs (desenvolvimento), QU (qualidade) e OPS (operacional e infraestrutura).
Dentro da área de testes, existem duas categorias:
Verificação: “O que eu fiz está correto?”
Validação: “O que eu fiz, era o que eu deveria ter feito?”
Existem, ainda, diversos tipos de testes:
Sistema: Testa o sistema como um todo.
Integração: Testa dois componentes juntos.
4.
Desempenho: Testa tempo de resposta, etc.
Regressão: Testa se o programa continua funcionando depois de alterações.
Aceitação: Testa se o software faz o que o cliente pede.
Usabilidade: testa se o programa é usável.
O JUnit é a biblioteca que serve para produzir testes de unidade em Java.
Coleções
Estrutura de dados: Java oferece uma API — Application Programming Interface — para trabalhar com
estruturas de dados, ou seja, entidade organizadas para armazenar dados.
Generics: Através do Generics é possível indicar qual o tipo de dado que a estrutura de dados carrega. Isso faz
com que a estrutura de dados opere somente com aquele tipo definido.
ArrayList<Aluno> alunos = new ArrayList<>();
Lista
A estrutura de dados mais básica que existem em Java, em específico a ArrayList. É possível pegar elementos
pela posição (get), têm ordem, pode armazenar todo tipo de objeto, aceita elementos repetidos.
Se for um Array (List), é necessário a definição de um tamanho fixo junto a criação do Array.
int[] Lista = new int[10];
Ou seja, o Array tem tamanho fixo e predefinido. Enquanto o ArrayList funciona manipulando Arrays
internamente, fazendo-o mutável.
5.
Funcionamento. Basicamente, ela funciona manipulando um array internamente para armazenar vários
elementos. O ArrayList é um array cujo o tamanho por crescer. A busca por elementos é rápida, enquanto
inserções e exclusões não são, são lineares.
ArrayList alunos = new ArrayList();
ArrayList<Integer> lista = new ArrayList<>(); //GENERICS
List fornece métodos para manipular elementos através da sua posição (índice), procurar ocorrência, remover e
adicionar o elemento.
add, contains, size, iterator, for each.
Quando usar? Armazenar elementos com ordem ou com repetição. Quando se deseja acesso rápido aos
elementos.
Conjuntos
São coleções onde não existem repetições de dados. Caso dois objetos sejam iguais, considerando o método
equals, apenas um será incluído no conjunto. Não pega elementos pela posição, não aceita elementos
repetidos e não tem ordem.
add, contains, size, iterator, for each.
HashSet. É uma representação do conjunto. Internamente ele reserva um espaço na memória para os objetos de
acordo com o hashcode. Para achar se um objeto faz parte da lista, ele pega o hashcode do objeto e procura na
memória.
HashSet<Integer> conjunto = new HashSet<>();
Quando usar? Armazenar elementos únicos, sem repetição e quando a ordem não for importante.
Mapas
HashMap. Associam chave e valor ao elemento. No mapa associa-se uma chave (key) a um valor (value). Cada
chave é única. Não existem chaves repetidas, mas chaves diferentes podem ter o mesmo valor.
HashMap<String, String> apelidos = new HashMap<>();
Quando usar? Se a ordenação não for importante e/ou existir a necessidade de associar um objeto a outro ou a
um “ID”.
6.
GRASP — Design
General Responsibility Assignment Software. Padrões Gerais de Software para a Definição de
Responsabilidade (GRASP) — Forma comum de estruturar o software, com definições de responsabilidades
“quem faz o que”.
Expert (Information) — Quem sabe?
Dada uma responsabilidade — Identifique a informação necessária para realizar tal responsabilidade e escolha
onde colocá-la (qual classe).
A responsabilidade em questão será dessa determinada classe.
Exemplo — No meu sistema, é preciso ter alguém que gere a descrição de um aluno. Para tal, preciso de nome
e matrícula do aluno. Essas informações serão colocadas na classe Aluno. A classe Aluno é responsável por
gerar essa descrição do aluno.
7.
Creator — Quem cria?
Dada uma responsabilidade — Os objetos da classe B criam os objetos da classe A se um ou mais desses itens
abaixo forem verdade:
B contém A;
B agrega A;
B tem os parâmetros para iniciar A;
B grava A;
B usa muito A.
Exemplo — Uma mensagem é algo que faz parte de um canal. O canal faz uso das mensagens para impressão. O
canal tem um conjunto de mensagens. O código de Canal é responsável por criar objetos do tipo Mensagem.
Controller — Quem cuida?
Facade Controller — Entidade controladora que recebe os comandos do usuário e vai delegar (repassar) esses
comandos para métodos em objetos internos.
Session Controller — Entidade controladora que receber e executa os comandos de um usuário com alguma
lógica associada àquele evento.
O main recebe eventos (comandos) do usuário e precisa repassar isso para alguém. Um candidato forte para isto
é um objeto “controlador” que irá controlar a execução (ou até fazer) desses comandos.
Baixo acoplamento — Evitando o ninho de gato.
Definição: Acoplamento é o nível de interdependência entre os módulos (classes) de um software. Quanto mais
baixo esse nível, melhor o código.
Imagine que seja necessário fazer certas alterações do código. Quanto menor for o acoplamento, menos classes
serão afetadas pela alteração.
Alta coesão — Evitando a classe 1001 utilidades.
Definição: Coesão, em computação, representa a medida de quão integra, pura e autocontida um entidade é. Uma
classe deve ter responsabilidade altamente relacionadas e focada.
DRY — Don’t Repeat Yourself.
Definição: Não faça mais de uma vez a mesma coisa (código). Está bastante ligada ao reuso de código.
SRP — Single Responsibility Principle.
Definição: Uma classe deve fazer apenas uma coisa e bem feita. Está bastante ligada à alta coesão.
8.
KIS — Keep It Simple.
Definição: Mantenha as coisas (código) simples. (Keep it simple, stupid).
Composição
Uma classe com composição é, basicamente, um objeto dentro do outro, para agregar informação em comum.
Os objetos do mesmo tipo podem ter uma referência ao mesmo objeto. Elas coexistem uma sem a outra, mas
podem se associar.
Composição também pode ser uma nova classe para delegar funções.
9.
Herança
Herança. A herança é um princípio em POO que permite a criação de novas classes a partir de outras já
criadas. Essas novas classes são chamadas de subclasses, ou classes filhas, classes derivadas. As classes
originais, de onde as subclasses derivam, são chamadas de superclasses ou classes base, classes mãe. Dessa
forma, é possível criar uma hierarquia dessas classes, tornando, assim, classes mais amplas e outras classes mais
específicas.
Uma subclasse, classe filha, herda métodos e atributos de sua superclasse, classe pai. Um objeto instanciado
de uma classe filha tem todos os métodos e atributos da própria classe e de todas as classes da sua
hierarquia. Um método chamado no objeto é procurado primeiro na classe filha, depois nas classes mãe. O
código definido na classe filha só pode usar métodos e atributos protected e public da classe mãe. Só pode
acessar o que é definido no tipo.
Classe abstrata. A classe não pode ser instanciada. Notação <<abstract>> no diagrama.
Atributo protected. O atributo pode ser alterado por um classe filha. Notação # no diagrama.
Método abstrato. A classe filha irá implementar esse método. Notação em itálico no diagrama.
Extends. Especialização das classes. ClasseFilha Extends ClasseMãe.
super. Usado para invocar um método ou construtor da classe mãe.
Sobre a classe-filha:
• Tem todos os atributos e métodos definidos nela mesma e na mãe.
• Um método chamado no objeto é procurado primeiro na classe filha.
• O código definido na classe-filha só pode usar métodos e atributos protected e public da classe-mãe.
• O tipo da referência limita o que pode ser acessado de um objeto.
10.
• Você só pode acessar o que é definido no tipo.
Afinal: pra quê serve herança? Reuso de código e reuso de tipo.
11.
Herança vs. Composição
Herança:
• Tipos bem definidos e objetos que não mudam ao longo da vida.
• Relação de “É UM” para sempre.
• Um gato É UM animal.
Composição:
• Os tipos são parte de um tipo maior.
• Papéis, funções, profissões, estados.
• Relação “TEM UM”, podendo trocar de papel.
• Pessoa TEM UMA função.
Benefícios e Problemas da Herança
• A herança consegue capturar o que é comum e o isola do que é diferente, além disso, ela é vista
diretamente no código.
• Entre os problemas da herança está o fraco encapsulamento entre as classes e subclasses, além de violar a
regra do baixo acoplamento.
12.
Benefícios e Problemas da Composição
• A grande desvantagem é que um software muito dinâmico e parametrizado é mais difícil de entender.
• A grande vantagem da composição é que o comportamento pode ser escolhido em tempo de execução.
• Os objetos que foram instanciados são somente acessados através de sua interface, seguindo assim o
princípio de programar para uma interface.
• A composição também tem um bom encapsulamento, uma vez que os detalhes internos dos objetos
instanciados não são visíveis.
• Menor dependência de implementações e aumenta a coesão.
No geral, é preferível sempre a Composição em relação à Herança, mas deve-se definir algumas regras para
identificar quando é mais adequado usar a Herança de forma que não tenhamos os problemas que ela acarreta.
Deve-se utilizar herança se uma instância de uma classe-filha nunca precisar torna-se um objeto de outra classe,
se a relação for “É UM” e não “TEM UM”.
Polimorfismo
Polimorfismo significa “muitas formas”, ou seja, é o uso do mesmo elemento de formas diferentes — um
objeto pode se comportar de diversas formas diferentes.
ADH — Sobrecarga:
• Se dá quando temos a mesma operação implementada várias vezes da mesma classe.
• A escolha de qual operação será chamada depende da assinatura dos métodos sobrecarregados.
Paramétrico:
• Mesmo tipo com diferentes comportamentos através de parametrização (generics).
• A escolha de qual método será chamado depende do tipo do objeto que recebe a mensagem.
Subtipo:
• Mesmo tipo (pai) com diferentes comportamentos (filhos) através de herança.
Na invocação de “referencia.metodo()” o código de método é procurado na ordem de hierarquia das classes, da
classe-filha para classe-mãe e assim por diante.
A ligação — BINDING — entre a chamada e o código a ser executado é feita de forma tardia — LATE. Java só
decide em tempo de execução — LATE BINDING.
13.
Interface
Define um contrato sem definir estado. Também define um tipo. Pode ter métodos com corpo, mas não podem ter
atributos. Interfaces podem ser pai.
14.
Sempre programe para a interface!
Serializable
• Descreve um objeto que pode ser convertido em uma sequência de bits, para que, assim, possa ser
armazenado em arquivos.
Comparator
• Interface que define a operação de comparação entre dois objetos por um objeto externo.
• É utilizado quando os objetos a serem adicionados não podem ser modificados para aceitarem a interface
Comparable.
• Ou quando é necessária a troca da estratégia de ordenação em tempo de execução.
• Esta interface provê maior flexibilidade, sem custo adicional significativo. Prefira seu uso, ao invés da
interface Comparable.
Comparable
• Interface que define a operação de comparação do própria objeto com outro, usando para definir a ordem
natural dos elementos de uma coleção.
• Pode ser utilizado caso os objetos que serão adicionados na coleção já implementam a interface.
15.
Herança vs. Interface
Herança
• Uma classe só pode herdar de uma outra classe.
Interface
• Uma classe pode implementar várias interfaces.
Parece que tem um bloqueador de anúncios ativo. Ao listar o SlideShare no seu bloqueador de anúncios, está a apoiar a nossa comunidade de criadores de conteúdo.
Odeia anúncios?
Atualizámos a nossa política de privacidade.
Atualizámos a nossa política de privacidade de modo a estarmos em conformidade com os regulamentos de privacidade em constante mutação a nível mundial e para lhe fornecer uma visão sobre as formas limitadas de utilização dos seus dados.
Pode ler os detalhes abaixo. Ao aceitar, está a concordar com a política de privacidade atualizada.