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 8

Publicado en el grupo Random-ES
¿Práctica o teoría? ¿Qué es más importante? Naturalmente, mucha gente dirá que la práctica es más importante. Por ejemplo, practica hasta que se ponga el sol y serás feliz. Me atreveré a no estar de acuerdo con esto. Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 1Durante las entrevistas, nadie sabrá nunca lo genial que eres cuando practicas. En su lugar, se le pedirá que demuestre sus habilidades teóricas. No será hasta más tarde, cuando hayas superado todas las capas de entrevistas y te asignen un proyecto, que aplicarás tus habilidades prácticas. Usted puede objetar, diciendo que a veces le dan una tarea de prueba, por lo que aún necesita práctica. No estoy en desacuerdo, pero mi punto es que esto es A VECES, pero SIEMPRE es necesario demostrar conocimiento de la teoría en una entrevista. ¿Sientes la diferencia? Todo esto significa que debes tener una base teórica sólida bajo tus pies, y eso es lo que vamos a seguir construyendo hoy. Más específicamente, continuaremos analizando las preguntas que se hacen a menudo en las entrevistas.

71. ¿Qué sucede si no anulamos el método toString() de Enum?

Supongamos que tenemos la siguiente enumeración :
public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;
}
Mostremos el campo ESTUDIANTE en la consola llamando a su método toString() :
System.out.println(Role.STUDENT.toString());
Como resultado, obtenemos la siguiente salida de consola:
ALUMNO
Por lo tanto, vemos que para una enumeración , la implementación predeterminada de toString() devuelve el nombre de la constante misma.

72. ¿Puedes declarar un constructor dentro de un Enum?

Sí, claro. El constructor es lo que establece los valores de los campos internos de la enumeración . Como ejemplo, agreguemos dos campos a la enumeración anterior ( ageFrom y ageTo ) para indicar el rango de edad para cada rol:
public enum Role {
   STUDENT(5,18),
   TEACHER(20,60),
   DIRECTOR(40,70),
   SECURITY_GUARD(18,50);

   int ageFrom;
   int ageTo;

   Role(int ageFrom, int ageTo) {
       this.ageFrom = ageFrom;
       this.ageTo = ageTo;
   }
}

73. ¿Cuál es la diferencia entre == y es igual()?

Esta es una de las preguntas de entrevista más comunes que se hacen a los aspirantes a desarrolladores de Java. Para empezar, al comparar valores simples ( int , char , double ...), usamos == , ya que estas variables contienen valores concretos que se pueden comparar directamente. Es más, las variables primitivas no son objetos completos: no heredan la clase Object y no tienen un método equals() . Si estamos hablando de comparar variables que hacen referencia a objetos, entonces necesitamos saber que == solo compara el valor de las referencias, es decir, si se refieren al mismo objeto o no. Incluso si todos los datos de un objeto son idénticos a todos los datos de otro, usar == para una comparación producirá un resultado negativo ( falso ), porque son objetos separados. Como habrás adivinado, utilizamos el método equals() para comparar variables de referencia. Este es uno de los métodos estándar de la clase Objeto y es necesario para una comparación completa de objetos. Pero debo decir de inmediato que para que este método funcione correctamente, debe anularse para indicar exactamente cómo se deben comparar los objetos. Si no anula el método, obtendrá la implementación predeterminada, que compara los objetos usando == . En IntelliJ IDEA, puede anularlo automáticamente usando un atajo de IDEA: Alt+Insert . En la ventana que aparece, seleccione igual a() y hashCode() . Luego seleccione los campos que deberían estar involucrados. ¡Voilá! Los métodos se implementan automáticamente. A continuación se muestra un ejemplo de cómo un método de igualdad generado automáticamente busca la clase Cat más simple posible con dos campos: int age y String name :
@Override
public boolean equals(final Object o) {
   if (this == o) return true;
   if (o == null || this.getClass() != o.getClass()) return false;
   final Cat cat = (Cat) o;
   return this.age == cat.age &&
           Objects.equals(this.name, cat.name);
}
Cuando se trata de enum , no existe una diferencia práctica entre == y equals() . Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 2Después de todo, una enumeración almacena constantes, e incluso cuando comparamos valores idénticos usando == , obtendremos true , ya que las referencias comparadas siempre apuntarán a los mismos objetos. Y usar equals() también nos da el resultado correcto. Si ingresa al cuerpo del método igual para Enum , verá que la clase Enum tiene la siguiente implementación: Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 3¡En el interior podemos ver una buena comparación de referencias! Para resumir, para enum s, podemos comparar correctamente usando == y equals() . Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 4

74. ¿Qué hace el método ordinal() de Enum?

Cuando llamamos al método int ordinal() en un campo de enumeración , obtenemos el índice de base cero del campo en la lista de valores de enumeración. Llamemos a este método en un campo de la enumeración Rol , que consideramos anteriormente:
System.out.println(Role.DIRECTOR.ordinal());
En consecuencia, la consola muestra:
2

75. ¿Se puede utilizar Enum con TreeSet o TreeMap en Java?

Podemos usar tipos de enumeración en TreeSet y TreeMap . Y podemos escribir esto:
TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
Y la consola mostrará:
ESTUDIANTE PROFESOR DIRECTOR GUARDIA_SEGURIDAD
Obtuvimos el resultado, pero no alfabéticamente. El punto es que si usamos campos de enumeración como valores de TreeSet o como claves de TreeMap , entonces los campos se ordenan en su orden natural (en el orden en que se especifican en la enumeración ). Comprender que así es como funciona nos ayuda a escribir mejor código.

76. ¿Cómo se relacionan los métodos ordinal() y compareTo() de Enum?

Como se mencionó anteriormente, ordinal() devuelve el índice de un campo en la lista de campos de enumeración. Además, al considerar la pregunta anterior, vio que cuando los campos de enumeración se colocan en un TreeSet (que es un conjunto ordenado), adoptan el orden en que se declaran en la enumeración . Y como sabemos, TreeSet y TreeMap clasifican elementos llamando al método compareTo() de su interfaz Comparable . Esto nos dice que la clase Enum implementa la interfaz Comparable , lo que significa que implementa el método compareTo() , que utiliza internamente el método ordinal() para determinar el orden de clasificación. Al ingresar a la clase Enum , podemos confirmar nuestra suposición: Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 5Y aquí está el cuerpo del método en sí: Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 6El método ordinal() no se llama aquí. En su lugar, se utiliza la variable ordinal , que es el número de índice del elemento en la enumeración. El método ordinal()Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 8 - 7 en sí no es más que un captador de la variable ordinal .

77. Escribe un ejemplo de enumeración.

En las preguntas discutidas anteriormente, ya he dado ejemplos de enumeraciones . No veo ninguna razón para duplicar el código aquí. Por ejemplo, consulte la Pregunta 72 sobre un constructor en una enumeración.

78. ¿Se puede utilizar un Enum en una caja de interruptor?

¡Puede ser y debe ser! Al observar mi experiencia, señalaré que uno de los usos más comunes de enum es en construcciones lógicas como declaraciones de cambio . En este caso, puede proporcionar todos los casos posibles : una vez que escriba la lógica para cada campo de enumeración , ¡ni siquiera necesitará una cláusula predeterminada ! Después de todo, si usa String o un valor numérico, como int , puede recibir un valor inesperado, pero eso es imposible con un enum . Así es como se vería una declaración de cambio para el ejemplo anterior:
public void doSomething(Role role) {
   switch (role) {
       case STUDENT:
           // some logic for STUDENT
           break;
       case TEACHER:
           // some logic for TEACHER
           break;
       case DIRECTOR:
           // some logic for DIRECTOR
           break;
       case SECURITY_GUARD:
           // some logic for SECURITY_GUARD
           break;
   }
}

79. ¿Cómo obtengo todos los valores posibles de un Enum?

Si necesita obtener todos los valores de enumeración posibles, existe un método de valores () , que devuelve una matriz de todos los valores posibles para la enumeración en su orden natural (es decir, en el orden en que se especifican en la enumeración ). Ejemplo:
Role[] roles = Role.values();
for (Role role : roles) {
   System.out.println(role);
}
Tendremos lo siguiente en la consola:
ESTUDIANTE PROFESOR DIRECTOR GUARDIA_SEGURIDAD

API de transmisión

80. ¿Qué es una secuencia en Java?

La API Java Stream es una forma relativamente nueva de interactuar con un flujo de datos, lo que nos permite procesar big data de manera más conveniente y compacta, así como procesar datos en paralelo entre una cierta cantidad de flujos, lo que potencialmente aumenta el rendimiento.

81. Nombra las principales propiedades de las transacciones.

El tema aquí es la API Stream, pero la pregunta es sobre las transacciones. Hmm... Primero, comprendamos qué es una transacción. Una transacción es un grupo de operaciones secuenciales en una base de datos. Representa una unidad lógica de trabajo. Una transacción se puede ejecutar independientemente de otras transacciones concurrentes de forma completa y exitosa, manteniendo así la integridad de los datos, o no ejecutarse en absoluto, en cuyo caso no tiene ningún efecto. Las transacciones tienen cuatro propiedades principales, que podemos recordar fácilmente gracias al acrónimo ACID . Veamos qué significa cada letra de este acrónimo: A significa Atomicidad . Esta propiedad garantiza que ninguna transacción se confirma parcialmente en el sistema. O se ejecutarán todas sus suboperaciones o ninguna de ellas ( todo o nada ). С significa Consistencia . Esta propiedad garantiza que cada transacción exitosa solo enviará resultados válidos. En otras palabras, esto es una garantía de que si la transacción tiene éxito, se obedecerán todas las reglas del sistema para datos específicos. Si la transacción no tiene éxito, no se ejecutará y los datos del sistema volverán a su estado anterior. I significa aislamiento . Esta propiedad significa que cuando se ejecuta una transacción, las transacciones simultáneas no deben afectar su resultado. Esta propiedad consume muchos recursos, por lo que, como regla general, se implementa parcialmente, lo que permite ciertos niveles de aislamiento que resuelven problemas de aislamiento específicos. Discutiremos esto con más detalle en la siguiente pregunta. D significa Durabilidad . Esta propiedad garantiza que si el usuario recibe la confirmación de que la transacción se completó, entonces puede estar seguro de que los cambios no serán cancelados por alguna falla. Es decir, puedes estar seguro de que alguna falla del sistema operativo no afectará tus datos si ya recibiste la confirmación de que tu transacción finalizó exitosamente.

82. ¿Cuáles son los niveles de aislamiento de transacciones?

Como dije antes, cuando se trata de propiedades ACID, garantizar el aislamiento es un proceso que requiere muchos recursos. En consecuencia, esta propiedad se implementa parcialmente. Existen diferentes niveles de aislamiento: cuanto mayor sea el nivel, más grave será el impacto en el rendimiento. Antes de pasar a los niveles de aislamiento de transacciones, debemos considerar varios problemas que ocurren debido a un aislamiento de transacciones insuficiente :
  • lecturas fantasma : cuando la misma solicitud, llamada más de una vez dentro de una sola transacción, produce resultados diferentes debido a inserciones de otra transacción;

  • lecturas no repetibles : cuando la misma solicitud, llamada más de una vez dentro de una sola transacción, produce datos diferentes debido a cambios (actualizaciones) y eliminaciones por parte de otra transacción;

  • lecturas sucias : lectura de datos aún no confirmados que han sido agregados o modificados por una transacción y posteriormente se revierten;

  • Actualizaciones perdidas : cuando un bloque de datos es cambiado simultáneamente por diferentes transacciones y todos los cambios excepto el último se pierden (similar a una condición de carrera en subprocesos múltiples).

Da la casualidad de que los niveles de aislamiento de transacciones se caracterizan por los problemas de aislamiento contra los que protegen. Considere la siguiente tabla de niveles de aislamiento y los problemas contra los que protegen:
Nivel de aislamiento lecturas fantasma Lecturas no repetibles lecturas sucias Actualización perdida
SERIALIZABLE + + + +
LECTURA REPETIBLE - + + +
LEER COMPROMETIDO - - + +
LEER SIN COMPROMISO - - - +
NINGUNO - - - -
Y no olvide la otra cara: cuanto mayor es el nivel de aislamiento, más tardan en procesarse las transacciones (dada la ejecución paralela de múltiples transacciones).

83. ¿Cuál es la diferencia entre una Declaración y una Declaración Preparada?

Aquí hemos cambiado abruptamente la transición a las características de JDBC . En cualquier caso, primero averigüemos de qué se trata una Declaración . Es un objeto utilizado para formar consultas SQL. JDBC utiliza tres tipos: Declaración , PreparedStatement y CallableStatement . No consideraremos CallableStatement hoy. En cambio, estamos hablando de la diferencia entre Statement y PreparedStatement .
  1. La declaración se utiliza para ejecutar consultas SQL simples sin parámetros de entrada en tiempo de ejecución. PrepareStatement puede aceptar parámetros de entrada en tiempo de ejecución.

  2. Para establecer parámetros para PreparedStatement , los parámetros de entrada se escriben como signos de interrogación en la solicitud, por lo que pueden reemplazarse por algún valor usando varios configuradores, como setDouble() , setFloat() , setInt() , setTime() ... Esto significa que no insertará el tipo incorrecto de datos en la solicitud.

  3. PreparedStatement está precompilado y utiliza almacenamiento en caché, por lo que se puede ejecutar un poco más rápido que una solicitud realizada a partir de objetos Statement . Como resultado, las sentencias SQL que se ejecutan con frecuencia se crean como objetos PreparedStatement para mejorar el rendimiento.

  4. La declaración es vulnerable a la inyección de SQL, pero PreparedStatement las previene.

¡Y con eso, terminaremos el día!
Comentarios
  • Populares
  • Nuevas
  • Antiguas
Debes iniciar sesión para dejar un comentario
Esta página aún no tiene comentarios