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 3

Publicado no grupo Random-PT
Olá! Assim como é impossível aprender a pilotar um avião sem treinamento especial, também é impossível se tornar um desenvolvedor Java sem passar longas horas estudando a base teórica necessária. Hoje trabalharemos exatamente nisso: continuaremos analisando mais de 250 perguntas de entrevistas para desenvolvedores Java e, consequentemente, as respostas a elas. Aqui estão a primeira e a segunda partes da análise. Sim, claro, você pode se tornar um bom desenvolvedor Java sem todas essas questões. No entanto, se você tiver um bom conhecimento dos meandros da linguagem Java, isso lhe dará uma vantagem, tornando-o um candidato mais desejável aos olhos de seu futuro empregador.Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 1

20. Quais elementos da linguagem são responsáveis ​​pelo encapsulamento?

Como lembramos, o encapsulamento oculta os detalhes de implementação de uma classe. Ou seja, quando nossa classe é usada externamente, o conteúdo interno e a lógica não são óbvios. E quais elementos da linguagem são responsáveis ​​por isso? Naturalmente, modificadores de acesso ! Marcamos o que precisamos esconder com o modificador privado . Por exemplo, campos privados de uma classe ou alguns métodos internos que ajudam a implementar determinadas funcionalidades internas. E ao que queremos fornecer acesso externo, adicionamos o modificador de acesso público . Por exemplo, um método responsável por fornecer alguma funcionalidade (dentro da qual muitos métodos privados podem ser usados) ou os mesmos getters e setters para acessar campos privados de uma classe. Ah, e também temos os modificadores padrão e protegidos , que podem ser usados ​​para configuração mais flexível e específica de acesso a partes selecionadas da classe.

21. Quais elementos da linguagem são responsáveis ​​pela herança?

Herança é um mecanismo que permite criar classes baseadas em outra classe. Em Java, a palavra-chave extends é usada para esse propósito . Por exemplo, temos uma determinada classe Cat e queremos criar seu sucessor - Lion . No código será algo assim:
public class Lion extends Cat
E isso significa que a classe Lion herda todos os métodos e variáveis ​​da classe Cat , exceto os estáticos. Além disso, os elementos de linguagem responsáveis ​​pela herança incluem super . Esta é uma referência semelhante a this , mas enquanto this se refere ao objeto no qual foi chamada, super refere-se ao objeto pai atual. Normalmente super é usado:
  1. Para chamar um construtor de superclasse: por exemplo, a classe Cat possui um nome de variável interna que precisa ser inicializado no construtor. No construtor da classe Lion ficaria assim:

    public Lion(final String name) {
       super(name);
    }
  2. Para acessar campos e métodos pai: por exemplo, na classe Cat temos um campo idade inicializado :

    public class Cat {
       int age = 10;
Ao mesmo tempo, temos o mesmo campo inicializado no Lion :
public class Lion extends Cat {
   int age = 15;
E se quisermos acessar a variável age do objeto pai do objeto Lion , precisamos fazer isso através de super :
super.name

22. Quais elementos da linguagem são responsáveis ​​pelo polimorfismo?

Polimorfismo é a capacidade de um objeto de uma assinatura assumir muitas formas (múltiplas implementações). Podemos dizer com segurança que em Java as palavras-chave implements e extendsAnálise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 2 são responsáveis ​​pelo polimorfismo . implements - quando criamos nossa interface, implementamos uma de suas possíveis formas em alguma classe, mas não é a única forma, não é mesmo? Vamos lembrar como são os implementos de implementação :
public class Cat implements Animal
E na classe Cat devemos implementar todos os métodos abstratos apresentados na interface Animal . O mesmo vale para herança: em uma classe descendente podemos sobrescrever uma implementação já existente de um método. Por exemplo: vários descendentes -> várias substituições diferentes do mesmo método. Bom, ou a superclasse era abstrata e possui um determinado método que precisa ser implementado de forma especial para cada um de seus descendentes. Ou seja, podemos dizer que o método assumirá diversas formas. Além disso, a anotação @Override pode nos ajudar com isso , que é colocada acima dos métodos implementados e indica que queremos implementar ou substituir (se a implementação já existir na superclasse) um ou outro método da superclasse ou interface. É opcional e serve para facilitar a detecção de erros. Com esta anotação, você indica ao compilador que deseja substituir/implementar um método de superclasse/interface, e isso garantirá que você não cometa erros na assinatura do método.

23. O que é SÓLIDO? Dar exemplos

SOLID é um acrônimo para Five Basic Design Principles for OOP, cunhado por Robert Martin. S - Princípio da responsabilidade única - o princípio da responsabilidade única, que afirma que uma aula deve ter apenas um objetivo e um único propósito. Ou seja, você não deve criar classes que façam tudo. Neste caso, você pode reproduzir o antipadrão “Objeto Divino”. Se você tiver um objeto Cat , ele deverá conter métodos que interajam apenas com sua funcionalidade interna, e não com lógica de negócios que não seja relevante para esta instância. Por exemplo, algum tipo de salvamento de objetos desse tipo em algum lugar. Esta funcionalidade externa (em relação ao Cat ) precisa ser transferida para outras classes, alguns serviços cuja tarefa é fornecer lógica de negócio para objetos deste tipo. O - Princípio aberto-fechado - princípio da abertura/fechamento. Isso significa que as entidades de software (classes, interfaces) devem estar abertas para extensão, mas fechadas para modificação. Por exemplo, precisávamos de funcionalidade semelhante à funcionalidade da classe Cat já existente , mas um pouco diferente. Em vez de alterar a funcionalidade da classe Cat , quebrando os locais onde ela já é utilizada, utilizamos herança ou composição . Como resultado, atingimos nosso objetivo com a funcionalidade modificada da classe Cat , mas ao mesmo tempo não a alteramos nem quebramos nada. L - Princípio da substituição de Liskov - Princípio da substituição de Barbara Liskov. O princípio afirma que uma função que usa um tipo base deve ser capaz de usar subtipos do tipo base sem saber disso. Por exemplo, nossa classe Cat deve ser intercambiável com qualquer um de seus descendentes, digamos Lion , sem alterar fundamentalmente o comportamento. A lógica geral (comportamento) permanece a mesma, mas os detalhes da implementação desta ou daquela funcionalidade mudam. I - Princípio da segregação de interfaces - princípio da separação de interfaces. Este princípio afirma que é melhor ter muitas interfaces especializadas (com foco restrito) do que uma interface universal. Por exemplo, um usuário implementa alguma interface, da qual ele só precisa deste método, mas esta interface possui mais nove métodos que nada têm a ver com a lógica do método desejado. Neste caso, o usuário precisará implementar dez métodos de interface, nove dos quais são desnecessários para ele! Em vez disso, é melhor criar dez interfaces diferentes que possam ser implementadas se necessário. Bem, ou não dez, mas vários, que terão métodos intimamente relacionados ao propósito comum da interface. D - Princípio de Inversão de Dependência— o princípio da inversão de dependência. O princípio afirma que os módulos de níveis superiores não devem depender de módulos de níveis inferiores. Este princípio também é descrito como “a abstração não deve depender de detalhes, os detalhes devem depender da abstração”. Ou seja, devemos construir nossa lógica referindo-nos às interfaces, e só então passar objetos específicos para essa funcionalidade, cujas classes implementam a interface necessária. Por exemplo, se tivermos uma interface Cat e algumas de suas implementações, digamos, Lion e HomeCat , construímos nossa lógica de interação especificamente com o tipo de interface Cat e só então substituímos por uma implementação específica de Lion ou HomeCat , mas não vice-versa.

24. O que é classe, objeto, interface?

Como lembramos, Java é uma linguagem OOP. Ou seja, os programas Java são construídos na interação entre objetos. Acontece que o programa é como um formigueiro, onde cada formiga é um objeto. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 3Objetos são alguns dados agrupados que contêm vários métodos (funções) para interagir com esses dados internos. E as classes são instruções, modelos para criação de objetos. Ou seja, pode haver muitos objetos construídos de acordo com a mesma instrução, preenchidos com valores de dados diferentes ou idênticos. Para dar um exemplo da vida, podemos dizer que uma aula é o desenho de um edifício, e um objeto é um edifício criado especificamente com base nesse desenho. As interfaces são análogas às classes, com a diferença de que objetos não podem ser criados usando-as. Seu objetivo é adicionar um elemento de abstração ao Java. Mais precisamente, para adicionar flexibilidade nas relações entre classes e objetos. Por flexibilidade entendemos o polimorfismo e a abstração descritos anteriormente, que por sua vez abrem muitas oportunidades para a construção da arquitetura interna da aplicação.

25. O que é uma aula POJO? Dê um exemplo de tal classe

Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 4POJO - Plain Old Java Object - um bom e velho objeto Java: um objeto simples de uma classe que não é herdado de nenhuma classe específica e não implementa nenhuma interface de serviço além daquelas necessárias para o modelo de negócios. Em outras palavras , uma classe POJO é apenas uma classe sem requisitos especiais. O único requisito é a ausência de vários sinos e assobios vinculados a uma estrutura específica. Via de regra, tais classes não herdam de outras classes (exceto classes POJO do mesmo pacote), não implementam interfaces - às vezes é feita uma exceção para interfaces de marcadores da biblioteca padrão, como Serializable ou Cloneable - não use anotações e não depende de bibliotecas de terceiros. Mas observo que os POJOs podem ter métodos com lógica de negócios e construtores de qualquer tipo. Se você permitir anotações que não façam alterações na semântica da classe (sem as quais a finalidade do objeto e a lógica de seu funcionamento não serão alteradas), os POJOs também poderão incluir entidades JPA Entity e objetos DTO desserializados de XML ou JSON , cujas regras são especificadas nas anotações. Também é aconselhável substituir equals e hashCode para classes POJO , pois isso pode ajudá-los a desempenhar melhor sua função. Exemplo de classe POJO :
public class User {
   private Long id;
   private String firstName;
   private String lastName;
   private Long age;

   public User(final Long id, final String firstName, final String lastName, final long age) {
       this.id = id;
       this.firstName = firstName;
       this.lastName = lastName;
       this.age = age;
   }

   public Long getId() {
       return this.id;
   }

   public String getFirstName() {
       return this.firstName;
   }

   public String getLastName() {
       return this.lastName;
   }

   public Long getAge() {
       return this.age;
   }

   @Override
   public boolean equals(final Object o) {
       if (this == o) return true;
       if (o == null || this.getClass() != o.getClass()) return false;
       final User user = (User) o;
       return Objects.equals(this.id, user.id) &&
               Objects.equals(this.firstName, user.firstName) &&
               Objects.equals(this.lastName, user.lastName) &&
               Objects.equals(this.age, user.age);
   }

   @Override
   public int hashCode() {
       return Objects.hash(this.id, this.firstName, this.lastName, this.age);
   }
}

26. Que elementos uma classe pode conter?

A classe pode conter os seguintes elementos:
  • campos de classe;
  • campos de classe estática;
  • bloco de inicialização;
  • bloco de inicialização estática;
  • construtores (vazio é sempre definido por padrão);
  • métodos;
  • métodos estáticos;
  • várias anotações (que podem ficar acima da própria classe ou de seus componentes);
  • genéricos ;
  • herança de outras classes ( extends ) ou implementação de interfaces ( implements ).

27. Explique herança em Java. Quais são os benefícios de usar a super palavra-chave?

Acima já falei sobre herança e a palavra-chave super em Java. Deixe-me mencionar mais alguns pontos importantes:
  1. É possível herdar apenas uma classe: não há herança múltipla em Java (mas com o advento dos métodos padrão no Java 8, esta afirmação se tornará muito controversa).
  2. Métodos e campos privados também são herdados, apenas não terão acesso a eles do herdeiro (mas se tivermos, por exemplo, um campo privado e houver getters e setters públicos ou protegidos para ele, o campo poderá ser trabalhado com por eles).
  3. classes finais não são herdadas.
  4. métodos finais não são substituídos (mas podem ser herdados e sobrecarregados).
  5. métodos e variáveis ​​estáticos não são herdados (já que não estão vinculados a objetos, mas a classes).
  6. Ao herdar de classes abstratas, é necessária a implementação de seus métodos abstratos, ou a classe atual também deve ser declarada abstrata.
  7. Se houver construtores não padrão no pai, eles deverão ser substituídos na classe filha (mas @Override não será escrito sobre eles).
  8. Os métodos substituídos no descendente podem ser estendidos com um modificador de acesso: private -> default -> protected -> public .
  9. Os métodos substituídos no descendente podem restringir as exceções escritas, por exemplo: Exceção -> IOException -> FileNotFoundException.
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 5

28. O que é uma assinatura de método? Dê exemplos de assinaturas corretas e incorretas

A assinatura de um método é o nome do método mais os tipos dos parâmetros recebidos (e a ordem dos parâmetros é importante). A assinatura do método não inclui o valor de retorno ou as exceções que ele lança. Exemplo de assinatura correta:
doSomething(int, double, double)
Um exemplo de assinatura incorreta:
void doSomething(int firstArg, int secondArg) throws Exception
A assinatura do método, combinada com o tipo de retorno e a lista de exceções lançadas, é chamada de método contract . Isso é tudo por hoje. Até mais!Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 3 - 6
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION