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 4

Publicado no grupo Random-PT
Olá a todos, hoje continuo analisando mais de 250 perguntas de entrevistas para desenvolvedores Java. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 1Partes anteriores da análise: primeira , segunda , terceira . Então vamos continuar.

29. É possível usar return em um construtor?

Você pode, mas sem o valor de retorno à direita de return . Ou seja, você pode usar return; como construção auxiliar durante os cálculos no construtor para finalizar (interromper) com urgência a execução de mais códigos e completar a inicialização do objeto. Por exemplo, temos uma classe Cat , e se Cat for homeless - isHomeless = true , precisamos finalizar a inicialização e não preencher os demais campos (afinal, eles nos são desconhecidos, já que o gato é morador de rua):
public Cat(int age, String name, boolean isHomeless) {
   if (isHomeless){
       this.isHomeless = isHomeless;
       return;
   }
   this.isHomeless = isHomeless;
   this.age = age;
   this.name = name;
}
Mas quando se trata de valores específicos, um construtor não pode usar return para retornar um valor porque:
  • ao declarar um construtor você não terá nada parecido com um tipo de retorno;
  • Normalmente, o construtor é chamado implicitamente durante a instanciação;
  • Um construtor não é um método: é um mecanismo separado cujo único propósito é inicializar variáveis ​​de instância, e o operador new é responsável por criar um objeto .
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 2

30. É possível lançar uma exceção de um construtor?

Os construtores lidam com exceções exatamente da mesma maneira que os métodos. E se os métodos nos permitem lançar exceções escrevendo throws <ExceptionType> no cabeçalho do método , então o construtor nos permite fazer isso, e também ao herdar e definir um construtor herdeiro, podemos expandir o tipo de exceção. Por exemplo, IOException -> Exception (mas não vice-versa). Como exemplo de lançamento de uma exceção por um construtor, tomemos a classe Cat . Digamos que ao criá-lo queremos inserir o nome e a idade no console:
public Cat() throws IOException {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   this.name = reader.readLine();
   this.age = Integer.parseInt(reader.readLine());
}
Como reader.readLine() lança uma IOException, nós a especificamos no cabeçalho como uma possível exceção lançada.

31. Em que elementos consiste o cabeçalho da classe? Escreva um exemplo

Falando dos elementos que compõem o cabeçalho da classe, vejamos um pequeno diagrama:
  • os componentes obrigatórios estarão entre colchetes <>
  • opcional - em {}
{modificador de acesso de classe}{staticidade de classe}{finalidade de classe}{abstração de classe} <nome da classe>{herança da classe pai} {implementação de interfaces} Então, o que temos: {class access modifier} - apenas os modificadores public e o modificador de acesso faltante, ou seja, default , estão disponíveis para a classe . {class static} - static é um modificador que indica que esta classe é estática, aplicável apenas a classes internas (classes dentro de outras classes). {finalidade da classe} - como lembramos, este é o modificador final , na presença do qual a classe se torna não herdável (exemplo da caixa - String ). {class abstraction} - modificador - abstract , que indica que esta classe pode ter métodos não implementados. Este modificador entra em conflito com o modificador final , ou seja, apenas um deles pode estar no cabeçalho da classe, pois o modificador abstrato implica que a classe dada será herdada e suas partes abstratas serão implementadas. E final indica que esta é a versão final (final) da classe e não pode ser herdada. Na verdade, usar os dois modificadores ao mesmo tempo seria um absurdo, e o compilador não nos permitirá fazer isso. <class> é uma palavra-chave obrigatória que indica uma declaração de classe. <nome da classe> é um nome de classe simples, que é o identificador de uma classe Java específica. O nome completo da classe consiste no nome completo do pacote + . + nome de classe simples. {herança da classe pai} - especificando a classe pai (se houver) usando a palavra-chave extends . Por exemplo, .. estende ParentClass . {implementação de interface} - especificando as interfaces que esta classe implementa (se houver) usando a palavra-chave implements . Por exemplo: ... implementa FirstInterface, SecondInterface ... Bem, como exemplo de cabeçalho de classe, considere o cabeçalho da classe Lion , que herda de Cat e implementa a interface WildAnimal :
public final class Lion extends Cat implements WildAnimal
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 3

32. Em quais elementos consiste o cabeçalho do método? Escreva um exemplo

Novamente, ao observar os elementos que compõem um cabeçalho de método, considere um pequeno diagrama onde:
  • componentes obrigatórios estão entre colchetes <>
  • opcional - em {}
{modificador de acesso}{método estático}{abstração do método}{finalidade do método}{modificador de sincronização} {modificador nativo}<valor de retorno><nome do método> <(> {argumentos do método} <)>{exceções lançadas} {modificador de acesso } — todos os modificadores de acesso estão disponíveis para o método: public , protected , default , private . {método estático} - estático é um modificador que indica que este método é estático, ou seja, não está vinculado a um objeto, mas a uma classe. {abstração do método} é o modificador abstrato , que indica que não há implementação (corpo) do método. Para uma operação correta, você também precisa de um modificador abstrato para a classe na qual o método é fornecido. Assim como no cabeçalho da classe, esse modificador entra em conflito com o modificador final , mas além dele, também entra em conflito com o modificador estático , pois um método abstrato implica substituir o método no descendente e os métodos estáticos não são substituídos. {finalidade do método} - final - um modificador que indica que este método não pode ser substituído. {modificador de sincronização} - sincronizado - um modificador que significa que este método está protegido contra acesso simultâneo de diferentes threads. Se o método não for estático, ele fecha no this mutex do objeto. Se o método for estático, ele fecha no mutex da classe atual. {modificador nativo} - nativo - este modificador indica que o método está escrito em uma linguagem de programação diferente. <valor de retorno> é o tipo de valor que o método deve retornar. Se não retornar nada, void . <nome do método> é o nome do método, seu identificador no sistema. {argumentos do método} são os argumentos (parâmetros) que o método utiliza: eles são necessários para implementar sua funcionalidade. {exceções lançáveis} - throwsExceptionType - uma lista de exceções verificadas que este método pode lançar. E como exemplo de cabeçalho de método, darei isto:
public static void main(String[] args) throws IOException

33. Crie um construtor padrão no objeto descendente se ele não estiver definido no objeto base (mas outro construtor estiver definido)

Não entendo completamente a pergunta em si, mas talvez isso signifique que, por exemplo, no pai temos algum construtor personalizado:
public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Portanto, na classe ancestral, definitivamente precisamos definir um construtor que irá preencher (chamar) o construtor pai:
public  class Lion extends Cat {

   public Lion(int age, String name) {
       super(age, name);
   }
}
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 4

34. Quando a palavra-chave this é usada?

Em Java, isso tem dois significados diferentes. 1. Como referência ao objeto atual, como this.age = 9 . Ou seja, this refere-se ao objeto no qual foi chamado e ao qual se refere o código que utiliza this . A principal função é aumentar a legibilidade do código e evitar ambiguidades. Por exemplo, se o nome do campo da classe interna e o argumento do método forem iguais:
public void setName(String name) {
   this.name = name;
}
Ou seja, this.name é um campo do nome do objeto que é um argumento de método. A referência this não pode ser usada em métodos estáticos. 2. this pode ser usado em um construtor na forma de uma chamada de método, como this(value) . Neste caso, será uma chamada para outro construtor da mesma classe. Resumindo, você pode chamar dois construtores ao mesmo tempo ao criar um objeto:
public Cat(int age, String name) {
   this(name);
   this.age = age;
}

public Cat(String name) {
   this.name = name;
}
Quando um objeto Cat é criado e o primeiro construtor é chamado, ambos os campos do objeto serão chamados e inicializados com sucesso. Existem algumas nuances:
  1. this() só funciona no construtor.
  2. Uma referência a outro construtor deve estar na primeira linha do bloco construtor (corpo). Portanto, mais de um (outro) construtor de uma determinada classe não pode ser chamado em um construtor.
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 5Mais exemplos estão neste artigo .

35. O que é um inicializador?

Pelo que entendi, nesta questão estamos falando de blocos de inicialização comuns e estatísticos. Primeiro, vamos lembrar o que é inicialização. A inicialização é criação, ativação, preparação para o trabalho, determinação de parâmetros. Colocar um programa ou componente em estado de prontidão para uso. Como você lembra, durante a criação do objeto, uma variável de classe pode ser inicializada diretamente na declaração:
class Cat {
   private int age = 9;
   private  String name = "Tom";
Ou configure-o externamente através de um construtor:
class Cat {
   private int age;
   private  String name;

   public Cat(int age, String name) {
       this.age = age;
       this.name = name;
   }
Mas há outra maneira: definir uma variável de objeto interna por meio de um bloco de inicialização, que se parece com chaves { } dentro da classe, sem nome (como um método ou construtor):
class Cat {
   private int age;
   private  String name;

   {
       age = 10;
       name = "Tom";
   }
Ou seja, um bloco de inicialização é um trecho de código carregado quando um objeto é criado. Normalmente, esses blocos são usados ​​para realizar alguns cálculos complexos necessários ao carregar uma classe. Os resultados desses cálculos podem ser especificados como valores de variáveis. Além disso, além dos blocos de inicialização regulares, existem os estáticos, que têm a mesma aparência, mas possuem a palavra-chave static antes das chaves :
class Cat {
   private static int age;
   private static String name;

   static{
       age = 10;
       name = "Tom";
   }
Este bloco é exatamente igual ao anterior. Mas se o normal for acionado quando cada objeto for inicializado, o estático será acionado apenas uma vez, quando a classe for carregada. Nesse bloco, via de regra, também são realizados alguns cálculos complexos para a posterior inicialização de variáveis ​​​​de classe estática. As mesmas restrições se aplicam a um bloco estático e a métodos estáticos: ele não pode usar dados não estáticos, bem como uma referência ao objeto atual - this . Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 6A seguir podemos ver a ordem de inicialização da classe (juntamente com seu ancestral) para uma melhor compreensão do momento em que os blocos de inicialização são acionados.

36. Para herdar uma classe public class Child estende Parent, escreva a ordem de inicialização do objeto

Quando a classe Child for carregada, a ordem de inicialização será a seguinte:
  1. Campos estáticos da classe Parent .
  2. Bloco de inicialização estática para a classe Parent .
  3. Campos estáticos da classe Сhild .
  4. Bloco de inicialização estática para a classe Child .
  5. Campos não estáticos da classe Parent .
  6. Não é um bloco de inicialização estático para a classe Parent .
  7. Construtor da classe Parent .
  8. Campos não estáticos da classe Child .
  9. Não é um bloco de inicialização estático para a classe Child .
  10. Construtor da classe Child .
Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 7Aqui está um pequeno artigo que explica a ordem de inicialização na prática.

37. Que relações você conhece entre classes (objetos)?

Existem dois tipos de relacionamentos entre classes em Java:
  • Relacionamento É-A
O princípio IS-A em OOP é baseado na herança de classe ou implementação de interface. Por exemplo, se a classe Lion herda de Cat , dizemos que Lion é Cat :
Lion IS-A Cat
(mas nem todo gato é um leão ) A situação é exatamente a mesma com as interfaces. Se a classe Lion implementa a interface WildAnimal , então eles também estão em uma relação:
Lion IS-A WildAnimal
  • Relacionamentos TEM-A
Este tipo de relacionamento é baseado na utilização de classes por outras classes, também chamada de “associação”. Uma associação é uma classe que faz referência a outra classe (ou até mesmo uma à outra). Por exemplo, a classe Carro poderia referir-se à classe Passageiro , e este seria o relacionamento:
Car HAS-A Passenger
E vice-versa: se Passenger tiver referência para Car , então esta será a relação:
Passenger HAS-A Car

38. Que conexões associativas entre objetos você conhece?

Agregação e composição nada mais são do que casos especiais de associação. Agregação é um relacionamento em que um objeto faz parte de outro. Por exemplo, um passageiro pode estar num carro. Além disso, pode haver vários passageiros ou nenhum (se estamos falando de um Tesla, então o motorista não é necessário). Por exemplo:
public class Car {
   private List passengers = new ArrayList<>();

 void setPassenger(Passenger passenger) {
     passengers.add(passenger);
 }

   void move() {
       for (Passenger passenger : passengers) {
           System.out.println("Перевозка пассажира - " + passenger.toString());
       }
       passengers.clear();
   }
}
Ou seja, não nos importamos com o número de passageiros (ou se há algum): a funcionalidade da classe Carro não depende disso. A agregação também implica que quando um objeto é usado por outro objeto, o primeiro pode ser usado em outros objetos. Por exemplo, o mesmo aluno pode ser membro de um clube de tricô e de um grupo musical de roqueiros e, ao mesmo tempo, frequentar um grupo de alunos de inglês. Como você entende, agregação é um relacionamento associativo mais flexível entre classes. Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 8A composição é uma relação ainda mais rígida quando um objeto não é apenas parte de outro objeto, mas o trabalho do outro objeto é muito dependente do primeiro. Por exemplo, um motor de carro. Embora o motor possa existir sem o carro, é inútil fora dele. Bem, um carro não pode funcionar sem motor:
public class Car {
   private Engine engine;

   public Car(Engine engine) {
       this.engine = engine;
   }

   void startMoving() {
       engine.start();
           ...
   }
A composição também implica que quando um objeto é usado por outro objeto, o primeiro não pode pertencer a mais ninguém. Se voltarmos ao nosso exemplo, um motor só pode pertencer a um carro, mas não a dois ou mais ao mesmo tempo. Provavelmente pararemos aqui hoje.Análise de perguntas e respostas de entrevistas para desenvolvedor Java.  Parte 4 - 9
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION