Nueva excepción de puntero nulo en Java 17
Fuente: Dev.to Todo desarrollador de Java debe conocer la existencia de una nueva excepción de puntero nulo o NPE en Java 17. Esta es una de esas situaciones que siempre debes intentar prevenir. A veces, Nullpointer significa que necesitas depurar tu código para encontrar un pequeño error. Una NPE es una excepción de tiempo de ejecución que ocurre cuando su código quiere usar un objeto o una referencia a un objeto que tiene un valor nulo. Puede ocurrir si no se asigna ningún valor o el objeto no tiene una referencia. Antes de la última versión de OpenJDK (versión 17), una excepción de puntero nulo normal en el seguimiento de la pila se vería así:java.lang.NullPointerException: null
Por supuesto, eso no es todo lo que necesita saber sobre los seguimientos de pila. Como puede ver, no indica dónde ni por qué ocurrió esta excepción. Vea cómo Java 17 soluciona este problema:
Exception in thread "main" java.lang.NullPointerException:
Cannot assign field "i" because "a" is null
at Prog.main(Prog.java:5)
En este ejemplo, la excepción indica dónde y cuál es nuestra referencia de objeto nulo. ¡Es así de simple!
¿Qué significa <T> en Java?
Fuente: Dev.to <T> es una letra común que significa "Tipo" y se refiere al concepto Genérico en Java. Puedes usar otra letra para esto, pero como puedes ver, es preferible la letra T.¿Qué es genérico?
Genérico es una forma de parametrizar una clase, método o interfaz. Veamos un ejemplo de genérico:package Generics;
class House<T>{
T doorNumber;
public House(T doorNumber) {
this.doorNumber = doorNumber;
}
public void print(){
System.out.println("Your house number is: " + this.doorNumber);
}
}
- Tenemos una clase llamada House que puede aceptar un tipo de objeto arbitrario.
- A continuación tenemos un campo llamado doorNumber , que también puede aceptar cualquier tipo de objeto.
- Al final declaramos un constructor parametrizado e imprimimos el número de puerta.
public class GenericsExample {
public static void main(String[] args) {
House<String> mainHouse = new House<>("14a");
mainHouse.print();
}
}
El resultado se verá así:
El número de tu casa es: 14a.
Reemplazaremos la letra "T" con "Cadena" e ingresaremos el número de la casa en el constructor. Podemos usar múltiples tipos si, por ejemplo, necesitamos que una clase acepte más de un objeto. Podemos agregar otra letra y con ello decir: queremos que la clase acepte otro Genérico.
package Generics;
class House<T, V>{
T doorNumber;
V streetName;
public House(T doorNumber, V streetName) {
this.doorNumber = doorNumber;
this.streetName = streetName;
}
public void print(){
System.out.println("You live at: " + this.doorNumber + " " + this.streetName);
}
}
public class GenericsExample {
public static void main(String[] args) {
House<Integer, String> mainHouse = new House<>(14, "Tellson Avenue");
mainHouse.print();
}
}
El resultado será así:
Vives en: Avenida Tellson 14
Hasta ahora hemos visto ejemplos del uso de Generic a nivel de clase. Pero también podemos tener métodos e interfaces comunes.
Método genérico
package Generics;
class House{
public <T> void print(T doorNumber){
System.out.println("You live at house number: " + doorNumber);
}
}
public class GenericsExample {
public static void main(String[] args) {
House mainHouse = new House();
mainHouse.<Integer>print(14);
}
}
El método acepta cualquier tipo de objeto y genera el número de puerta, que será cualquier tipo de Objeto . En este caso, queremos que el método acepte un número entero. El resultado será:
Vives en la casa número: 14
Interfaz genérica
Primero crea la interfaz.package Generics;
interface Property<T>{
void hasBalcony(T balcony);
}
Luego implemente la interfaz.
package Generics;
public class House implements Property<String> {
@Override
public void hasBalcony(String balcony) {
System.out.println("Is there a balcony in the room? " + balcony);
}
public static void main(String[] args) {
House mainHouse = new House();
mainHouse.hasBalcony("YES");
}
}
Resultado:
¿Hay un balcón en la habitación? SÍ
¿Cuáles son las ventajas de utilizar genéricos?
- Mejor verificación en tiempo de compilación : si usa un tipo de objeto distinto al que especificó, el compilador se lo indicará.
- Reutilizabilidad : puede usar una clase, método o interfaz varias veces porque decide qué tipo de objeto usar dependiendo de lo que intenta lograr.
- Es excelente para estructuras de datos y algoritmos : ArrayList y HashMap son solo algunos ejemplos en los que se usa Generic.
GO TO FULL VERSION