JavaRush /Blogue Java /Random-PT /Análise de perguntas e respostas de entrevistas para dese...

Análise de perguntas e respostas de entrevistas para desenvolvedor Java. Parte 8

Publicado no grupo Random-PT
Prática ou teoria? O que é mais importante? Muitos dirão que, claro, a prática é mais importante. Tipo, pratique o máximo que puder e você será feliz. Atrevo-me a discordar disso. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 1Durante as entrevistas, ninguém saberá o quão bom você é na prática. Você será questionado detalhadamente, precisamente de acordo com a teoria. E só então, quando você passar por todas as rodadas de entrevistas e entrar no projeto, você usará suas habilidades práticas. Você pode objetar: às vezes eles lhe dão uma tarefa de teste e ainda é necessária prática. Não discuto, às vezes são dadas, mas o fato é que ÀS VEZES, mas SEMPRE acontece uma entrevista teórica. Você sente a diferença? Portanto, você deve ter uma base teórica sólida sob seus pés, que continuaremos fortalecendo hoje. Ou seja, continuaremos a analisar perguntas que são frequentemente feitas durante as entrevistas.

71. O que acontece se não substituirmos o método toString() para Enum?

Digamos que temos o seguinte enum :
public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;
}
Vamos exibir o aluno no console chamando toString() nele :
System.out.println(Role.STUDENT.toString());
Resultado no console:
ESTUDANTE
Ou seja, por padrão, toString() para enum é o nome da própria constante.

72. É possível especificar um construtor dentro de um Enum?

Sim, claro. É através do construtor que são definidos os valores das variáveis ​​enum internas. Como exemplo, vamos adicionar dois campos à enumeração anterior - ageFrom e ageTo - para indicar a faixa etária de cada função:
public enum Role {
   STUDENT(5,18),
   TEACHER(20,60),
   DIRECTOR(40,70),
   SECURITY_GUARD(18,50);

   int ageFrom;
   int ageTo;

   Role(int ageFrom, int ageTo) {
       this.ageFrom = ageFrom;
       this.ageTo = ageTo;
   }
}

73. Qual é a diferença entre == e igual()?

Esta é uma das perguntas mais comuns das entrevistas com desenvolvedores Java. Vamos começar com o fato de que quando comparamos valores simples ( int , char , double ...), fazemos isso usando == , pois as variáveis ​​​​contêm valores específicos e podemos compará-los. E variáveis ​​primitivas não são objetos completos - elas não herdam de Object e não possuem um método equals() . Quando falamos em comparar variáveis ​​que se referem a objetos, == comparará apenas o valor das referências - sejam elas referentes ao mesmo objeto ou não. E mesmo que um objeto seja idêntico a outro, a comparação via == dará um resultado negativo ( false ), pois este é um objeto diferente. Como você entende, o método equals() é usado para comparar variáveis ​​de referência . Este é um dos métodos padrão da classe Object , necessário para uma comparação completa de objetos. Mas vale esclarecer desde já: para que esse método funcione corretamente, ele precisa ser redefinido escrevendo exatamente como os objetos dessa classe devem ser comparados. A menos que você substitua o método, por padrão ele comparará objetos por == . No IntelliJ IDEA , você pode substituí-lo automaticamente (usando as ferramentas IDEA) -> alt + insert , na janela que aparece, selecione equals() e hashCode() -> selecione quais campos de classe devem participar -> e pronto, implementação automática de os métodos estão concluídos. Aqui está um exemplo de como seria um método equals gerado automaticamente para uma classe Cat simples com dois campos - int age e String name :
@Override
public boolean equals(final Object o) {
   if (this == o) return true;
   if (o == null || this.getClass() != o.getClass()) return false;
   final Cat cat = (Cat) o;
   return this.age == cat.age &&
           Objects.equals(this.name, cat.name);
}
Se falarmos sobre a diferença entre == e equals para enums , não há muito disso. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 2Afinal, enum armazena constantes, e mesmo comparando valores semelhantes usando == , receberemos true , já que as referências serão sempre aos mesmos objetos. Bom, ao usar equals, também vamos trabalhar a funcionalidade corretamente, principalmente se você entrar no corpo do método equals para um enum , verá que na classe Enum a implementação do método é a seguinte: Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 3Ou seja, por dentro - a boa e velha comparação por referência! Para resumir: para enum , a comparação entre == e equals está correta.Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 4

74. O que o método ordinal() faz no Enum?

Ao chamar o método int ordinal() em um elemento enum , obteremos o número ordinal de zero deste valor na série geral de enumerações. Vamos usar este método em um elemento da enumeração anterior discutida - Role :
System.out.println(Role.DIRECTOR.ordinal());
Assim, o console exibirá:
2

