Perguntas e Respostas Técnicas sobre Java
1. O que é o Modelo de Memória Java (JMM) e qual seu papel na programação concorrente?
**Resposta:**O Modelo de Memória Java (JMM) é uma abstração que define as regras de acesso a variáveis (especificamente as compartilhadas entre threads) em programas Java e como essas variáveis são visualizadas por diferentes threads em ambientes concorrentes. O JMM estabelece os conceitos de memória principal e memória de trabalho, além das regras de interação entre elas. Na programação concorrente, o JMM garante a atomicidade, visibilidade e ordenação das operações entre threads. Ele permite uma execução paraella razoável enquanto mantém a correção dos resultados do programa. Por exemplo, o uso da palavra-chave volatile baseia-se no JMM para garantir a visibilidade de variáveis.
2. Explique o mecanismo de coleta de lixo em Java e dê exemplos de como otimizá-lo.
**Resposta:**A coleta de lixo (GC) em Java é um mecanismo automático de gerenciamento de memória que recupera a memória ocupada por objetos que não estão mais em uso. O coletor de lixo periodicamente escaneia a memória heap, identificando objetos que não são referenciados por nenhum objeto vivo e liberando a memória por eles ocupada. A otimização da coleta de lixo geralmente envolve reduzir a criação de objetos, usar pools de objetos, selecionar um coletor de lixo adequado e ajustar parâmetros da JVM. Por exemplo, o uso de referências suaves (SoftReference) e fracas (WeakReference) pode criar uma estratégia de gerenciamento de memória mais flexível, permitindo que o coletor de lixo recupere esses objetos quando a memória estiver escassa.
3. Em Java, o que são referências fortes, suaves, fracas e fantasma? Quais são suas diferenças?
**Resposta:**Em Java, as referências são classificadas em quatro tipos:
- Referência Forte: Se um objeto possui uma referência forte, ele nunca será recuperado pelo coletor de lixo.
- Referência Suave: Objetos com referências suaves são recuperados quando a memória está insuficiente, implementadas através da classe
java.lang.ref.SoftReference. - Referência Fraca: Objetos com referências fracas só sobrevivem até a próxima execução do coletor de lixo, usando a classe
java.lang.ref.WeakReference. - Referência Fantasma: O principal propósito das referências fantasma é acompanhar o estado de recuperação de objetos pelo coletor de lixo, implementadas com
java.lang.ref.PhantomReference. Essas referências devem ser usadas com uma fila de referências.
A principal diferença entre elas está na estratégia de tratamento do coletor de lixo, oferecendo diferentes mecanismos de gerenciamento de memória e controle do ciclo de vida dos objetos.
4. Explique o mecanismo de sincronização em Java e demonstre o uso da palavra-chave synchronized com um exemplo.
**Resposta:**O mecanismo de sincronização em Java garante que múltiplas threads possam acessar recursos compartilhados mantendo consistência e segurança. A palavra-chave synchronized pode ser usada para sincronizar métodos ou blocos de código, garantindo que apenas uma thread possa executar aquele trecho de código por vez. Quando uma thread acessa um método ou bloco de código sincronizado de um objeto, ela primeiro obtém o bloqueio daquele objeto. Por exemplo:
public class Contador {
private int valor = 0;
public synchronized void incrementar() {
valor++;
}
public synchronized int obterValor() {
return valor;
}
}
Neste exemplo, os métodos incrementar e obterValor são sincronizados, permitindo que múltiplas threads chamem esses métodos com segurança, sem preocupações com problemas de concorrência.
5. Qual é o mceanismo de carregamento de classes em Java? Descreva seu processo de carregamento.
**Resposta:**O mecanismo de carregamento de classes em Java é o processo pelo qual o ambiente de execução Java carrega dinamicamente arquivos de classes. Esse processo ocorre principalmente em três etapas:
- Carregamento (Loading): O carregador de classes (ClassLoader) localiza o arquivo .com base no nome completo da classe e o carrega na memória.
- Linkagem (Linking): O processo de linkagem inclui a verificação (garantindo que as informações da classe carregada estejam em conformidade com as especificações da JVM), a preparação (alocando memória para variáveis estáticas e definindo valores iniciais padrão) e a resolução (convertendo referências de símbolos para referências diretas).
- Inicialização (Initialization): Nesta fase, a JVM atribui valores iniciais corretos às variáveis de classe e executa blocos de código de inicialização estática.
Esse processo garante a segurança e a estrutura das classes, além de suportar o carregamento e descarregamento dinâmicos de classes.
6. O que são genéricos em Java? Quais são suas vantagens?
**Resposta:**Genéricos em Java são uma tecnologia que permite parametrizar tipos, permitindo verificações de tipo em tempo de compilação, aumentando a reutilização, segurança e legibilidade do código. Genéricos usam parâmetros de tipo ao declarar classes, interfaces ou métodos, que são substituídos por tipos concretos durante a instanciação. As principais vantagens dos genéricos incluem:
- Segurança de tipo: Verificações de tipo em tempo de compilação evitam erros de conversão de tipo em tempo de execução.
- Eliminação de conversões de tipo: O uso de genéricos evita conversões de tipo, tornando o código mais limpo.
- Maior reutilização de código: Genéricos permitem escrever classes e métodos que não dependem de tipos específicos, aumentando a reutilização do código.
Por exemplo, uma ArrayList genérica:
ArrayList<String> lista = new ArrayList<>();
lista.add("Olá");
String valor = lista.get(0); // Uso direto do tipo String, sem necessidade de conversão