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 2

Publicado en el grupo Random-ES
¡Hola de nuevo a todos! Seguimos buscando respuestas a preguntas para desarrolladores de Java junior, medio y senior. Las preguntas son súper interesantes. Personalmente me gusta analizarlos, porque me ayuda a encontrar lagunas en mis conocimientos teóricos y, a veces, en los lugares más inesperados. Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 2 - 1La parte anterior se puede encontrar en este artículo . Pero antes de comenzar, quiero recordarles que:
  1. Saltaré las preguntas que se superponen con esta serie de artículos para no duplicar información innecesariamente. Recomiendo leer estos artículos, ya que cubren las preguntas más comunes (populares) de las entrevistas sobre Java Core.
  2. Podría describir las respuestas con más detalle, pero no lo haré, porque entonces cada respuesta podría prolongarse durante todo el artículo. Y nadie te pedirá ese nivel de detalle en ninguna entrevista de trabajo.
Dejaré enlaces para un estudio más profundo si quieres. ¡Volemos!

11. Nombra todos los métodos de la clase Objeto.

La clase Object tiene 11 métodos:
  1. Class<?> getClass() — obtiene la clase del objeto actual;

  2. int hashCode() — obtiene el código hash del objeto actual;

  3. booleano igual a (Objeto obj) : compara el objeto actual con otro objeto;

  4. Clon de objeto() : crea y devuelve una copia del objeto actual;

  5. String toString() : obtiene la representación en cadena del objeto;

  6. void notify() — despierta un hilo esperando en el monitor de este objeto (la elección del hilo es aleatoria);

  7. void notifyAll() — activa todos los hilos que esperan en el monitor de este objeto;

  8. void wait() : hace que el hilo actual espere en el monitor actual (congela el hilo actual) hasta que una llamada notify o notifyAll despierte el hilo (solo funciona en un bloque sincronizado);

  9. espera vacía (tiempo de espera largo) : hace que el hilo actual espere en el monitor actual (en el bloque sincronizado actual), pero con un tiempo de espera para salir del estado de espera (o nuevamente, hasta que una llamada de notificación o notificación a todos despierte el hilo);

  10. void wait(long timeout, int nanos) : este método es como el método anterior, pero con un tiempo de espera más preciso;

  11. void finalize() : este método se llama (finalmente) antes de que el recolector de basura elimine el objeto. Se utiliza para limpiar los recursos adquiridos.

Para utilizar correctamente los métodos hashCode , equals , clone , toString y finalize , deben anularse de acuerdo con las especificaciones de la tarea actual.

12. ¿Cuál es la diferencia entre intentar con recursos y intentar capturar finalmente cuando se trabaja con recursos?

Normalmente, cuando se usa try-catch-finally , el bloque final se usa para cerrar recursos. Java 7 introduce la nueva declaración de prueba con recursos . Es análogo a try-catch-finally para liberar recursos, pero más compacto y legible. Recordemos cómo se ve try-catch-finally :
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
Ahora reescribamos este código, pero usando try-with-resources :
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
Eso es algo más sencillo, ¿no crees? Además del código más simple, hay un par de puntos más a tener en cuenta:
  1. En try-with-resources , los recursos declarados entre paréntesis (recursos que se cerrarán) deben implementar la interfaz AutoCloseable y su único método close() .

    El método close se ejecuta en un bloque finalmente implícito ; de lo contrario, ¿cómo descubriría el programa exactamente cómo cerrar el recurso?

    Pero probablemente rara vez escriba sus propias implementaciones de recursos y su método de cierre.

  2. Los bloques se ejecutan en este orden:

    1. El bloque de prueba .
    2. El bloque finalmente implícito .
    3. El bloque catch , que detecta excepciones que ocurren en los pasos anteriores.
    4. El bloque finalmente explícito .

    Como regla general, las excepciones lanzadas más abajo en la lista interrumpen las lanzadas más arriba.

Imagina que estás usando try-catch-finally y obtienes una excepción en el bloque try . Luego, inmediatamente comienza a ejecutarse el bloque catch especificado, en el que hemos escrito otra excepción (por ejemplo, con un mensaje que describe el error con más detalle) y desea que el método arroje esta excepción hacia arriba . Luego se ejecuta el bloque finalmente y también se genera una excepción. Pero esta vez uno diferente. ¿Cuál de estas dos excepciones arrojará finalmente este método? ¡ La excepción lanzada por el bloque finalmente ! Pero ahora hemos llegado a otro punto sobre la prueba con recursos . Consideremos cómo se comporta try-with-resources en la misma situación. Obtenemos una excepción en el bloque try cuando intentamos cerrar recursos en el método close() , es decir, en el bloque implícito finalmente . ¿ Cuál de estas excepciones detectará el bloque catch ? ¡ El que arroja el bloque try ! Se ignorará la excepción del bloque finalmente implícito (del método perder() ). Esta ignorancia de excepciones también se denomina supresión de excepciones.

13. ¿Qué son las operaciones bit a bit?

Las operaciones bit a bit son operaciones sobre secuencias de bits. Incluyen operaciones lógicas y cambios bit a bit. Operadores logicos:
  • bit a bit AND : compara valores de bits. Cualquier bit establecido en 0 (falso) establece el bit correspondiente en el resultado en 0. Es decir, si un bit es 1 (verdadero) en ambos valores comparados, entonces el bit resultante también será 1.

    Denotado como AND o &

    Ejemplo: 10111101 y 01100111 = 00100101

  • bit a bit OR : esta operación es la opuesta a la anterior. Cualquier bit establecido en 1 establece el bit correspondiente en el resultado en 1. En consecuencia, si el bit es 0 en ambos valores comparados, entonces el bit resultante también será 0.

    Denotado como OR o |

    Ejemplo: 10100101 | 01100011 = 11100111

  • bit a bit NOT : este operador se aplica a un solo valor. Voltea (invierte) los bits. Es decir, los bits que eran 1 pasan a ser 0; y los que eran 0 pasan a ser 1.

    Denotado como NOT o ~

    Ejemplo: ~10100101 = 01011010

  • OR exclusivo bit a bit : compara valores de bits. Si ambos bits son 1, entonces el bit resultante es 0. Si ambos bits son 0, entonces el bit resultante es 0. En otras palabras, para que el bit resultante sea 1, solo uno de los bits debe ser 1, y el otro bit debe ser 0.

    Denotado como XOR o ^

    Ejemplo: 10100101 ^ 01100011 = 11000110

Los desplazamientos bit a bit ( >> y << ) desplazan los bits del operando en la dirección especificada, en el número de lugares especificado. Los puestos vacantes se llenan con ceros. Por ejemplo:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
La excepción es cuando desplazas un número negativo hacia la derecha. Como recordará, el primer bit de un número con signo indica el signo. Si este bit es 1, entonces el número es negativo. Si desplaza un número negativo, las posiciones libres no se rellenan con ceros sino con unos, ya que se debe conservar el bit de signo. Por ejemplo: 10100010 >> 2 = 11101000 Dicho esto, Java tiene un operador de desplazamiento a la derecha sin firmar adicional (>>>). Este operador es análogo a >>, pero cuando se desplaza, las posiciones desocupadas se llenan con 0, independientemente de si el operando es un número negativo o positivo. Por ejemplo: 10100010 >>> 2 = 00101000 Lea más sobre operaciones bit a bit aquí . Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 2 - 2Puede tomar el método hash() en HashMaps como ejemplo de cambios bit a bit en Java. Este método se utiliza para determinar el código hash interno especial de la clave: Explorando preguntas y respuestas de una entrevista de trabajo para un puesto de desarrollador de Java.  Parte 2 - 3este método le permite distribuir uniformemente los datos en un HashMap para minimizar la cantidad de colisiones.

14. ¿Qué objetos inmutables estándar existen en Java?

Un objeto es inmutable si no permite que cambien sus valores originales. Puede tener métodos que devuelvan nuevos objetos del mismo tipo con valores diferentes. Algunos objetos inmutables estándar incluyen:
  • Sin duda, el tipo inmutable más famoso de Java es String;
  • instancias de las clases contenedoras que envuelven tipos estándar: booleano, carácter, byte, corto, entero, largo, doble, flotante;
  • Objetos BigInteger y BigDecimal, que normalmente se utilizan para números especialmente GRANDES;
  • Objetos StackTraceElement que forman un seguimiento de pila (por ejemplo, el seguimiento de pila de una excepción);
  • un objeto de la clase Archivo: puede modificar archivos, pero al mismo tiempo el objeto en sí permanece sin cambios;
  • UUID, que a menudo se utilizan para identificar elementos de forma única;
  • todos los objetos de clases en el paquete java.time;
  • Objetos locales, que se utilizan para identificar una región geográfica, política o cultural.

15. ¿Cuáles son las ventajas de los objetos inmutables sobre los objetos ordinarios?

  1. Los objetos inmutables son seguros de usar en un entorno multiproceso . Lo hacen para que no tengas que preocuparte por la pérdida de datos debido a las condiciones de la carrera. Esto es diferente a cuando trabajas con objetos comunes. En ese caso, hay que pensar e idear buenos mecanismos al utilizar el objeto en un entorno paralelo.

  2. Los objetos inmutables sirven como claves en un mapa. Si usa un objeto mutable como clave HashMap y luego el estado del objeto cambia, entonces la estructura de datos podría confundirse: el objeto seguirá presente, pero si usa contieneKey(), es posible que no lo encuentre.

  3. Los objetos inmutables son excelentes para almacenar datos inmutables (constantes) que nunca deben cambiarse mientras se ejecuta el programa.

  4. Otra ventaja es la atomicidad del fallo. Si un objeto inmutable genera una excepción, no quedará en un estado no deseado (roto).

  5. Estas clases son fáciles de probar.

  6. No necesita ningún mecanismo adicional, como un constructor de copias o una implementación de clonación de objetos.

Preguntas sobre POO

16. ¿Cuáles son las ventajas de la programación orientada a objetos en general y en comparación con la programación procesal?

Bien, ventajas de la programación orientada a objetos:
  1. Las aplicaciones complejas son más fáciles de escribir usando programación orientada a objetos que con programación procedimental, ya que todo se divide en pequeños módulos (objetos que interactúan entre sí) y, como resultado, la programación se reduce a relaciones entre objetos.

  2. Las aplicaciones escritas con programación orientada a objetos son mucho más fáciles de modificar (cuando se observan adecuadamente los principios de diseño).

  3. Dado que tanto los datos como las operaciones de datos forman una sola entidad, no se manchan por toda la aplicación (como suele ser el caso en la programación de procedimientos).

  4. El principio de encapsulación protege los datos más críticos del usuario.

  5. El mismo código se puede reutilizar con datos diferentes porque las clases te permiten crear muchos objetos, cada uno con sus propios valores.

  6. La herencia y el polimorfismo también le permiten reutilizar y ampliar el código existente (en lugar de duplicar funciones similares).

  7. Ampliar una solicitud es más sencillo que hacerlo mediante un enfoque procesal.

  8. El enfoque OOP permite abstraer los detalles de implementación.

17. Cuéntanos qué desventajas tiene la programación orientada a objetos

Lamentablemente también existen:
  1. La programación orientada a objetos requiere muchos conocimientos teóricos que deben dominarse antes de poder escribir algo.

  2. Las ideas de programación orientada a objetos no son tan fáciles de entender y aplicar en la práctica (en el fondo hay que ser un pequeño filósofo).

  3. La programación orientada a objetos reduce ligeramente el rendimiento de un programa debido a la mayor complejidad del sistema.

  4. El enfoque OOP requiere más memoria ya que todo consta de clases, interfaces y métodos, que ocupan mucha más memoria que las variables ordinarias.

  5. El tiempo requerido para el análisis inicial es mayor que para un enfoque procesal.

18. ¿Qué es el polimorfismo estático versus el polimorfismo dinámico?

El polimorfismo permite que objetos de la misma clase o interfaz se comporten de manera diferente. Hay dos tipos de polimorfismo, que también se conocen como unión temprana y tardía. Polimorfismo estático o unión temprana:
  • ocurre en el momento de la compilación (al principio del ciclo de vida del programa);
  • decide qué método ejecutar en tiempo de compilación;
  • la sobrecarga de métodos es un ejemplo de polimorfismo estático;
  • la vinculación anticipada incluye métodos privados, estáticos y finales;
  • la herencia no está involucrada en la vinculación anticipada;
  • El polimorfismo estático no involucra objetos específicos, sino información sobre el tipo de clase que aparece a la izquierda del nombre de una variable.
Polimorfismo dinámico o unión tardía:
  • ocurre en tiempo de ejecución (mientras el programa se está ejecutando);
  • el polimorfismo dinámico decide qué implementación específica tendrá un método en tiempo de ejecución;
  • la anulación de métodos es un ejemplo de polimorfismo dinámico;
  • vinculación tardía significa asignar un objeto específico, una referencia de su tipo o su superclase;
  • la herencia está asociada con el polimorfismo dinámico.

19. Proporcionar una definición del principio de abstracción en programación orientada a objetos.

En POO, la abstracción es una forma de aislar un conjunto de características significativas de un objeto, excluyendo detalles insignificantes. Es decir, al diseñar un programa con enfoque POO, te centras en modelos generales, sin entrar en detalles de su implementación. En Java, la abstracción se realiza a través de interfaces . Por ejemplo, tienes un coche y esa será una interfaz. Y las diversas interacciones con él (por ejemplo, arrancar el motor, cambiar de marcha) son funciones que utilizamos sin profundizar en los detalles de implementación. De hecho, cuando conduces, no piensas exactamente en cómo la caja de cambios cumple su función, ni en cómo arranca el motor con la llave, ni en cómo exactamente el volante hace girar las ruedas. Y si reemplaza la implementación de alguna funcionalidad (por ejemplo, el motor), es posible que ni siquiera lo note. No te importa: no profundizas en los detalles de implementación. Lo que te importa es que la acción se lleve a cabo. En esencia, se trata de abstraer los detalles de implementación. En este punto nos detendremos hoy: ¡continuará!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION