Perguntas da entrevista sobre Java
1. Introdução
Este artigo contém respostas para algumas das perguntas mais importantes da entrevista de emprego sobre o Java principal. As respostas para algumas delas podem não ser óbvias, portanto este artigo ajudará a esclarecer as coisas.
2. Perguntas sobre a linguagem Java principal para iniciantes
Q1. Os dados são transmitidos por referência ou por valor em Java?
Embora a resposta a essa pergunta seja bastante simples, essa pergunta pode ser confusa para iniciantes. Primeiro, vamos esclarecer sobre o que se trata:
-
Passing by value – significa que passamosa copy of an object como um parâmetro em um método.
-
Passing by reference – significa que passamosa reference to an object como um parâmetro em um método.
Para responder à pergunta, temos que analisar dois casos. Eles representam dois tipos de dados que podemos passar para um método: um primitivo e um objeto.
Quando passamos as primitivas para um método, seu valor é copiado para uma nova variável. Quando se trata de objetos, o valor da referência é copiado para uma nova variável. So we can say that Java is a strictly pass-by-value language.
Podemos aprender mais sobre isso em um de nossos artigos:Pass-By-Value as a Parameter Passing Mechanism in Java.
Q2. Qual é a diferença entre importação e importação estática?
Podemos usar importações regulares para importar uma classe específica ou todas as classes definidas em um pacote diferente:
import java.util.ArrayList; //specific class
import java.util.*; //all classes in util package
Também podemos usá-los para importar classes públicas aninhadas de uma classe anexa:
import com.example.A.*
No entanto, devemos estar cientes de que a importação acima não importa a classeA em si.
Existem também importações estáticas que nos permitem importar membros estáticos ou classes aninhadas:
import static java.util.Collections.EMPTY_LIST;
O efeito é que podemos usar a variável estática EMPTY_LIST sem preceder o nome completo da classe, ou seja, como se fosse declarado na classe atual.
Q3. Quais modificadores de acesso estão disponíveis em Java e qual é o seu objetivo?
Existem quatro modificadores de acesso emJava:
-
privado
-
default (pacote)
-
protegido
-
público
The private modifier assures that class members won’t be accessible outside the class. Pode ser aplicado a métodos, propriedades, construtores, classes aninhadas, mas não às próprias classes de nível superior.
Ao contrário do modificadorprivate, podemos aplicar o modificadordefault a todos os tipos de membros da classe e à própria classe. Podemos aplicar a visibilidadedefault não adicionando nenhum modificador de acesso. If we use default visibility our class or its members will be accessible only inside the package of our class. Devemos ter em mente que o modificador de acesso padrão não tem nada em comum com a palavra-chavedefault.
De forma semelhante ao modificadordefault, todas as classes dentro de um pacote podem acessar membrosprotected. What’s more, the protected modifier allows subclasses to access the protected members of a superclass, even if they are not within the same package. Não podemos aplicar este modificador de acesso às classes, apenas aos membros da classe.
O modificadorpublic pode ser usado junto com a palavra-chave class e todos os membros da classe. It makes classes and class members accessible in all packages and by all classes.
Podemos aprender mais no artigoJava Access Modifiers.
Q4. Quais outros modificadores estão disponíveis em Java e qual é o seu objetivo?
Existem outros cinco modificadores disponíveis em Java:
-
estático
-
final
-
abstrato
-
sincronizado
-
volátil
Estes não controlam a visibilidade.
Em primeiro lugar, podemos aplicar a palavra-chavestatic a campos e métodos. Static fields or methods are class members, whereas non-static ones are object members. Os membros da classe não precisam de nenhuma instância para ser invocada. Eles são chamados com o nome da classe em vez do nome de referência do objeto. This article entra em mais detalhes sobre a palavra-chavestatic.
Então, temos a palavra-chavefinal. Podemos usá-lo com campos, métodos e classes. When final is used on a field, it means that the field reference cannot be changed. Portanto, não pode ser reatribuído a outro objeto. When final is applied to a class or a method, it assures us that that class or method cannot be extended or overridden. A palavra-chavefinal é explicada com mais detalhes emthis article.
A próxima palavra-chave éabstract. Este pode descrever classes e métodos. When classes are abstract, they can’t be instantiated. Em vez disso, eles devem ser subclasses. Quando os métodos sãoabstract, eles são deixados sem implementação e podem ser substituídos nas subclasses.
A palavra-chavesynchronized pode ser a mais avançada. Podemos usá-lo com a instância, bem como com métodos estáticos e blocos de código. When we use this keyword, we make Java use a monitor lock to provide synchronization on a given code fragment. Mais informações sobresynchronized podem ser encontradas emthis article.
A última palavra-chave que discutiremos évolatile. Só podemos usá-lo junto com os campos da instância. It declares that the field value must be read from and written to main memory – bypassing the CPU cache. Todas as leituras e gravações de uma variável volátil são atômicas. A palavra-chave volatile é explicada em detalhes emthis article.
Q5. Qual é a diferença entre JDK, JRE e JVM?
JDK significaJava Development Kit, que é um conjunto de ferramentas necessárias para os desenvolvedores escreverem aplicativos em Java. Existem três tipos de ambientes JDK:
-
Standard Edition - kit de desenvolvimento para criar aplicativos portáteis de desktop ou servidor
-
Enterprise Edition - uma extensão da Standard Edition com suporte para computação distribuída ou serviços da web
-
Micro Edition - plataforma de desenvolvimento para aplicativos embarcados e móveis
Existem várias ferramentas incluídas no JDK quehelp programmers with writing, debugging or maintaining applications. Os mais populares são um compilador (javac), um interpretador (java), um arquivador (jar) e um gerador de documentação (javadoc).
JRE é umJava Runtime Environment. É uma parte do JDK, masit contains the minimum functionality to run Java applications. Ele consiste emJava Virtual Machine, classes principais e arquivos de suporte. Por exemplo, não tem nenhum compilador.
JVM é a sigla paraJava Virtual Machine, que é uma máquina virtual capaz de executar programas compilados em bytecode. É descrito pela especificação JVM, pois é importante garantir a interoperabilidade entre diferentes implementações. The most important function of a JVM is to enable users to deploy the same Java application into different operating systems and environments without worrying about what lies underneath.
Para mais informações, vamos verificar o artigoDifference Between JVM, JRE, and JDK.
Q6. Qual é a diferença entre Stack e Heap?
Há duas partes da memória em que todas as variáveis e objetos são armazenados pela JVM. O primeiro é ostacke o segundo é oheap.
Ostack is a place where the JVM reserves blocks for local variables and additional data. A pilha é uma estruturaLIFO (último a entrar, primeiro a sair). Isso significa que sempre que um método é chamado, um novo bloco é reservado para variáveis locais e referências a objetos. Cada nova invocação de método reserva o próximo bloco. Quando os métodos concluem sua execução, os blocos são liberados da maneira inversa em que foram iniciados.
Cada novo thread tem sua própria pilha.
Devemos estar cientes de que a pilha possui muito menos espaço de memória que a pilha. E quando uma pilha estiver cheia, a JVM lançará umStackOverflowError. É provável que ocorra quando há uma chamada recursiva ruim e a recursão é muito profunda.
Every new object is created on the Java heap which is used for a dynamic allocation. Existe umgarbage collector que é responsável por apagar objetos não utilizados que são divididos em espaços jovens (berçário) e antigos. O acesso da memória ao heap é mais lento que o acesso à pilha. A JVM lança umOutOfMemoryError quando o heap está cheio.
Podemos encontrar mais detalhes no artigoStack Memory and Heap Space in Java.
Q7. Qual é a diferença entre as interfacesComparable andComparator?
Às vezes, quando escrevemos uma nova classe, gostaríamos de poder comparar objetos dessa classe. É especialmente útil quando queremos usar coleções ordenadas. Existem duas maneiras de fazer isso: com a interfaceComparable ou com a interfaceComparator.
Primeiro, vamos dar uma olhada na interfaceComparable:
public interface Comparable {
int compareTo(T var1);
}
Devemos implementar essa interface pela classe cujos objetos queremos classificar.
Possui o métodocompareTo()e retorna um inteiro. Ele pode retornar três valores: -1, 0 e 1, o que significa que esse objeto é menor que, igual ou maior que o objeto comparado.
Vale a pena mencionar que o métodocompareT0() substituído deve ser consistente com o métodoequals().
Por outro lado, podemos usar a interfaceComparator. Ele pode ser passado para os métodossort() da interfaceCollection ou ao instanciar coleções classificadas. É por isso que é usado principalmente para criar uma estratégia de classificação única.
Além do mais, também é útil quando usamos uma classe de terceiros que não implementa a interface Comparable.
Como o métodocompareTo(), os métodoscompare() substituídos devem ser consistentes com o métodoequals(), mas podem opcionalmente permitir a comparação com nulos.
Vamos visitar o artigoComparator and Comparable in Java para mais informações.
Q8. Qual é o tipo devoid e quando o usamos?
Toda vez que escrevemos um método em Java, ele deve ter um tipo de retorno. Se quisermos que o método não retorne nenhum valor, podemos usar a palavra-chavevoid.
Também devemos saber que existe uma classeVoid. É uma classe de espaço reservado que pode ser usada, por exemplo, ao trabalhar com genéricos. A classeVoid não pode ser instanciada nem estendida.
Q9. Quais são os métodos da classe Object e o que eles fazem?
É importante saber quais métodos a classeObject contém e como eles funcionam. Também é muito útil quando queremos substituir esses métodos:
-
clone() - retorna uma cópia deste objeto
-
equals() - retornatrue quando este objeto é igual ao objeto passado como parâmetro
-
finalize() - o coletor de lixo chama este método enquanto está limpando a memória
-
getClass() - retorna a classe de tempo de execução deste objeto
-
hashCode() - retorna um código hash deste objeto. We should be aware that it should be consistent with the equals() method
-
notify() - envia uma notificação para um único thread esperando pelo monitor do objeto
-
notifyAll() - envia uma notificação para todos os threads esperando pelo monitor do objeto
-
toString() - retorna uma representação de string deste objeto
-
wait() - existem três versões sobrecarregadas deste método. Ele força o thread atual a aguardar a quantidade de tempo especificada até que outro thread chamenotify() ounotifyAll() neste objeto.
Q10. O que é um Enum e como podemos usá-lo?
Enum é um tipo de classe que permite aos desenvolvedores especificar um conjunto de valores constantes predefinidos. Para criar tal classe, temos que usar a palavra-chaveenum. Vamos imaginar uma enumeração dos dias da semana:
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
Para iterar sobre todas as constantes, podemos usar o métodovalues() estático. Além do mais, enums nos permitem definir membros, como propriedades e métodos, como classes regulares.
Although it’s a special type of class, we can’t subclass it. Um enum pode, entretanto, implementar uma interface.
Outra vantagem interessante deEnums é que eles são thread-safe e, portanto, são usados popularmente como singletons.
Podemos encontrar mais sobre Enums emone of our guides.
Q11. O que éa JAR?
JAR é um atalho paraJava archive. É um arquivo compactado usando o formato de arquivo ZIP. Podemos usá-lo para incluir os arquivos de classe e os recursos auxiliares necessários para os aplicativos. Possui muitos recursos:
-
Security – podemos assinar digitalmente arquivos JAR
-
Compression – ao usar um JAR, podemos compactar arquivos para armazenamento eficiente
-
Portability – podemos usar o mesmo arquivo JAR em várias plataformas
-
Versioning – arquivos JAR podem conter metadados sobre os arquivos que eles contêm
-
Sealing – podemos lacrar um pacote dentro de um arquivo JAR. Isso significa que todas as classes de um pacote devem ser incluídas no mesmo arquivo JAR
-
Extensions – podemos usar o formato de arquivo JAR para empacotar módulos ou extensões para software existente
Q12. O que éaNullPointerException?
ONullPointerException é provavelmente a exceção mais comum no mundo Java. É uma exceção não verificada e, portanto, estendeRuntimeException. Não devemos tentar lidar com isso.
Essa exceção é lançada quando tentamos acessar uma variável ou chamar um método de referência nula, como quando:
-
invocando um método de uma referência nula
-
definindo ou obtendo um campo de uma referência nula
-
verificando o comprimento de uma referência de matriz nula
-
configurando ou obtendo um item de uma referência de matriz nula
-
jogandonull
Q13. Quais são os dois tipos de transmissão em Java? Qual exceção pode ser lançada durante a transmissão? Como podemos evitá-lo?
Podemos distinguir dois tipos de conversão em Java. We can do upcasting which is casting an object to a supertype or downcasting which is casting an object to a subtype.
Upcasting é muito simples, pois sempre podemos fazer isso. Por exemplo, podemos fazer o upcast de uma instânciaString para o tipoObject:
Object str = "string";
Alternativamente, podemosdowncast uma variável. Não é tão seguro quanto o upcasting, pois envolve uma verificação de tipo. Se lançarmos incorretamente um objeto, a JVM lançará umClassCastExcpetion no tempo de execução. Fortunately, we can use the instanceof keyword to prevent invalid casting:
Object o = "string";
String str = (String) o; // it's ok
Object o2 = new Object();
String str2 = (String) o2; // ClassCastException will be thrown
if (o2 instanceof String) { // returns false
String str3 = (String) o2;
}
Podemos aprender mais sobre fundição de tipoin this article.
3. Perguntas sobre a linguagem Java principal para programadores avançados
Q1. Por que String é uma classe imutável?
Devemos saber que os objetosString são tratados de forma diferente dos outros objetos peloJVM. Uma diferença é que os objetosString são imutáveis. It means that we can’t change them once we have created them. Existem vários motivos pelos quais eles se comportam dessa forma:
-
Eles são armazenados emstring pool, que é uma parte especial da memória heap. É responsável por economizar muito espaço.
-
A imutabilidade da classeString garante que seu código hash não mudará. Due to that fact, Strings can be effectively used as keys in hashing collections. Podemos ter certeza de que não substituiremos nenhum dado devido a uma mudança nos códigos hash.
-
Eles podem ser usados com segurança em vários segmentos. No thread can change the value of a String object, so we get thread safety for free.
-
As strings são imutáveis para evitar sérios problemas de segurança. Dados confidenciais, como senhas, podem ser alterados por uma fonte não confiável ou outro encadeamento.
Podemos aprender mais sobre a imutabilidade de Stringsin this article.
Q2. Qual é a diferença entre ligação dinâmica e ligação estática?
A ligação em Java é um processo de associação de uma chamada de método ao corpo do método apropriado. Podemos distinguir dois tipos de ligação em Java: estático e dinâmico.
A principal diferença entre a vinculação estática e a vinculação dinâmica é que a vinculação estática ocorre em tempo de compilação e a vinculação dinâmica em tempo de execução.
Static binding usa informações de classe para vinculação. É responsável por resolver os membros da classe que são métodos e variáveisprivate oustaticefinal. Além disso, a ligação estática vincula métodos sobrecarregados.
Dynamic binding, por outro lado, usa informações do objeto para resolver ligações. É por isso que é responsável por resolver métodos virtuais e substituídos.
Q3. O que é o JIT?
JIT significa “just in time”. É um componente do JRE que é executado no tempo de execução e aumenta o desempenho do aplicativo. Specifically, it’s a compiler which runs just after the program’s start.
Isso é diferente do compilador Java comum que compila o código muito antes do aplicativo ser iniciado. O JIT pode acelerar o aplicativo de diferentes maneiras.
Por exemplo, o compilador JIT é responsável por compilar o bytecode em instruções nativas dinamicamente para melhorar o desempenho. Além disso, ele pode otimizar o código para a CPU e o sistema operacional de destino.
Além disso, ele tem acesso a muitas estatísticas de tempo de execução que podem ser usadas para recompilação para um desempenho ideal. Com isso, ele também pode fazer algumas otimizações de código global ou reorganizar o código para melhor utilização do cache.
Q4. O que é reflexão em Java?
A reflexão é um mecanismo muito poderoso em Java. A reflexão é um mecanismo da linguagem Java que permite aos programadores examinar ou modificar o estado interno do programa (propriedades, métodos, classes etc.) em tempo de execução. O pacote java.lang.reflect fornece todos os componentes necessários para o uso da reflexão.
Ao usar esse recurso, podemos acessar todos os campos possíveis, métodos, construtores incluídos em uma definição de classe. Podemos acessá-los, independentemente do seu modificador de acesso. Isso significa que, por exemplo, somos capazes de acessar membros privados. Para fazer isso, não precisamos saber seus nomes. Tudo o que precisamos fazer é usar alguns métodos estáticos deClass.
Vale a pena saber que existe a possibilidade de restringir o acesso por reflexão. Para fazer isso, podemos usar o gerenciador de segurança Java e o arquivo de política de segurança Java. Eles nos permitem conceder permissões para as classes.
Ao trabalhar com módulos desde Java 9, devemos saber que, por padrão, não podemos usar reflexão em classes importadas de outro módulo. Para permitir que outras classes usem a reflexão para acessar os membros privados de um pacote, temos que conceder a permissão "Reflexão".
This article aprofunda mais sobre o Java Reflection.
Q5. O que éa Classloader?
Oclassloader é um dos componentes mais importantes em Java. Faz parte do JRE.
Simplificando, o classloader é responsável por carregar classes na JVM. Podemos distinguir três tipos de carregadores de classe:
-
Bootstrap classloader – carrega as classes Java principais. Eles estão localizados no diretório<JAVA_HOME>/jre/lib
-
Extension classloader – carrega classes localizadas em<JAVA_HOME>/jre/lib/ext ou no caminho definido pela propriedadejava.ext.dirs
-
System classloader – carrega classes no classpath de nosso aplicativo
Um carregador de classes carrega classes "sob demanda". Isso significa que as classes são carregadas após serem chamadas pelo programa. Além do mais, um carregador de classe pode carregar uma classe com um determinado nome apenas uma vez. No entanto, se a mesma classe for carregada por dois carregadores de classes diferentes, essas classes falharão em uma verificação de igualdade.
Há mais informações sobre carregadores de classe no artigoClass Loaders in Java.
Q6. Qual é a diferença entre carregamento de classe estática e dinâmica?
O carregamento de classe estática ocorre quando temos classes de origem disponíveis em tempo de compilação. Podemos fazer uso dele criando instâncias de objeto com a palavra-chavenew.
O carregamento de classe dinâmica se refere a uma situação em que não podemos fornecer uma definição de classe no momento da compilação. No entanto, podemos fazer isso em tempo de execução. Para criar uma instância de uma classe, temos que usar o métodoClass.forName():
Class.forName("oracle.jdbc.driver.OracleDriver")
Q7. Qual é o objetivo da interfaceSerializable?
We can use the Serializable interface to enable serializability of a class, using Java’s Serialization API. A serialização é um mecanismo para salvar o estado de um objeto como uma sequência de bytes, enquanto a desserialização é um mecanismo para restaurar o estado de um objeto a partir de uma sequência de bytes. A saída serializada contém o estado do objeto e alguns metadados sobre o tipo do objeto e os tipos de seus campos.
Deveríamos saber que subtipos de classes serializáveis também são serializáveis. No entanto, se queremos tornar uma classe serializável, mas seu supertipo não é serializável, temos que fazer duas coisas:
-
implementar a interfaceSerializable
-
garantir que um construtor sem argumento esteja presente na superclasse
Podemos ler mais sobre serialização emone of our articles.
Q8. Existe um destruidor em Java?
Em Java, o coletor de lixo exclui automaticamente os objetos não utilizados para liberar a memória. Os desenvolvedores não precisam marcar os objetos para exclusão, o que é propenso a erros. So it’s sensible Java has no destructors available.
Caso os objetos contenham sockets abertos, arquivos abertos ou conexões de banco de dados,the garbage collector is not able to reclaim those resources. Podemos liberar os recursos emclose method e usartry-finally syntax para chamar o método antes do Java 7, como as classes de E / SFileInputStreamandFileOutputStream. As of Java 7, we can implement interface AutoCloseable and use try-with-resources statement to write shorter and cleaner code. Mas é possível que os usuários da API se esqueçam de chamar o métodoclose , então o métodofinalize e o métodoCleaner passam a existir para atuar como a rede de segurança. But please be cautioned they are not equivalent to the destructor.
It’s not assured both the finalize method and Cleaner class will run promptly. Eles ainda não têm chance de serem executados antes da saída da JVM. Embora pudéssemos chamarSystem.runFinalization to sugerir que a JVM execute os métodosfinalize de quaisquer objetos pendentes para finalização, ainda é não determinístico.
Além disso, o métodofinalize pode causar problemas de desempenho, deadlocks etc. Podemos encontrar mais informações em um de nossos artigos:A Guide to the finalize Method in Java.
As of Java 9,Cleaner class is added to replace the finalize method por causa das desvantagens que tem. Como resultado, temos um melhor controle sobre o encadeamento, que executa as ações de limpeza.
Mas a especificação java aponta o comportamento dos limpadores durante a implementação específica deSystem.exit is e o Java não oferece garantias se as ações de limpeza serão chamadas ou não.