CodeGym /Blog Java /Random-ES /Explorando preguntas y respuestas de una entrevista de tr...
John Squirrels
Nivel 41
San Francisco

Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java. parte 4

Publicado en el grupo Random-ES
¡Hola a todos! Hoy continúo con mi revisión de las preguntas de la entrevista para desarrolladores de Java. Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 1

29. ¿Se puede utilizar return en un constructor?

Sí, pero sólo sin un valor a la derecha de la palabra clave de retorno . Puedes usar return; como declaración auxiliar en un constructor para terminar (interrumpir) urgentemente la ejecución de código adicional y finalizar la inicialización del objeto. Por ejemplo, supongamos que tenemos una clase Cat , y si un Cat no tiene hogar ( isHomeless = true , entonces queremos terminar la inicialización y no completar los 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 si hablamos de valores concretos, entonces la palabra clave return no puede devolver un valor específico porque:
  • cuando declaras un constructor, no tendrás nada parecido al tipo de retorno;
  • como regla general, el constructor se llama implícitamente durante la creación de instancias;
  • el constructor no es un método: es un mecanismo separado cuyo único propósito es inicializar variables de instancia, es decir, estamos usando el operador new para crear un objeto.
Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 2

30. ¿Se puede lanzar una excepción desde un constructor?

Los constructores trabajan con excepciones de la misma manera que lo hacen los métodos. Los métodos nos permiten lanzar excepciones escribiendo throws <ExceptionType> en el encabezado del método. Y los constructores nos permiten hacer lo mismo. Cuando heredamos y definimos el constructor de una clase secundaria, podemos ampliar el tipo de excepción, por ejemplo, IOException -> Exception (pero no al revés). Usemos el constructor de la clase Cat como ejemplo de un constructor que lanza una excepción. Digamos que cuando creamos un objeto, queremos ingresar 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 escribimos en el encabezado como una posible excepción lanzada.

31. ¿Cuáles son los elementos de un encabezado de clase? Escribe un ejemplo

Para ilustrar los elementos que componen un encabezado de clase, veamos un pequeño esquema:
  • los elementos obligatorios aparecen entre corchetes <>
  • los elementos opcionales están en {}
{modificador de acceso}{estático}{final}{abstracto}<nombre de clase>{herencia de la clase principal}{implementación de interfaces} Entonces, lo que tenemos: { modificador de acceso} : solo los modificadores de acceso público y predeterminado están disponibles para el clase. {static} — el modificador estático indica que esta clase es estática; se aplica sólo a clases internas (clases dentro de otras clases). {final} : este es el modificador final , por supuesto, que hace que la clase no sea heredable (un ejemplo listo para usar es String ). {abstract} : el modificador abstracto , que indica que la clase puede tener métodos no implementados. Este modificador entra en conflicto con el modificador final . El encabezado de la clase solo puede tener uno de ellos ya que el modificador abstracto significa que la clase se heredará y sus elementos abstractos se implementarán. Pero final indica que esta es la versión final de la clase y que no se puede heredar. En realidad, utilizar ambos modificadores simultáneamente sería absurdo. El compilador no nos permitirá hacer esto. <clase> es una palabra clave obligatoria que indica una declaración de clase. <nombre de clase> es un nombre de clase simple que se convierte en el identificador de una clase Java específica. El nombre de clase completo consta del nombre del paquete calificado más '.' más el nombre de clase simple. {herencia de la clase principal} es una indicación de la clase principal (si la hay) utilizando la palabra clave extends . Por ejemplo, ... extiende ParentClass . {implementación de interfaces} : una lista de las interfaces que implementa esta clase (si las hay), utilizando la palabra clave implements . Por ejemplo: ... implementa FirstInterface, SecondInterface ... Como ejemplo, considere el encabezado de clase de la clase Lion , que hereda Cat e implementa la interfaz WildAnimal :
public final class Lion extends Cat implements WildAnimal
Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 3

32. ¿Cuáles son los elementos del encabezado de un método? Escribe un ejemplo

Al considerar los elementos que componen el encabezado de un método, consideremos nuevamente un pequeño esquema:
  • los elementos obligatorios aparecen entre corchetes <>
  • los elementos opcionales están en {}
{modificador de acceso}{estático}{abstracto}{final}{sincronizado} {nativo} <valor de retorno><nombre del método> <(>{parámetros del método}<}>{lanzar excepciones} {modificador de acceso}: todos los modificadores de acceso son disponible para el método: público , protegido , predeterminado , privado . {estático} : el modificador estático , que indica que el método es estático y, por lo tanto, está asociado con la clase, no con un objeto. {abstract} : el modificador abstracto , que indica que el método no tiene implementación (cuerpo). Para funcionar correctamente, la clase que declara el método también debe tener el modificador abstracto . Al igual que en el encabezado de la clase, este modificador entra en conflicto con el modificador final , y también entra en conflicto con el modificador estático , porque un El método abstracto implica anular el método en un descendiente, y los métodos estáticos no se pueden anular. {finale} : el modificador final , que indica que este método no se puede anular. {synchronized} : el modificador sincronizado , lo que significa que el método está protegido contra acceso simultáneo a él desde diferentes hilos. Si el método no es estático, entonces está cerrado para este mutex del objeto. Si el método es estático, entonces está cerrado para el mutex de la clase actual. {nativo} : el modificador nativo indica que el método está escrito en otro lenguaje de programación. <tipo de retorno> : el tipo de valor que el método debe devolver. Si el método no devuelve nada, entonces se anula . <nombre del método> : el nombre del método, es decir, su identificador en el sistema. {parámetros del método} : los parámetros que acepta el método: son necesarios para implementar su funcionalidad. {excepciones lanzadas} : arroja <ExceptionType> : una lista de las excepciones marcadas que este método puede generar. Ofreceré lo siguiente como ejemplo de un encabezado de método:
public static void main(String[] args) throws IOException

33. Cree un constructor predeterminado en una clase secundaria si aún no está definido en la clase base (pero sí se define un constructor diferente)

No estoy seguro de entender completamente la pregunta, pero tal vez signifique que tenemos algún constructor como este en la clase principal:
public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
En ese caso, en la clase principal, definitivamente necesitamos definir un constructor que inicializará la clase principal (es decir, llamará al constructor principal):
public class Lion extends Cat {

   public Lion(int age, String name) {
       super(age, name);
   }
}
Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 4

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

En Java, esto tiene dos significados diferentes. 1. Es una referencia al objeto actual, por ejemplo, this.age = 9 . Es decir, this se refiere al objeto en el que se utiliza y al que se refiere el código con esto . El objetivo principal es mejorar la legibilidad del código y evitar la ambigüedad. Por ejemplo, si un campo de instancia y un argumento de método tienen el mismo nombre:
public void setName(String name) {
   this.name = name;
}
Es decir, this.name es el campo del objeto, mientras que nombre es el parámetro del método. Esta referencia no se puede utilizar en métodos estáticos. 2. En el constructor, esto se puede llamar como un método, por ejemplo, this(value) . En este caso será una llamada a otro constructor de la misma clase. Básicamente, puedes llamar a dos constructores durante el proceso de creación de un objeto:
public Cat(int age, String name) {
   this(name);
   this.age = age;
}

public Cat(String name) {
   this.name = name;
}
Al llamar al primer constructor para crear un objeto Cat , ambos campos de instancia se inicializarán correctamente. Aquí hay un par de matices:
  1. this() sólo funciona en un constructor.
  2. Una referencia a otro constructor debe estar en la primera línea del bloque constructor (cuerpo). Esto significa que un constructor no puede llamar a más de un (otro) constructor de su clase.
Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 5

35. ¿Qué es un inicializador?

Según tengo entendido, esta pregunta trata sobre bloques de inicialización ordinarios y estáticos. Primero recordemos qué es la inicialización. La inicialización es la creación, activación, preparación y definición de campos. Preparar un programa o componente para que esté listo para su uso. Recordarás que cuando creas un objeto, una variable de clase se puede inicializar inmediatamente cuando se declara:
class Cat {
   private int age = 9;
   private String name = "Tom";
O configurarlo después del hecho a través del 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: puedes configurar una variable de instancia usando un bloque de inicialización, que toma la forma de llaves {} dentro de una clase, sin un nombre (como un método o constructor sin nombre):
class Cat {
   private int age;
   private String name;

   {
       age = 10;
       name = "Tom";
   }
Un bloque de inicialización es un fragmento de código que se carga cuando se crea un objeto. Estos bloques se utilizan normalmente para realizar ciertos cálculos complejos que se requieren cuando se carga una clase. Los resultados de estos cálculos se pueden establecer como valores de variables. Además de los bloques de inicialización habituales, existen bloques estáticos. Se ven iguales pero tienen la palabra clave estática delante de la llave de apertura:
class Cat {
   private static int age;
   private static String name;

   static{
       age = 10;
       name = "Tom";
   }
Este bloque es igual que el anterior. Pero si el ordinario se ejecuta cuando se inicializa cada objeto, entonces el estático se ejecuta solo una vez, cuando se carga la clase. Como regla general, ciertos cálculos complejos se realizan en un bloque estático, que se utiliza para inicializar variables de clase estáticas. Se aplican las mismas restricciones a un bloque estático que a los métodos estáticos: no se pueden utilizar datos no estáticos, como una referencia al objeto actual ( this ) en un bloque estático. Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 6Ahora podemos observar el orden de inicialización de la clase (junto con su clase principal) para comprender mejor cuándo se invocan exactamente los bloques de inicialización.

36. Dada una clase Child pública que extiende Parent, escriba el orden de inicialización del objeto.

Al cargar la clase Child , el orden de inicialización será el siguiente:
  1. Campos de clase estática de la clase Padre .
  2. Bloque de inicialización estática de la clase Parent .
  3. Campos estáticos de la clase Сhild .
  4. Bloque de inicialización estático de la clase Child .
  5. Campos no estáticos de la clase Parent .
  6. Bloque de inicialización no estático de la clase Parent .
  7. Constructor de clase padre .
  8. Campos no estáticos de la clase Сhild .
  9. Bloque de inicialización no estático de la clase Сhild .
  10. El constructor de la clase Сhild .
Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 4 - 7

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

Hay dos tipos de variables en Java: tipos primitivos y referencias a objetos completos.
  • Relaciones IS-A
El principio IS-A de OOP se basa en la herencia de clases o la implementación de interfaces. Por ejemplo, si la clase Lion hereda Cat , entonces decimos que Lion es un Cat :
Lion IS-A Cat
(pero no todos los gatos son leones ) La misma situación existe con las interfaces. Si la clase Lion implementa la interfaz WildAnimal , entonces también existen en la relación:
Lion IS-A WildAnimal
  • Relación TIENE-A
Este tipo de relación es donde una clase utiliza otras clases, también llamada "asociación". Una asociación es una clase que hace referencia a otra clase (o referencias mutuas entre sí). Por ejemplo, la clase Auto puede hacer referencia a la clase Pasajero , lo que constituiría la siguiente 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é relaciones de objeto asociativo 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 podría estar ubicado en un automóvil. Es más, puede haber varios pasajeros o ninguno (y si hablamos de Tesla, puede que no haya ningún 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("Transporting passenger - " + passenger.toString());
       }
       passengers.clear();
   }
}
En otras palabras, el número de pasajeros (cualquiera) para nosotros no es importante: de ello no depende la funcionalidad de la clase Car . La agregación también implica que cuando otro objeto usa un objeto, el primer objeto puede ser usado por otros objetos. Por ejemplo, el mismo estudiante puede estar en un club de tejido y en una banda de rock y asistir simultáneamente a una clase de español. Como puedes imaginar, la agregación es una relación asociativa más flexible entre clases. La composición es una relación aún más estrecha en la que un objeto no sólo es parte de otro objeto, sino que el trabajo de un objeto depende en gran medida de otro. Por ejemplo, un coche tiene motor. Un motor puede existir sin un automóvil, pero es inútil fuera de un automóvil. Y 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 otro objeto usa un objeto, el primer objeto no puede pertenecer a ningún otro objeto. Volviendo a nuestro ejemplo, un motor sólo puede pertenecer a un coche, no a dos o más al mismo tiempo. Creo que es suficiente por hoy, así que nos detendremos aquí.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION