Estilos

Varios fragmentos de código Java con estilos distintos: la llave de apertura en la misma línea o en la siguiente, sangría con espacios o con tabuladores, y espacios o no alrededor de los operadores en un for.
¿Que estilo prefieres?

La eterna discusión sobre el estilo del código. Todos funcionan igual, así que lo importante no es cuál eliges, sino que todo el equipo use el mismo; hoy los formateadores automáticos como google-java-format, gofmt o Black zanjan la discusión.

No es el error más común

Si eres programador con algo de experiencia, lo sabes…
Una cara con expresión de fastidio y el texto: «Sería genial que el error típico de programación sea tan solo la falta de un simple punto y coma».

El punto y coma que falta es el error que todo el mundo cita, pero es de los más fáciles: el compilador lo señala al momento. Los errores que de verdad cuestan son los de lógica, que compilan sin protestar y hacen otra cosa de la que creías.

Pregunta Java: HashSet sin equals ni hashCode

Piensa la respuesta antes de abrirla. Todas las opciones parecen razonables, y casi siempre hay un detalle que lo cambia todo.

Pregunta Java · Collections

¿Cuál es el resultado de compilar y ejecutar la clase Test?

import java.util.HashSet;
public class Test {
    public static void main(String args[]) {
        HashSet hashset = new HashSet();
        String s1 = new String("uno");
        String s2 = new String("uno");
        CadenaBean s3 = new CadenaBean("dos");
        CadenaBean s4 = new CadenaBean("dos");
        CadenaBean s5 = new CadenaBean("tres");
        hashset.add(s1);
        hashset.add(s2);
        hashset.add(s3);
        hashset.add(s4);
        System.out.println(hashset);
    }
}
class CadenaBean {
    private String str;
    CadenaBean(String str) {
        this.str = str;
    }
    public String toString() {
        return str;
    }
}
  1. [uno,dos,tres]
  2. [uno,uno,dos,dos]
  3. [dos,dos,uno]
  4. No hay garantía del orden.
  5. Error de ejecución
Ver la respuesta

Respuesta: d.

java Test[dos, uno, dos]

Hay tres cosas que mirar:

  • s1 y s2 son objetos distintos, pero String define equals y hashCode por contenido, así que el conjunto los ve iguales y solo guarda uno.
  • CadenaBean no redefine ninguno de los dos y usa los de Object, que comparan identidad. Los dos "dos" cuentan como distintos y entran ambos.
  • s5 se crea pero nunca se añade.

Quedan tres elementos, uno, dos y dos, en un orden que HashSet no garantiza. En nuestra ejecución salió [dos, uno, dos], que se parece a la opción c pero no es lo que el código asegura. La respuesta correcta es la d. (La quinta opción también estaba marcada como «d» en la imagen original.)

Al compilar sale además un aviso, Test.java uses unchecked or unsafe operations, por usar HashSet sin tipo. Hoy se escribiría Set<Object> hashset = new HashSet<>();.

Pregunta publicada en 2014 y revisada en octubre de 2026. La respuesta se comprobó compilando y ejecutando el código con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.

Pregunta Java: un assert que nunca falla

Piensa la respuesta antes de abrirla. Todas las opciones parecen razonables, y casi siempre hay un detalle que lo cambia todo.

Pregunta Java · Assertions

Suponiendo que ejecutas la clase Prueba con java -enableassertions Prueba, ¿cuál es el resultado?

public class Prueba {

    public static void main(String... args) {
        for (int i = 2; i < 4; i++) {
            for (int j = 2; j < 4; j++) {
                if (i < j) {
                    assert i != j : i;
                }
            }
        }

    }
}
  1. Exception in thread "main" java.lang.AssertionError: 1
  2. Exception in thread "main" java.lang.AssertionError: 2
  3. Se ejecuta y no imprime nada
  4. Error de ejecución
Ver la respuesta

Respuesta: c.

java -enableassertions Prueba(no imprime nada)
[código 0]

El assert solo se evalúa cuando i < j, y en ese caso i != j siempre es cierto, así que la condición nunca falla. El valor que va detrás de los dos puntos (: i) solo se usaría como mensaje del AssertionError, y aquí no llega a usarse.

Por omisión, la máquina virtual ignora los assert: hay que activarlos con -enableassertions (o -ea). Por eso no sirven para validar datos de entrada en un programa en producción, sino para comprobar suposiciones durante el desarrollo.

Pregunta publicada en 2014 y revisada en octubre de 2026. La respuesta se comprobó compilando y ejecutando el código con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.

Pregunta Java: llamar a run() en vez de start()

Piensa la respuesta antes de abrirla. Todas las opciones parecen razonables, y casi siempre hay un detalle que lo cambia todo.

Pregunta Java · Threads

¿Cuál es el resultado de compilar y ejecutar la clase Test02?

public class Test02 {
    public static void main(String argv[]) {
        Test1 pm1 = new Test1("Uno");
        pm1.run();
        Test1 pm2 = new Test1("Dos");
        pm2.run();
    }
}

class Test1 extends Thread {
    private String nombre = "";
    Test1(String s) {
        nombre = s;
    }
    public void run() {
        for (int i = 0; i < 2; i++) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
            }
            yield();
            System.out.println(nombre);
        }
    }
}
  1. Uno Dos
  2. Uno Dos Uno Dos
  3. Uno Uno Dos Dos
  4. Error de ejecución
Ver la respuesta

Respuesta: c.

java Test02  —  con Thread.yield()Uno
Uno
Dos
Dos

El código llama a run() directamente, no a start(). Así no se crea ningún hilo: run() es un método normal que se ejecuta en el hilo principal, de principio a fin, antes de pasar a la línea siguiente. Primero Uno dos veces, luego Dos dos veces, y tarda unos cuatro segundos por los cuatro sleep(1000). Con start(), los dos hilos irían a la vez y lo normal sería ver los nombres intercalados.

En Java actual este código ya no compila tal cual. Desde Java 14, yield es una palabra con significado propio en las expresiones switch, y una llamada sin calificar se rechaza:
javac Test02.java  —  Java 25Test02.java:21: error: invalid use of a restricted identifier 'yield'
            yield();
            ^
  (to invoke a method called yield, qualify the yield with a receiver or type name)
1 error

Basta con escribir Thread.yield();. Con ese cambio se obtuvo la salida de arriba. En 2014, con Java 7 u 8, el código original compilaba.

Pregunta publicada en 2014 y revisada en octubre de 2026. La respuesta se comprobó compilando y ejecutando el código con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.

Pregunta Java: clases internas anidadas

Piensa la respuesta antes de abrirla. Todas las opciones parecen razonables, y casi siempre hay un detalle que lo cambia todo.

Pregunta Java · Clases internas

¿Cuál es el resultado de compilar y ejecutar la clase Prueba1?

public class Prueba1 {
    public class Prueba2 {
        public class Prueba3 {
            public Prueba3(){
                System.out.println("Hola");
            }
            public class Prueba4 {
                public void Prueba4(){
                    System.out.println("Mundo");
                }
            }
        }
    }

    public static void main(String args []){
        Prueba2.Prueba3.Prueba4 p = new Prueba1().new Prueba2().new Prueba3().new Prueba4();
    }
}
  1. No compila por la declaración de las clases Prueba2, Prueba3 y Prueba4 dentro de Prueba1.
  2. No compila porque la declaración de la variable p es incorrecta.
  3. Compila y no imprime nada.
  4. Imprime "Hola Mundo"
  5. Imprime "Hola"
Ver la respuesta

Respuesta: e.

java Prueba1Hola

Las clases internas se pueden anidar sin límite, y para crear una hace falta una instancia de la que la contiene. Eso es justo lo que hace la cadena new Prueba1().new Prueba2().new Prueba3().new Prueba4(), y el tipo Prueba2.Prueba3.Prueba4 es correcto.

La trampa está en public void Prueba4(): por llevar void, no es un constructor, sino un método que se llama igual que la clase. Al hacer new Prueba4() se usa el constructor por defecto, que no imprime nada. El único constructor que escribe algo es el de Prueba3, y por eso solo sale Hola.

Pregunta publicada en 2014 y revisada en octubre de 2026. La respuesta se comprobó compilando y ejecutando el código con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.

Pregunta Java: serializar una clase cuyo padre no es Serializable

Piensa la respuesta antes de abrirla. Todas las opciones parecen razonables, y casi siempre hay un detalle que lo cambia todo.

Pregunta Java · Serialización

¿Cuál es el resultado de ejecutar la clase Prueba?

public class Padre {
    public Padre() {
        System.out.println("Padre");
    }
}
import java.io.Serializable;
public class Hijo extends Padre implements Serializable {
    public Hijo() {
        System.out.println("Hijo");
    }
}
import java.io.*;
public class Prueba {

    public static void main(String... args) throws Exception {
        Hijo a = new Hijo();
        ObjectOutputStream save = new ObjectOutputStream(new FileOutputStream("archivo.txt"));
        save.writeObject(a);
        save.flush();
        System.out.println("-");
        ObjectInputStream restore = new ObjectInputStream(new FileInputStream("archivo.txt"));
        Hijo b = (Hijo) restore.readObject();
    }
}
  1. Padre Hijo – Padre Hijo
  2. Padre Hijo – Padre
  3. Padre – Hijo
  4. Error en tiempo de ejecución
Ver la respuesta

Respuesta: b.

java PruebaPadre
Hijo
-
Padre

Al crear el objeto se ejecutan los dos constructores: Padre y Hijo. Al deserializarlo no se llama al constructor de la clase serializable, porque su estado se recupera del archivo. Pero Padre no es Serializable, así que su parte no se guardó, y Java la reconstruye llamando a su constructor sin parámetros. Por eso sale Padre una vez más, y Hijo no.

De ahí una regla poco conocida: si una clase serializable hereda de una que no lo es, esa clase padre tiene que tener un constructor sin parámetros accesible. Si no lo tiene, la deserialización falla con InvalidClassException.

Pregunta publicada en 2014 y revisada en octubre de 2026. La respuesta se comprobó compilando y ejecutando el código con Java 25 LTS en un contenedor limpio; las salidas están copiadas de esa ejecución.