75. É possível usar Enum com TreeSet ou TreeMap em Java?

O uso de tipos enum em TreeSet e TreeMap é aceitável. E podemos escrever:
TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
E o console exibirá:
DIRETOR PROFESSOR ESTUDANTE SECURITY_GUARD
Recebemos a saída não em ordem alfabética. A questão é que se usarmos elementos enum para valores TreeSet ou como chaves para TreeMap , os elementos serão classificados em sua ordem natural (a ordem em que são especificados no enum ). Compreender esses recursos nos ajuda a escrever um código melhor.Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 5

76. Como os métodos ordinal() e compareTo() estão relacionados no Enum?

Conforme afirmado anteriormente, ordinal() retorna o número ordinal de um valor em uma lista de enumeração geral. Além disso, na análise da questão anterior, você viu que os elementos das enumerações, uma vez que, por exemplo, em um TreeSet (conjunto ordenado) tomam a ordem em que são declarados em enum . E como sabemos, TreeSet e TreeMap classificam os elementos chamando seu método compareTo() da interface Comparable . A partir disso podemos assumir que a classe Enum implementa a interface Comparable , implementando-a no método compareTo() , dentro do qual ordinal() é usado para definir a ordem de classificação. Tendo entrado na classe Enum , vemos a confirmação disso: Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 6E o próprio corpo do método: O Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 7método ordinal() não é chamado aqui. Em vez disso, uma variável ordinal é usada - o número ordinal do elemento na enumeração. O método ordinal()Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 8 em si nada mais é do que um getter para a variável ordinal .

77. Escreva um exemplo EnumM

Nas questões discutidas acima, já dei exemplos de enums e não vejo sentido em duplicar o código (por exemplo, pergunta número 72 sobre o construtor em enum).

78. É possível usar Enum em um switch case?

É possível e necessário! Olhando para minha prática, observo que um dos lugares mais comuns para usar enum são construções lógicas como switch . Nesse caso, você pode fornecer todas as variações possíveis de case e depois escrever a lógica para todos os valores de enum - e usar o operador padrão pode nem ser necessário! Afinal, se você usar uma String ou um valor numérico, por exemplo, do tipo int , poderá receber um valor inesperado, o que por sua vez é impossível usando um enum . Qual seria a aparência de uma opção no exemplo discutido anteriormente:
public void doSomething(Role role) {
   switch (role) {
       case STUDENT:
           // некая логика для STUDENT
           break;
       case TEACHER:
           // некая логика для TEACHER
           break;
       case DIRECTOR:
           // некая логика для DIRECTOR
           break;
       case SECURITY_GUARD:
           // некая логика для SECURITY_GUARD
           break;
   }
}

79. Como obter todos os valores disponíveis em uma instância Enum?

Se você precisar obter todas as instâncias de uma enumeração, existe um métodovalues() que retorna um array de todos os valores disponíveis de um determinado enum em ordem natural (na ordem em que foram especificados no enum ). Exemplo:
Role[] roles = Role.values();
for (Role role : roles) {
   System.out.println(role);
}
O console exibirá a seguinte saída:
DIRETOR PROFESSOR ESTUDANTE SECURITY_GUARD

API de fluxo

80.O que é Stream em Java?

Java Stream é uma maneira relativamente nova de interagir com um fluxo de dados, que por sua vez permite processar grandes dados de maneira mais conveniente e compacta, bem como paralelizar o processamento de dados entre um certo número de threads, o que pode aumentar o desempenho no uso. funcionalidade. Este tema não pode ser abordado mais profundamente em poucas palavras, por isso deixarei aqui um link para um artigo que pode te ajudar a se aprofundar neste tema.Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 9

81. Quais são as principais propriedades das transações?

O tópico se chama Stream API, mas a dúvida é sobre a transação. Hmm... Primeiro, vamos descobrir o que é uma transação. Uma transação é um grupo de operações sequenciais de banco de dados que representa uma unidade lógica de trabalho com dados. Uma transação pode ser concluída de forma completa e bem-sucedida, mantendo a integridade dos dados e independentemente de outras transações executadas em paralelo, ou não pode ser concluída de forma alguma, caso em que não terá efeito. Portanto, as transações têm quatro propriedades principais, que são abreviadamente chamadas de ACID . Vejamos como significa cada letra desta abreviatura: A - Atomicidade - atomicidade - esta propriedade garante que nenhuma transação será registrada parcialmente no sistema. Todas as suas suboperações serão executadas ou nenhuma será executada ( tudo ou nada ). C – Consistência – consistência é uma propriedade que garante que cada transação bem-sucedida registre apenas resultados válidos. Ou seja, trata-se de uma garantia de que em caso de sucesso da transação, todas as regras e restrições que o sistema impõe a dados específicos serão cumpridas, caso contrário a transação não será concluída e os dados do sistema retornarão ao seu estado anterior. estado. I – Isolamento – isolamento é uma propriedade que diz que durante a execução de uma transação, as transações paralelas não devem afetar o seu resultado. Esta propriedade consome muitos recursos, por isso é normalmente implementada em parte permitindo certos níveis de isolamento que resolvem certos problemas de isolamento. Discutiremos isso com mais detalhes na próxima pergunta. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 8 - 10D - Durabilidade - esta propriedade garante que caso o usuário tenha recebido a confirmação do sistema de que a transação foi concluída, ele pode ter certeza de que as alterações que realizou não serão canceladas por alguma falha. Ou seja, você pode ter certeza de que algum tipo de falha no sistema operacional não afetará seus dados se você já tiver recebido a confirmação da conclusão bem-sucedida de sua transação.

82. Quais são os níveis de isolamento das transações?

Como eu disse anteriormente, fornecer isolamento ACID é um processo que consome muitos recursos. Portanto, esta propriedade é parcialmente satisfeita. Existem diferentes níveis de isolamento e quanto maior o nível, maior o impacto na produtividade. Antes de passar para os níveis de isolamento de transações, precisamos examinar os vários problemas de isolamento insuficiente de transações :
  • leitura fantasma - quando a mesma amostra (mesma consulta) é chamada repetidamente dentro de uma mesma transação, os dados recebidos diferem, o que ocorre devido a inserções de dados por outra transação;

  • leitura não repetitiva - quando a mesma amostra (a mesma consulta) é chamada repetidamente dentro de uma mesma transação, os dados recebidos diferem, o que ocorre devido a alterações (atualização) e exclusões de dados por outra transação;

  • leitura suja - o processo de leitura de dados adicionados ou alterados por uma transação que posteriormente não é confirmada (revertida), ou seja, lendo dados inválidos;

  • atualização perdida - quando transações diferentes alteram os mesmos dados ao mesmo tempo, todas as alterações, exceto a última, são perdidas (uma reminiscência do problema de “condição de corrida” em um ambiente multithread).

Os níveis de isolamento das transações são caracterizados pelos problemas de isolamento contra os quais eles protegem. Consideremos em forma de tabela os níveis de isolamento e de quais problemas eles protegem:
Nível de isolamento Leitura fantasma Leitura não repetitiva Leitura suja Atualização perdida
SERIALIZÁVEL + + + +
LEITURA REPETÍVEL - + + +
LEIA COMPROMETIDO - - + +
LEIA NÃO COMPROMETIDO - - - +
NENHUM - - - -
E não se esqueça do outro lado da moeda: quanto maior o nível de isolamento, mais tempo as transações levarão para serem processadas (se várias transações forem executadas em paralelo). Se você quiser se aprofundar neste tópico, aqui está um ótimo artigo para você começar.

83. Qual é a diferença entre Declaração e PreparedStatement?

E aqui a transição para os recursos da tecnologia JDBC não é muito tranquila . Então, primeiro, vamos descobrir o que realmente é Statement . Este é um objeto usado para gerar consultas SQL. JDBC usa três tipos - Statement , PreparedStatement e CallableStatement . Não veremos CallableStatement hoje: vamos falar sobre a diferença entre Statement e PreparedStatement .
  1. A instrução é usada para executar consultas SQL simples sem parâmetros de entrada inseridos dinamicamente. PrepareStatement é usado com a capacidade de inserir parâmetros de entrada dinamicamente.

  2. Para definir parâmetros em PreparedStatement, os parâmetros de entrada na solicitação são escritos como pontos de interrogação, para que um valor possa ser inserido usando vários setters, como setDouble() , setFloat() , setInt() , setTime() ... . Como resultado, você não inserirá o tipo errado de dados em sua consulta.

  3. PreparedStatement é “pré-compilado” e usa cache, portanto sua execução pode ser um pouco mais rápida do que consultar objetos Statement . Como resultado, as consultas SQL executadas com frequência são gravadas como objetos PreparedStatement para melhorar o desempenho .

  4. A instrução é vulnerável a injeções de SQL, enquanto PreparedStatement as impede. Leia mais sobre como eliminar injeções de SQL e outras práticas recomendadas em segurança Java neste artigo .

Se você está começando a estudar a tecnologia de conexão de uma aplicação Java a um Banco de Dados - JDBC, aconselho que comece por este artigo . Bem, neste ponto vamos parar hoje.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 11
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION