JavaRush /Blog Java /Random-ES /Análisis de preguntas y respuestas de entrevistas para de...

Análisis de preguntas y respuestas de entrevistas para desarrollador Java. parte 4

Publicado en el grupo Random-ES
Hola a todos, hoy continúo analizando más de 250 preguntas de entrevistas para desarrolladores de Java. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 1Partes anteriores del análisis: primera , segunda , tercera . Así que continuemos.

29. ¿Es posible utilizar return en un constructor?

Puedes, pero sin el valor de retorno a la derecha de devolución . Es decir, puedes usar return; como construcción auxiliar durante los cálculos en el constructor para finalizar (interrumpir) urgentemente la ejecución de código adicional y completar la inicialización del objeto. Por ejemplo, tenemos una clase Cat , y si Cat no tiene hogar - isHomeless = true , debemos finalizar la inicialización y no completar otros campos (después de todo, los desconocemos, ya que el gato no tiene hogar):
public Cat(int age, String name, boolean isHomeless) {
   if (isHomeless){
       this.isHomeless = isHomeless;
       return;
   }
   this.isHomeless = isHomeless;
   this.age = age;
   this.name = name;
}
Pero cuando se trata de valores específicos, un constructor no puede usar return para devolver un valor porque:
  • al declarar un constructor no tendrás nada parecido a un tipo de retorno;
  • Normalmente, el constructor se llama implícitamente durante la creación de instancias;
  • Un constructor no es un método: es un mecanismo separado cuyo único propósito es inicializar variables de instancia, y el nuevo operador es responsable de crear un objeto .
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 2

30. ¿Es posible lanzar una excepción desde un constructor?

Los constructores tratan las excepciones exactamente de la misma manera que los métodos. Y si los métodos nos permiten lanzar excepciones escribiendo throws <ExceptionType> en el encabezado del método , entonces el constructor nos permite hacer esto, y también al heredar y definir un constructor heredero, podemos expandir el tipo de excepción. Por ejemplo, IOException -> Excepción (pero no al revés). Como ejemplo de cómo generar una excepción por parte de un constructor, tomemos la clase Cat . Digamos que al crearlo queremos introducir el nombre y la edad desde la consola:
public Cat() throws IOException {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   this.name = reader.readLine();
   this.age = Integer.parseInt(reader.readLine());
}
Dado que lector.readLine() lanza una IOException, la especificamos en el encabezado como una posible excepción lanzada.

31. ¿De qué elementos consta el encabezado de clase? Escribe un ejemplo

Hablando de los elementos que componen el encabezado de la clase, veamos un pequeño diagrama:
  • Los componentes obligatorios estarán entre paréntesis <>
  • opcional - en {}
{modificador de acceso de clase}{estática de clase}{finalidad de clase}{abstracción de clase} <nombre de clase>{herencia de la clase principal} {implementación de interfaz} Entonces, lo que tenemos: {modificador de acceso de clase} : solo los modificadores públicos y el modificador de acceso que falta, es decir, predeterminado, están disponibles para la clase . {class static} - static es un modificador que indica que esta clase es estática, aplicable solo a clases internas (clases dentro de otras clases). {finalidad de clase} : como recordamos, este es el modificador final , en presencia del cual la clase se vuelve no heredable (ejemplo del cuadro - String ). {abstracción de clase} - modificador - abstracto , que indica que esta clase puede tener métodos no implementados. Este modificador entra en conflicto con el modificador final , es decir, solo uno de ellos puede estar en el encabezado de la clase, ya que el modificador abstracto implica que la clase dada será heredada y sus partes abstractas serán implementadas. Y final indica que esta es la versión final (final) de la clase y no se puede heredar. En realidad, usar ambos modificadores al mismo tiempo sería absurdo y el compilador no nos permitirá hacerlo. <clase> es una palabra clave requerida que indica una declaración de clase. <nombre de clase> es un nombre de clase simple, que es el identificador de una clase Java específica. El nombre de clase completo consta del nombre del paquete completo + . + nombre de clase simple. {herencia de la clase principal} : especifica la clase principal (si la hay) utilizando la palabra clave extends . Por ejemplo,... extiende ParentClass . {implementación de interfaz} : especifica las interfaces que implementa esta clase (si las hay) usando la palabra clave implements . Por ejemplo: ... implementa FirstInterface, SecondInterface ... Bueno, como ejemplo de un encabezado de clase, considere el encabezado de la clase Lion , que hereda de Cat e implementa la interfaz WildAnimal :
public final class Lion extends Cat implements WildAnimal
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 3

32. ¿De qué elementos consta el encabezado del método? Escribe un ejemplo

Nuevamente, cuando observe los elementos que componen el encabezado de un método, considere un pequeño diagrama donde:
  • Los componentes obligatorios están entre paréntesis <>
  • opcional - en {}
{modificador de acceso}{método estático}{abstracción del método}{finalidad del método}{modificador de sincronización} {modificador nativo}<valor de retorno><nombre del método> <(> {argumentos del método} <)>{excepciones lanzadas} {modificador de acceso } — todos los modificadores de acceso están disponibles para el método: público , protegido , predeterminado , privado . {método estático} : estático es un modificador que indica que este método es estático, es decir, no está vinculado a un objeto, sino a una clase. {method abstraction} es el modificador abstracto , que indica que no hay implementación (cuerpo) del método. Para un funcionamiento correcto, también necesita un modificador abstracto para la clase en la que se proporciona el método. Como en el encabezado de clase, este modificador entra en conflicto con el modificador final , pero además de él, también entra en conflicto con el modificador estático , porque un método abstracto implica anular el método en el descendiente y los métodos estáticos no se anulan. {finalidad del método} - final : un modificador que indica que este método no se puede anular. {modificador de sincronización} - sincronizado - un modificador que significa que este método está protegido del acceso simultáneo desde diferentes subprocesos. Si el método no es estático, se cierra en este mutex del objeto. Si el método es estático, se cierra en el mutex de la clase actual. {modificador nativo} - nativo : este modificador indica que el método está escrito en un lenguaje de programación diferente. <valor de retorno> es el tipo de valor que el método debe devolver. Si no devuelve nada, nulo . <nombre del método> es el nombre del método, su identificador en el sistema. {argumentos del método} son los argumentos (parámetros) que toma el método: son necesarios para implementar su funcionalidad. {excepciones arrojables} - throwsExceptionType : una lista de excepciones marcadas que este método puede generar. Y como ejemplo de encabezado de método, daré esto:
public static void main(String[] args) throws IOException

33. Cree un constructor predeterminado en el objeto descendiente si no está definido en el objeto base (pero sí se define otro constructor)

No entiendo completamente la pregunta en sí, pero tal vez signifique que, por ejemplo, en el padre tenemos algún constructor personalizado:
public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Por lo tanto, en la clase ancestral, definitivamente necesitamos definir un constructor que completará (llamará) al constructor principal:
public  class Lion extends Cat {

   public Lion(int age, String name) {
       super(age, name);
   }
}
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 4

34. ¿Cuándo se utiliza esta palabra clave?

En Java, esto tiene dos significados diferentes. 1. Como referencia al objeto actual, como this.age = 9 . Es decir, this se refiere al objeto sobre el que se llamó y al que se refiere el código que lo utiliza . La función principal es aumentar la legibilidad del código y evitar la ambigüedad. Por ejemplo, si el nombre del campo de clase interno y el argumento del método son iguales:
public void setName(String name) {
   this.name = name;
}
Es decir, this.name es un campo del nombre del objeto y es un argumento del método. La referencia a esta no se puede utilizar en métodos estáticos. 2. esto se puede usar en un constructor en forma de llamada a un método, como this(value) . En este caso será una llamada a otro constructor de la misma clase. En resumen, puedes llamar a dos constructores a la vez al crear un objeto:
public Cat(int age, String name) {
   this(name);
   this.age = age;
}

public Cat(String name) {
   this.name = name;
}
Cuando se crea un objeto Cat y se llama al primer constructor, se llamarán e inicializarán con éxito ambos campos del objeto. Hay un par de matices:
  1. this() sólo funciona en el constructor.
  2. Una referencia a otro constructor debe estar en la primera línea del bloque constructor (cuerpo). Por lo tanto, no se puede llamar a más de un (otro) constructor de una clase determinada en un constructor.
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 5Más ejemplos están en este artículo .

35. ¿Qué es un inicializador?

Según tengo entendido, en esta pregunta estamos hablando de bloques de inicialización ordinarios y estadísticos. Primero, recordemos qué es la inicialización. La inicialización es creación, activación, preparación para el trabajo, determinación de parámetros. Poner un programa o componente en un estado de preparación para su uso. Como recordará, durante la creación de un objeto, una variable de clase se puede inicializar directamente tras la declaración:
class Cat {
   private int age = 9;
   private  String name = "Tom";
O configúrelo externamente a través de un constructor:
class Cat {
   private int age;
   private  String name;

   public Cat(int age, String name) {
       this.age = age;
       this.name = name;
   }
Pero hay otra manera: establecer una variable de objeto interna a través de un bloque de inicialización, que parece llaves { } dentro de la clase, sin un nombre (como un método o constructor):
class Cat {
   private int age;
   private  String name;

