CodeGym /Blogue Java /Random-PT /Explorando perguntas e respostas de uma entrevista de emp...
John Squirrels
Nível 41
San Francisco

Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java. Parte 3

Publicado no grupo Random-PT
Oi! Assim como é impossível aprender a pilotar um avião sem treinamento especial, você não pode se tornar um desenvolvedor Java sem passar longas horas estudando os fundamentos teóricos necessários. E é exatamente nisso que trabalharemos hoje: continuaremos a explorar questões encontradas durante entrevistas de emprego para desenvolvedores Java e, é claro, veremos as respostas. Aqui estão a primeira e a segunda partes desta visão geral. Não há dúvida de que você pode se tornar um bom desenvolvedor Java sem todas essas questões. Dito isto, se você tiver um bom entendimento de todas as complexidades do Java, certamente terá uma vantagem e parecerá mais atraente aos olhos do seu futuro empregador. Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java.  Parte 3 - 1

20. Quais elementos da linguagem permitem o encapsulamento?

Lembremos que o encapsulamento consiste em ocultar os detalhes de implementação de uma classe. Em outras palavras, quando nossa classe é usada, suas entranhas e lógica interna não são óbvias para quem está de fora. E quais elementos da linguagem são responsáveis ​​por isso? Modificadores de acesso , é claro! Tudo o que precisamos esconder, marcamos com o modificador privado . Por exemplo, os campos privados de uma classe ou alguns métodos internos que ajudam a implementar alguma funcionalidade interna. E para qualquer coisa que queiramos fornecer acesso externo, adicionamos o modificador de acesso público . Por exemplo, um método que implementa alguma funcionalidade (que pode usar internamente muitos métodos privados) ou, claro, getters e setters para acessar os campos privados de uma classe. Ainda não mencionamos os modificadores padrão e protegidos , que podem ser usados ​​de forma mais flexível e personalizar especificamente o acesso a certas partes da classe.

21. Quais elementos da linguagem permitem a herança?

Herança é um mecanismo que permite criar classes baseadas em outra classe. Java tem a palavra-chave extends para isso. Por exemplo, suponha que temos uma classe Cat e queremos criar uma classe filha 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 as variáveis ​​estáticas. Outro elemento da linguagem responsável pela herança é o super . É uma referência semelhante a esta . A palavra-chave this refere-se ao objeto no qual é referenciada. A palavra-chave super refere-se ao pai do objeto atual. Normalmente super é usado:
  1. Para chamar o construtor de uma superclasse. Por exemplo, a classe Cat possui uma variável de nome interna que deve ser inicializada no construtor. No construtor da classe Lion , ficará assim:

    
    public Lion(final String name) {
       super(name);
    }

  2. Para se referir aos campos e métodos do pai. Por exemplo, na classe Cat , temos um campo de idade inicializado:

    
    public class Cat {
       int age = 10;

Mas temos o mesmo campo inicializado no Lion :

public class Lion extends Cat {
   int age = 15;
E se em um objeto Lion quisermos nos referir à variável age do objeto pai, então temos que 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 com uma assinatura assumir muitas formas (muitas implementações). Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java.  Parte 3 - 2Podemos afirmar com segurança que as palavras-chave implements e extends do Java são responsáveis ​​pelo polimorfismo. Quando temos uma interface, implements nos permite fornecer uma implementação possível, mas essa não precisa ser a única implementação, não é mesmo? Vamos revisitar como é usar implementos :

public class Cat implements Animal
Então, na classe Cat , temos que implementar todos os métodos abstratos na interface Animal . Herança também: na classe filha, podemos substituir a implementação existente de um método. Isso significa que com múltiplas classes filhas, podemos ter diversas substituições diferentes do mesmo método. Ou uma superclasse pode ser abstrata e ter um determinado método que deve ser implementado de maneira especial em cada uma de suas classes filhas. Em outras palavras, este método terá muitas implementações diferentes. A anotação @Override também pode nos ajudar nisso. É colocado acima dos métodos implementados e indica que queremos implementar ou substituir (se já existir uma implementação na superclasse) um método específico de uma superclasse ou interface. É opcional e ajuda a detectar erros com mais facilidade. Você usa esta anotação para informar ao compilador que deseja substituir/implementar o método de superclasse/interface. O compilador garantirá que você não cometa erros na assinatura do método.

23. O que é SÓLIDO? Forneça exemplos

SOLID é um acrônimo para os cinco princípios básicos de design OOP de Robert Martin. S (princípio da responsabilidade única) : afirma que uma classe deve ter apenas um propósito/responsabilidade. Em outras palavras, você não deve criar classes que façam tudo. Se fizer isso, você poderá reproduzir o antipadrão "Objeto de Deus". Se você tiver um objeto Cat , ele deverá ter métodos apenas para interagir com sua funcionalidade interna, mas não deverá conter nenhuma lógica de negócios não relacionada a essa instância. Por exemplo, algum mecanismo para armazenar objetos deste tipo. Esta funcionalidade (externa à entidade de um Cat ) deverá ser movida para outras classes ou serviços, cuja tarefa é fornecer a lógica de negócio para os objetos correspondentes. O (princípio aberto-fechado) : Este princípio é descrito da seguinte forma: entidades de software (classes, módulos, funções, etc.) devem ser abertas para extensão, mas fechadas para modificação. Por exemplo, suponha que precisamos de uma funcionalidade semelhante, mas ligeiramente diferente da funcionalidade de nossa classe Cat existente . Em vez de alterar a funcionalidade da classe Cat e, assim, quebrar o código em todos os lugares em que ela já é usada, podemos usar herança ou composição . Assim, atingimos nosso objetivo de modificar a funcionalidade da classe Cat , e fazemos isso sem alterar a classe em si e sem quebrar nada. L (Princípio de Substituição de Liskov) : este é o princípio de substituição de Barbara Liskov. O princípio diz que uma função que usa um tipo base deve ser capaz de usar subtipos desse tipo base sem saber o que está acontecendo. Por exemplo, nossa classe Cat deve ser substituída por qualquer um de seus descendentes, digamos, Lion , sem alterar fundamentalmente seu comportamento. A lógica geral (comportamento) permanece a mesma, mas os detalhes de implementação de funcionalidades específicas mudam. I (Princípio de segregação de interface) : este princípio afirma que é melhor ter muitas interfaces especializadas (com foco restrito) do que uma interface universal. Por exemplo, suponha que um desenvolvedor implemente alguma interface. Eles só precisam de um de seus métodos, mas a interface possui mais nove métodos que não se relacionam com a lógica do método requerido. Nesse caso, o desenvolvedor precisará implementar dez métodos de interface, nove dos quais são supérfluos para ele! Em vez disso, é melhor criar dez interfaces diferentes que você possa implementar conforme necessário. Bem, se não dez, então vários, cada um com métodos intimamente relacionados ao propósito único da interface. D (princípio de inversão de dependência): O princípio diz que os módulos de nível superior não devem depender de módulos de nível inferior. Este princípio também afirma: "A abstração não deve depender de detalhes. Os detalhes devem depender de abstrações." Devemos construir nossa lógica referindo-nos a interfaces e repassando objetos concretos de classes que implementam a interface necessária. Por exemplo, suponha que temos uma interface Cat e algumas implementações, digamos, Lion e HouseCat . Construímos nossa lógica especificamente para interagir com a interface Cat . Só então substituímos a interface por uma implementação específica ( Lion ou HouseCat ), mas não o contrário.

24. O que é classe, objeto e interface?

Lembraremos que Java é uma linguagem OOP. Ou seja, os programas Java são construídos com base nas interações entre objetos. Um programa é como um formigueiro, onde cada formiga é um objeto. Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java.  Parte 3 - 3Objetos são coleções de dados que incluem vários métodos (funções) para interagir com esses dados internos. As classes são instruções ou modelos para a criação de objetos. Isso significa que podemos ter muitos objetos construídos de acordo com as mesmas instruções, mas preenchidos com dados diferentes (ou iguais). Tomando um exemplo da vida real, podemos dizer que uma classe é a planta de um edifício, e um objeto é um edifício construído especificamente de acordo com a planta. As interfaces são semelhantes às classes, mas não podemos usá-las para criar objetos. Seu objetivo é adicionar abstração ao Java. Mais precisamente, acrescentam flexibilidade ao relacionamento entre classes e objetos. Por flexibilidade entendemos o polimorfismo e a abstração descritos anteriormente, que criam muitas oportunidades para a construção da arquitetura interna de uma aplicação.

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

Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java.  Parte 3 - 4Um POJO (Plain Old Java Object) é um objeto de classe simples que não herda 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, essas classes não herdam 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 usam anotações e não depende de bibliotecas de terceiros. Observemos que um POJO pode ter métodos contendo lógica de negócios e construtores de qualquer tipo. Se permitirmos anotações que não alterem a semântica da classe (ou seja, anotações cuja ausência não altere o propósito ou a lógica do objeto), então os POJO s também poderão incluir entidades JPA e objetos DTO desserializados de XML ou JSON , cujas regras são especificado em anotações. Outra coisa a ter em mente em relação às classes POJO é que é bom substituir seus métodos equals e hashCode porque isso pode ajudá-los a cumprir melhor sua função. Exemplo de uma 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?

Uma classe pode conter os seguintes elementos:
  • campos de instância;
  • campos estáticos;
  • um bloco de inicialização;
  • um bloco de inicialização estático;
  • construtores (um construtor vazio é sempre declarado por padrão);
  • métodos;
  • métodos estáticos;
  • diversas anotações (que podem ser aplicadas à própria classe ou às suas partes constituintes);
  • genéricos ;
  • herança de outras classes ( extends ) ou implementações de interfaces ( implements ).

27. Conte-nos sobre herança em Java. Quais são as especificidades da super palavra-chave?

Acima, falei anteriormente sobre herança e a palavra-chave super em Java. Mencionarei mais alguns pontos importantes:
  1. Podemos herdar apenas uma única classe: Java não tem herança múltipla em Java. 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. Eles simplesmente não podem ser acessados ​​​​a partir da classe filha (mas se, por exemplo, tivermos um campo privado e getters e setters públicos ou protegidos , podemos usá-los para acessar o campo).
  3. classes finais não podem ser herdadas.
  4. métodos finais não podem ser substituídos (mas podem ser herdados e sobrecarregados).
  5. métodos e variáveis ​​estáticos não são herdados (porque são anexados a classes, não a objetos).
  6. Ao herdar classes abstratas, seus métodos abstratos devem ser implementados ou a classe filha 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 está escrito acima deles).
  8. Você pode estender o modificador de acesso para métodos substituídos na classe filha: private -> default -> protected -> public .
  9. Os métodos substituídos na classe filha podem gerar exceções mais restritas, por exemplo: Exceção -> IOException -> FileNotFoundException.
Explorando perguntas e respostas de uma entrevista de emprego para um cargo de desenvolvedor Java.  Parte 3 - 5

28. O que são assinaturas de métodos? Forneça exemplos de assinaturas corretas e incorretas

Uma assinatura de método é o nome do método mais os tipos dos parâmetros de entrada (a ordem dos parâmetros é importante). A assinatura do método não inclui o valor de retorno ou as exceções que o método lança. Exemplo de assinatura correta:

doSomething(int, double, double)
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!
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION