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 11

Publicado en el grupo Random-ES
¡Hola! Incluso el barco más rápido y sin rumbo simplemente flotará sobre las olas. Si estás leyendo mi artículo ahora, definitivamente tienes un objetivo. Lo principal es no extraviarse, sino seguir su línea hasta el final: convertirse en desarrollador de Java. Hoy quiero continuar mi análisis de más de 250 preguntas para desarrolladores de Java, que les ayudarán a cubrir algunas de las lagunas de la teoría. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 1

97. ¿Se imponen condiciones de redefinición de acuerdos al redefinir Iguales?

El método equals() anulado debe cumplir con las siguientes condiciones (reglas):
  • reflexividad : para cualquier valor x, una expresión como x.equals(x) siempre debe devolver verdadero (cuando x != null ).

  • simetría : para cualquier valor de x e y, una expresión de la forma x.equals(y) debe devolver verdadero solo si y.equals(x) devuelve verdadero .

  • transitividad : para cualquier valor de x , y y z , si x.equals(y) devuelve verdadero y y.equals(z) también devuelve verdadero , entonces x.equals(z) debe devolver verdadero .

  • coherencia : para cualquier valor de x e y, una llamada repetida a x.equals(y) siempre devolverá el valor de la llamada anterior a este método, siempre que los campos utilizados para comparar los dos objetos no hayan cambiado entre llamadas. .

  • comparación nula : para cualquier valor x, llamar a x.equals(null) devolverá false .

98. ¿Qué sucede si no anulas Equals y HashCode?

En este caso, hashCode() devolverá un número generado en función de la ubicación de la memoria en la que está almacenado el objeto determinado. Es decir, dos objetos con exactamente los mismos campos recibirán valores diferentes al llamar a un hashCode() no anulado (después de todo, se almacenan en diferentes ubicaciones de memoria). El método equals() no anulado compara referencias para ver si apuntan al mismo objeto o no. Es decir, la comparación se realiza a través de == , y en el caso de objetos con los mismos campos siempre devolverá false . True solo lo será al comparar referencias al mismo objeto. A veces es lógico no anular estos métodos. Por ejemplo, desea que todos los objetos de una determinada clase sean únicos y anular estos métodos sólo arruinará la lógica de la unicidad. Lo principal es comprender los matices de los métodos anulados y no anulados y utilizar ambos enfoques según la situación.

99. ¿Por qué la simetría sólo es verdadera si x.equals(y) devuelve verdadero?

Una pregunta un poco extraña. Si el objeto A es igual al objeto B, entonces el objeto B es igual al objeto A. Si B no es igual al objeto A, ¿cómo es posible lo contrario? Esta es una lógica simple. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 2

100. ¿Qué es la colisión en HashCode? ¿Como lidiar con?

Una colisión de código hash es una situación en la que dos objetos diferentes tienen el mismo valor de código hash . ¿Cómo es esto posible? El hecho es que el código hash está asignado al tipo Integer , que a su vez tiene un rango de -2147483648 a 2147483647, es decir, aproximadamente 4 mil millones de enteros diferentes. Este rango es enorme, sin embargo, no es infinito. Por lo tanto, son posibles situaciones en las que dos objetos completamente diferentes tengan el mismo código hash. Esto es muy improbable, pero posible. Una función hash mal implementada también puede aumentar la frecuencia de códigos hash idénticos, lo que, por ejemplo, devolverá números en un rango pequeño, lo que aumentará la posibilidad de colisiones. Para combatir una colisión, es necesario tener una buena implementación del método hashCode para que la dispersión de valores sea máxima y la posibilidad de que se repitan valores sea mínima.

101. ¿Qué sucede si un elemento que participa en un contrato HashCode cambia su valor?

Si se ha cambiado un elemento que participa en el cálculo del código hash, entonces se cambiará el código hash del objeto en sí (si la función hash es buena). Por lo tanto, en HashMap se recomienda utilizar objetos inmutables (inmutables) como clave, porque su estado interno (campos) no se puede cambiar después de la creación. En consecuencia, su código hash tampoco se convierte después de su creación. Si usa un objeto mutable como clave, cuando cambie los campos de este objeto, su código hash cambiará y, como resultado, puede perder este par en HashMap . Después de todo, se almacenará en el depósito el código hash original y, después de cambiarlo, se buscará en otro depósito. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 3

102. Escriba los métodos Equals y HashCode para la clase Student, que consta de campos de nombre de cadena e int age

public class Student {
int age;
String name;

 @Override
 public boolean equals(final Object o) {
   if (this == o) {
     return true;
   }
   if (o == null || this.getClass() != o.getClass()) {
     return false;
   }

   final Student student = (Student) o;

   if (this.age != student.age) {
     return false;
   }
   return this.name != null ? this.name.equals(student.name) : student.name == null;
 }

 @Override
 public int hashCode() {
   int result = this.age;
   result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
   return result;
 }
}
Igual a:
  • Primero, comparamos los enlaces directamente, porque si los enlaces son al mismo objeto, ¿qué sentido tiene continuar con la verificación? Todo será verdad de todos modos .

  • Comprobar si hay tipos de clase nulos y coincidentes, porque si un objeto es un argumento de nulo u otro tipo, esto significa que los objetos no son iguales: falso .

  • Convertir el objeto de argumento a un tipo (en caso de que fuera un objeto del tipo principal).

  • Comparación de un campo de clase primitivo (después de todo, la comparación mediante =! es suficiente para ello ), si el campo no es igual - false .

  • Verificar un campo no primitivo en busca de nulos e iguales (en String , el método se anula y se comparará correctamente), si ambos campos son nulos o iguales , entonces la verificación finaliza y el método devuelve verdadero .

Código hash:
  • Establecer el valor del código hash inicial en la primitiva de edad del objeto .

  • Multiplicar el código hash actual por 31 (para una mayor difusión) y agregarle el código hash de un campo de cadena no primitivo (si no es nulo).

  • Devolviendo el resultado.

  • Como resultado de esta anulación del código hash, los objetos con el mismo nombre y valores int siempre devolverán el mismo valor.

103. ¿Cuál es la diferencia entre usar if (objstanceof Student) y if (getClass() == obj.getClass())?

Veamos qué hace cada enfoque:
  • instancia de comprueba si una referencia de objeto en el lado izquierdo es una instancia de un tipo en el lado derecho o algún subtipo del mismo.

  • getClass() == ... comprueba la identidad del tipo.

Es decir, si getClass() comprueba la identidad completa de una clase, entonces instanciaof devolverá verdadero incluso si el objeto es sólo un subtipo, lo que puede darnos más flexibilidad al utilizar activamente el polimorfismo. En realidad, ambos enfoques son buenos si comprendes las características de su trabajo y los aplicas en los lugares correctos.

104. Dé una breve descripción del método clone().

Clone() es un método de la clase Object , cuyo propósito es crear y devolver un clon del objeto actual (una copia del objeto actual). Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 4Para usarlo, necesita implementar la interfaz del marcador Cloneable :
Student implements Cloneable
Y anule el método clone() en sí :
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
Después de todo, en la clase Objeto está protegido, es decir, será visible solo en la clase Estudiante , pero no visible para las clases externas.

105. ¿Cuál es la peculiaridad del método clone() que trabaja con los campos de un objeto de tipo de referencia?

Al clonar objetos, solo se copian los valores primitivos y el valor de las referencias de objetos. Esto significa que si un objeto tiene un enlace a otro objeto en su campo interno, entonces sólo se clonará este enlace, pero este otro objeto en sí no será clonado. De hecho, esto es lo que llaman clonación de superficie. Bueno, ¿qué pasa si necesita una clonación completa con clonación de todos los objetos anidados? ¿Cómo asegurarse de que no se trate de copias de enlaces, sino de clones completos de objetos con otras celdas de memoria ocupadas en el montón? De hecho, todo es bastante simple: para esto también necesita anular el método clone() en cada clase de estos objetos internos y agregar una interfaz de marcador: Cloneable . Entonces no serán las referencias a los objetos las que se copiarán, sino los objetos mismos, porque ahora también tienen la capacidad de copiarse a sí mismos.

Excepciones

106. ¿Cuál es la diferencia entre error y excepción?

Tanto las excepciones como los errores son subclases de la clase Throwable . Sin embargo, tienen sus diferencias. El error indica un problema que ocurre principalmente debido a recursos insuficientes del sistema. Y nuestra aplicación no debería detectar este tipo de problemas. Algunos de los ejemplos de errores son fallas del sistema y errores de falta de memoria. Los errores ocurren principalmente en tiempo de ejecución, ya que son de un tipo no verificado. Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 5Las excepciones son problemas que pueden ocurrir en tiempo de ejecución y en tiempo de compilación. Normalmente, esto sucede en el código escrito por los desarrolladores. Es decir, las excepciones son más predecibles y más dependientes de nosotros como desarrolladores. Al mismo tiempo, los errores son más aleatorios y más independientes de nosotros, sino que dependen de problemas del propio sistema en el que se ejecuta nuestra aplicación.

107. ¿Cuál es la diferencia entre marcado y no marcado, excepción, lanzamiento, lanzamiento?

Como dije antes, una excepción es un error durante la ejecución del programa y durante la compilación que ocurrió en el código escrito por el desarrollador (debido a alguna situación anormal). Checked es un tipo de excepción que siempre debe manejarse mediante el mecanismo try-catch o incluirse en los métodos anteriores. Throws se utiliza en el encabezado del método para indicar posibles excepciones lanzadas por el método. Es decir, este es el mecanismo para "lanzar" excepciones a los métodos anteriores. Sin marcar es un tipo de excepción que no necesita ser manejada y normalmente es menos predecible y menos probable que ocurra. Sin embargo, también se pueden procesar si se desea. Throw se utiliza cuando se lanza una excepción manualmente, por ejemplo:
throw new Exception();

108. ¿Cuál es la jerarquía de las excepciones?

La jerarquía de excepciones es muy grande y extensa, incluso demasiado extensa para contarlo todo aquí. Por lo tanto, consideraremos solo sus vínculos clave: Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 6aquí, en la parte superior de la jerarquía, vemos la clase Throwable , una clase general, el antepasado de la jerarquía de excepciones, que a su vez se divide en:
  • Error : errores críticos que no se pueden verificar.
  • Excepción : excepciones marcadas.
La excepción se divide en varias excepciones de tiempo de ejecución no verificadas y varias excepciones verificadas.

109. ¿Qué es la excepción marcada y no marcada?

Como dije antes:
  • Marcado : excepciones que debe manejar de alguna manera, es decir, procesarlas en un bloque try-catch o "reenviarlas" al método anterior. Para hacer esto, en la firma del método, después de enumerar los argumentos del método, debe usar la palabra clave trows <tipo de excepción> , que indica a los usuarios del método que el método puede generar esta excepción (algo así como una advertencia) y transfiere la responsabilidad de manejar la excepción para los usuarios de este método.

  • Sin marcar : excepciones que no necesitan ser procesadas, ya que no se verifican en el momento de la compilación y, por regla general, son más impredecibles. Es decir, la principal diferencia con los check es que para ellos estos mecanismos try-catch o throwing funcionan igual, pero no son obligatorios.

101. Escriba un ejemplo de cómo interceptar y manejar una excepción en un bloque try-catch de un método.

try{                                                 // начало блока перехвата
 throw new Exception();                             // ручной бросок исключения
} catch (Exception e) {                              // данное исключение и его потомки будут перехватываться
 System.out.println("Упс, что-то пошло не так =("); // вывод некоторого исключения в консоль
}

102. Escriba un ejemplo de cómo detectar y manejar una excepción utilizando sus propias excepciones.

Primero, escribamos nuestra propia clase de excepción, que hereda de Exception y anula su constructor con un mensaje de error:
public class CustomException extends Exception {

 public CustomException(final String message) {
   super(message);
 }
}
Bueno, entonces lo lanzaremos manualmente y lo interceptaremos como en la pregunta anterior:
try{
 throw new CustomException("Упс, что-то пошло не так =(");
} catch (CustomException e) {
 System.out.println(e.getMessage());
}
Y nuevamente, cuando lo ejecute, obtendrá el siguiente resultado en la consola:
Ups, algo salió mal =(
Análisis de preguntas y respuestas de entrevistas para desarrollador Java.  Parte 11 - 7Puede obtener más información sobre las excepciones aquí . Bueno, ¡eso es todo por hoy! ¡Nos vemos en la siguiente parte!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION