Principales errores de desarrolladores Java principiantes: de la A a la Z
Java es un lenguaje potente, pero estricto. Los novatos suelen tropezar una y otra vez con los mismos errores que los desarrolladores experimentados evitan automáticamente. En este artículo analizaremos los 10 errores más comunes que cometen los programadores Java principiantes. No solo aprenderá por qué ocurren, sino también cómo solucionarlos utilizando patrones correctos y best practices.
1. NullPointerException (NPE) olvidado
El error más popular en Java. Ocurre cuando intenta llamar a un método o acceder a un campo de un objeto que es igual a null.
Problema
public class User {
private String name;
public int getNameLength() {
return name.length(); // NPE, si name == null
}
}
Solución
Siempre verifique los objetos para null antes de usarlos. Utilice Optional o las anotaciones @Nullable / @NonNull.
public int getNameLength() {
return Optional.ofNullable(name)
.map(String::length)
.orElse(0);
}
2. Ignorar el contrato de equals() y hashCode()
Si sobrescribe equals(), está obligado a sobrescribir también hashCode(). De lo contrario, sus objetos no funcionarán correctamente en colecciones como HashSet, HashMap y otras.
Problema
public class Person {
private String id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(id, person.id);
}
// ¡hashCode() no está sobrescrito!
}
// En HashMap dos objetos "iguales" terminarán en diferentes cubos
Map<Person, String> map = new HashMap<>();
map.put(new Person("1"), "Alice");
System.out.println(map.get(new Person("1"))); // null
Solución
Utilice siempre Objects.hash() para generar el código hash:
@Override
public int hashCode() {
return Objects.hash(id);
}
3. Uso incorrecto de Generics (tipos crudos)
El uso de tipos crudos (raw types) le priva de la verificación de tipos en tiempo de compilación. Esto provoca ClassCastException en tiempo de ejecución.
Problema
List list = new ArrayList(); // tipo crudo
list.add("cadena");
list.add(123); // el compilador no se queja
String s = (String) list.get(1); // ¡ClassCastException!
Solución
List<String> list = new ArrayList<>();
list.add("cadena");
// list.add(123); // error de compilación — ¡perfecto!
String s = list.get(0); // seguro
4. Mutación de objetos en colecciones
Modificar los campos de un objeto que ya se encuentra en un HashSet o que es clave en un HashMap rompe la estructura de datos. El código hash del objeto cambia, pero el cubo sigue siendo el mismo.
Problema
Set<StringBuilder> set = new HashSet<>();
StringBuilder sb = new StringBuilder("A");
set.add(sb);
sb.append("B"); // mutación
System.out.println(set.contains(sb)); // ¡puede ser false!
Solución
Utilice objetos inmutables (String, Integer, record) como claves. Si necesita modificar un objeto, elimínelo de la colección, modifíquelo y luego agréguelo de nuevo.
5. Manejo incorrecto de excepciones
Dos extremos: tragarse las excepciones (un catch vacío) o lanzar excepciones demasiado genéricas (throws Exception).
Problema
try {
// código peligroso
} catch (Exception e) {
// no hacemos nada — el error se pierde
}
```