O documento resume conceitos de programação orientada a objetos e estruturas de dados, incluindo modificadores de acesso, herança, polimorfismo, classes abstratas, interfaces, mapas, conjuntos, pilhas, filas e exceções.
2. Github
● Repositório online que usa o Git para o controle de versão
● Arquivos em geral, código, arquivos de texto
● Fork, repos públicos e privados, repos de organizações
● Funciona como uma árvore, usando Branches como seus galhos
● Status, add, commit, push, merge
● Origin, upstream
● É possível fazer continuous deployment da sua branch master ou de alguma de sua
escolha
3. POO - Modificadores de acesso
● Padrões de visibilidade de classes, métodos e atributos. Favorecem o encapsulamento e
proteção dos dados permitindo que as variáveis sejam alteradas apenas por quem
realmente precisa alterar
● Private
○ Modificador de variáveis e métodos
○ Itens anotados com esse modificador não podem ser acessados por outras classes
○ É necessário o uso de getters e setters para alterar o valor
● Protected
○ Torna os membros da classe acessíveis apenas a classes do mesmo pacote ou por herança
○ Por herança, pode-se acessar a partir de outro pacote
4. POO - Modificadores de acesso
● Public
○ Esse modificador permite que a classe ou atributo seja acessada de qualquer lugar e por qualquer
outra classe
● Default
○ Classe e seus membros são acessíveis somente para classes do mesmo pacote
○ Classes e seus membros quando não anotados com algum tipo de modificador, são
automaticamente definidos como Default
5. POO - Modificadores de acesso
● Final
○ Na classe, impede que a classe seja estendida.
○ Nos métodos, impede que eles sejam sobrescritos nas subclasses
○ Nas variáveis, impede que seu valor seja alterado depois de atribuído
○ É necessário atribuir valor a ele no momento da declaração ou no construtor
○ Por convenção, variáveis final devem ser em letras maiusculas e os espaços de uma palavra, se
houverem, substituídos por ” _”
● Abstract
○ Aplicado a classes a métodos
○ Na classe, faz com que ela não possa ser instanciada, chamada pelo seu construtor. Define ela
como um tipo e não uma classe concreta
○ Se algum método for anotado com esse modificador, a classe também deverá ser abstract e deverá
ser sobrescrito na subclasse
6. POO - Modificadores de acesso
● Static
○ Aplicado a variáveis e métodos
○ Facilita o acesso ao item, uma vez que não é necessário instanciar a classe para ter acesso
○ Itens com esse modificador pertencem a classe e não a instância, ou seja, qualquer instância pode
acessar e compartilhar o mesmo recurso
○ Métodos com essa anotação só podem acessar variáveis também static
8. POO - Static methods
● Métodos que pertencem a classe e não a uma instância, assim como as variáveis estáticas
● Podem ser acessados através de métodos estáticos ou em qualquer método usando o
nome da classe
● Só podem acessar variáveis estáticas
● Quando usar?
○ Assim como as variáveis estáticas, os métodos devem ser usados em casos de valores fixos ou que
não sejam alterados com tanta frequência e que várias partes do sistema precisam de acesso a
função daquele método
○ Exemplo de um sistema de empréstimos com a taxa de juros do banco central onde várias partes
do sistema precisam acessar essa taxa
10. POO - Herança
● É uma forma de criar um objeto genérico, do qual outros objetos mais específicos vão se
aproveitar
● É um dos pilares da programação orientada a objetos
● Também é uma maneira de reaproveitar o código, uma vez que informações genéricas
não serão escritas novamente nas classes especializadas
● Classes filhas herdam os métodos e atributos da classe pai, podendo ou não fazer uso
desses métodos
● Herança é feita por meio da palavra reservada “extends”
● Herança pode ocorrer em classes abstratas e também em concretas
13. POO - Polimorfismo de sobrescrita
● Polimorfismo está muito relacionado com a herança
● É o comportamento de uma função ser diferente para objetos distintos, mas continua
sendo a mesma função de uma mesma classe Pai
● É implementar apenas a assinatura do método, podendo personalizar ele para o problema
a ser solucionado
15. POO - Polimorfismo de sobrecarga
● O polimorfismo de sobrecarga acontece quando temos o mesmo método na classe, mas
com assinaturas diferentes
● O mesmo método recebe um parâmetro String, outrora recebe um inteiro, um lógico e
por aí vai…
● Pode receber, inclusive, mais de um parâmetro
17. POO - Classes abstratas
● Classes abstratas são aquelas que idealizam um tipo, descrevem um modelo de algo
● Não podem ser instanciadas, por exemplo.: Pessoa p = new Pessoa()
● Podem ter variáveis, construtores e métodos como todas as classes
● O funcionamento é bem parecido com as classes concretas onde ocorre herança, porém,
os métodos abstratos das classes abstratas são somente assinados, sem código para
executar
● Os métodos abstratos precisam, obrigatoriamente, ser sobrescritos nas classes que irão
estender nossa classe abstrata
19. POO - Interface
● Serve como um substituto de classes abstratas, quando não são necessários atributos
● Possui métodos, sem código a ser executado
● Possui variáveis também, mas são public, static e final
● Serve também como um contrato, as classes que assinam esse contrato (implementam),
estão obrigadas a sobrescrever os métodos da interface
● Uma classe pode implementar várias interfaces ao mesmo tempo
● Uma interface é implementada através da palavra reservada “implements”
● Interfaces diminuem o acoplamento ao passo que são uma abstração
22. Estruturas de dados - Map
● Estrutura associativa baseada em chave - valor
● Não permite duplicação de chaves
● Em caso de duplicação, o valor inserido por último é que será gravado
● Pode ser iterado pela chave, pelo valor
● Deve ser especificado o tipo de dado que será a chave e o valor
● É possível inserir (put), buscar (get), deletar (remove), contar (size)
23. Map - HashMap
● É uma classe que implementa a interface Map
● Armazena os valore com chaves, mas não guarda de forma ordenada
24. Map - LinkedHashMap
● Também implementa a interface Map, mas ordena os dados na ordem de entrada
25. Map - TreeMap
● Também implementa a interface Map, mas também implementa a interface Comparable
● Podemos fazer sort e por padrão o sort é feito pela ordem natural
26. Estruturas de dados - Set
● Interface que estende Collection
● Coleção não ordenada que armazena objetos
● Valores iguais não são aceitos, apenas o adicionado primeiro é guardado
● As classes que implementam Set são:
○ HashSet - Guarda os dados não ordenados
○ LinkedHashSet - Guarda os dados na ordem de inserção
○ TreeSet - Guarda os dados ordenados e implementa a interface Comparable
28. Estruturas de dados - Stack
● Estrutura de pilha
● Podemos inserir push(), remover pop(), verificar se o item está lá search(), verificar se a
pilha está vazia ou não
● A pilha apaga primeiro o último objeto adicionado, política conhecida como LIFO (Last In
First Out)
29. Estruturas de dados - Queue
● Estrutura de fila
● Implementa a interface Collections e por isso tem todos os métodos como add, remove,
size e outros.
● A fila apaga sempre o primeiro item na ordem, ela segue a política de FIFO (First In First
Out)
● Normalmente é utilizada com as classes concretas LinkedList, ArrayBlockingQueue ou
PriorityQueue, essa última serve pra mudar a ordem da Queue através do método
comparator
31. Exceptions
● Exceptions são eventos não esperados que ocorrem durante a execução de um programa
● Estes erros podem ser por entrada de dados inválidos, problemas ao ler ou escrever
arquivos, acesso à bancos de dados
● Se não tratados, podem ocasionar a derrubada do serviço, que inviabilizaria a operação
de uma empresa, por exemplo
● Existem duas classificações
○ Implícitas
■ São aquelas que normalmente são causadas por erro de programação. Por exemplo, um
“for” que vai além do tamanho do array. Tem origem das subclasses Error ou
RunTimeException
○ Explícitas
■ São aquelas que não podem ser contornadas por programação, que não foram erros de
programação. Por exemplo, um arquivos corrompido ou algo assim.
33. Exceptions
● As subclasses de RunTimeException precisam de Try/Catch ou de declaração
throw/throws porque não são erros de programação, então se faz necessário capturar
essa exception
● Throw é diferente de throws porque ao usar throw estamos criando um objeto de alguma
exception e throws é usada para “avisar” que aquela operação pode gerar tal exception
● Podemos usar Throw para lançar uma exception personalizada que nós criamos e assim
mostrar uma mensagem um pouco mais descritiva do que estamos fazendo
34. Exceptions - blocos try/catch/finally
● O bloco Try tenta executar o código escrito, caso ocorra alguma
Exception o bloco Catch entra em ação
● Podem existir mais de um bloco Catch, cada um responsável
por capturar uma exception epecífica
● Caso nenhum bloco catch consiga capturar a exception, é
causada uma interrupção no sistema dependendo do tipo de
exception
● No bloco catch podemos usar printStackTrace() para “printar” na tela todos os dados do
erro. Podemos usar getStackTrace() para pegar esse dado e escolher o que fazer com ele.
Podemos também usar o getMessage() para pegar uma lista de erros em formato de
String
37. Acesso por referência e cópia
● Variáveis de referência são variáveis que apontam para objetos que estão na memória
● Ao usar por exemplo Carro carro1 = new Carro("VW"); estamos solicitando ao SO que grave o
objeto de Carro em um espaço na memória.
Então ao usar a variável carro1 para alterar a marca de um carro, por exemplo, estamos
usando o endereço na memória que é a nossa referência de onde está o objeto de Carro.
● Podemos fazer com que mais de uma variável aponte para esse endereço. Basta atribuir a
uma variável do tipo Carro esse nosso objeto de Carro. Por exemplo, Carro
carroReferenciaCarro1 = carro1;
● Assim, ao alterarmos qualquer item, tanto em carro1 como em carroReferenciaCarro1, o que
vai estar sendo alterado, na verdade, é o objeto de Carro que já estava guardado na
memória
39. Acesso por referência e cópia
● Ao passarmos um objeto ou uma variável comum como argumento em um método,
estamos fazendo uma cópia dos parâmetros e trabalhando com a cópia dentro do método
● Mas há uma diferença, nesse caso, entre uma variável e um objeto.
O objeto traz a referência na memória, então fazemos uma cópia da referência, mas a
cópia ainda faz referência ao local original, então qualquer alteração no método será
replicada na memória
● Em variáveis comuns isso não acontece porque temos um valor no lugar de uma
referência, então estaremos trabalhando na cópia e isso não ocasionará nenhuma
mudança no valor original da variável
41. Acesso por referência e cópia
● Há ainda uma maneira de clonar um objeto usando o método clone()
● Esse método só é usado se implementarmos Cloneable na classe a ser clonada
● Fazendo o clone, estaremos trazendo um objeto idêntico e não uma referência
● Todas as alterações serão feitas apenas no clone, pois ele estará alocado em outro espaço
na memória
● O perigo é a classe clonada ter uma referência a outra classe, assim o clone também terá e
isso pode ser uma falha de segurança ou até mesmo um causador de erros na aplicação
● Não implementar Cloneable causará uma exception do tipo CloneNotSupportedException
43. Mutable
● Mutable diz respeito a tudo que pode ser mudado depois de criar um objeto, uma variável
ou um software em si
● Alterar a marca de um carro que está na classe Carro , receber valores de um usuário para
fazer uma conta. Tudo isso diz respeito a mutabilidade, poder mudar o estado ou valores
● Adicionar itens a uma lista, por exemplo, é um exemplo de mutable List
44. Immutable
● Immutable objects são aqueles que não tem seu estado alterado depois que são criados
● Muito úteis em ambiente de multithread porque podem ser compartilhados sem muita
preocupação
● Para criar um objeto imutável é necessário que não haja Setters, campos devem ser final e
private
● Se existirem campos que são mutáveis, faça cópia defensiva e retorne aquela cópia a cada
nova requisição
● Declare a classe e métodos também como final, assim a classe não poderá ser estendida e
os métodos não poderão ser sobrescritos
46. Threads
● Threads são subprocessos de um processo (programa) que podem trabalhar
paralelamente
● Podemos executar apenas um método em uma thread ou uma classe inteira
● O benefício desse tipo de processamento é que podemos fazer várias coisas ao mesmo
tempo, otimizando o tempo e entregando o resultado com mais rapidez para o usuário
● Ao usar threads, devemos ter cuidado com os dados que são utilizados, pois o
programador não tem controle sobre o escalonador de processos do SO, então não
sabemos a ordem de execução
● Podemos usar threads implementando a interface Runnable, estendendo a classe Thread
ou instanciando a classe Thread em um método e sobrescrevendo o método run()
47. Threads
● As threads tem um ciclo de vida, que vai de New até Terminated passando por Runnable,
Blocked, Waiting e Timed_Waiting
● Em alguns casos precisamos ter uma ordem de execução de threads, para isso podemos
usar threads synchronized, assim uma thread espera que outra encerre sua operação
para iniciar
● É possível ainda usar a interface Callable para usar threads com retorno e captura de
exceptions
50. Semaphores
● Semaphores é um mecanismo que usa um contador para permitir ou negar acesso a
recursos
● Ao compartilhar um recurso com várias threads, às vezes é necessário que o acesso a ele
seja controlado
● Um semaphore conta 1 para acesso permitido e 0 para negado
● Quando uma thread acessa o recurso, o semaphore decrementa e fica em 0, logo,
qualquer outra thread que quiser o recurso terá que aguardar
● Quando a thread que tem acesso ao recurso terminar seu trabalho, ela encerra o acesso e
o semaphore incrementa e sobe para 1, liberando o acesso para outra thread
● Ao instanciar um Semaphore, podemos dizer quantas threads podem acessar o recurso
simultaneamente
51. Semaphores
● Para solicitar acesso a um recurso, é necessário utilizar o método acquire() e para
encerrar o acesso, utilizamos o método release()
● No construtor do semaphore podemos dizer quantas threads podem usar um recurso e
também que ordenamos a fila de espera ou não
● Setamos true no construtor para dizer que o acesso será concedido por ordem de
chegada na fila de espera, false ou nada para que seja aleatório
54. Synchronized
● É uma maneira de regular o acesso de threads a um recurso, para isso podemos usar a
palavra reservada synchronized ou usar o bloco synchronized(this) dentro do método
● O bloco marcado com synchronized só pode ser acessado por uma thread de cada vez
● Ao tentar acessar um bloco synchronized que já está sendo usado, a thread é inserida em
um espaço (não ordenado) de espera
● Assim que o método for liberado, outra thread poderá acessar
● Diferentemente dos semaphores que bloqueiam o método durante toda a execução da
thread, o synchronized bloqueia o acesso ao método, independente de ter encerrado a
thread ou não