   {
       age = 10;
       name = "Tom";
   }
Es decir, un bloque de inicialización es un fragmento de código que se carga cuando se crea un objeto. Normalmente, estos bloques se utilizan para realizar algunos cálculos complejos que son necesarios al cargar una clase. Los resultados de estos cálculos se pueden especificar como valores para variables. Además, además de los bloques de inicialización habituales, hay bloques estáticos, que tienen el mismo aspecto, pero tienen la palabra clave static antes de la llave :
class Cat {
   private static int age;
   private static String name;

   static{
       age = 10;
       name = "Tom";
   }
Este bloque es exactamente igual que el anterior. Pero si el normal se activa cuando se inicializa cada objeto, entonces el estático se activará solo una vez, cuando se cargue la clase. En dicho bloque, por regla general, también se realizan algunos cálculos complejos para la posterior inicialización de variables de clase estáticas. Se aplican las mismas restricciones a un bloque estático que a los métodos estáticos: no puede utilizar datos no estáticos, así como una referencia al objeto actual: this . Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 6A continuación, podemos ver el orden de inicialización de la clase (junto con su ancestro) para comprender mejor el momento en que se activan los bloques de inicialización.

36. Para heredar una clase pública, la clase Child extiende a Parent, escribe el orden de inicialización del objeto.

Cuando se carga la clase Child, el orden de inicialización será el siguiente:
  1. Campos estáticos de la clase Padre .
  2. Bloque de inicialización estático para la clase Parent .
  3. Campos estáticos de la clase Child .
  4. Bloque de inicialización estático para la clase Child .
  5. Campos no estáticos de la clase Parent .
  6. No es un bloque de inicialización estático para la clase Parent .
  7. Constructor para la clase Padre .
  8. Campos no estáticos de la clase Child .
  9. No es un bloque de inicialización estático para la clase Child .
  10. Constructor de la clase Niño .
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 7Aquí hay un breve artículo que explica el orden de inicialización en la práctica.

37. ¿Qué relaciones conoces entre clases (objetos)?

Hay dos tipos de relaciones entre clases en Java:
  • relación ES-A
El principio IS-A en programación orientada a objetos se basa en la herencia de clases o la implementación de la interfaz. Por ejemplo, si la clase León hereda de Gato , decimos que León es Gato :
Lion IS-A Cat
(pero no todos los gatos son leones ) La situación es exactamente la misma con las interfaces. Si la clase Lion implementa la interfaz WildAnimal , entonces también están en una relación:
Lion IS-A WildAnimal
  • Relaciones HA-A
Este tipo de relación se basa en el uso de clases por otras clases, también llamado “asociación”. Una asociación es una clase que hace referencia a otra clase (o incluso entre sí). Por ejemplo, la clase Coche podría hacer referencia a la clase Pasajero , y esta sería la relación:
Car HAS-A Passenger
Y viceversa: si Passenger tiene una referencia a Car , entonces esta será la relación:
Passenger HAS-A Car

38. ¿Qué conexiones asociativas entre objetos conoces?

La agregación y la composición no son más que casos especiales de asociación. La agregación es una relación en la que un objeto es parte de otro. Por ejemplo, un pasajero puede estar en un automóvil. Además, puede haber varios pasajeros o ninguno (si hablamos de un Tesla, entonces no es necesario el conductor). Por ejemplo:
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();
   }
}
Es decir, no nos importa el número de pasajeros (o si hay alguno): la funcionalidad de la clase Car no depende de esto. La agregación también implica que cuando un objeto es usado por otro objeto, el primero puede usarse en otros objetos. Por ejemplo, un mismo estudiante puede ser miembro de un club de tejido y de un grupo de música de rockeros, y al mismo tiempo asistir a un grupo de estudiantes de inglés. Como comprenderá, la agregación es una relación asociativa más flexible entre clases. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 8La composición es una relación aún más rígida cuando un objeto no sólo es parte de otro objeto, sino que el trabajo de este otro objeto depende mucho del primero. Por ejemplo, el motor de un coche. Aunque el motor pueda existir sin el coche, es inútil fuera de él. Bueno, un coche no puede funcionar sin motor:
public class Car {
   private Engine engine;

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

   void startMoving() {
       engine.start();
           ...
   }
La composición también implica que cuando un objeto es utilizado por otro objeto, el primero no puede pertenecer a nadie más. Si volvemos a nuestro ejemplo, un motor sólo puede pertenecer a un coche, pero no a dos o más a la vez. Probablemente nos detendremos aquí hoy.Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 4 - 9
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION