JavaRush /Blog Java /Random-ES /Pausa para el café #98. Nueva excepción de puntero nulo e...

Pausa para el café #98. Nueva excepción de puntero nulo en Java 17. ¿Qué significa en Java?

Publicado en el grupo Random-ES

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. Pausa para el café #98.  Nueva excepción de puntero nulo en Java 17. ¿Qué significa <T>  en Java?  - 1Una 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. Pausa para el café #98.  Nueva excepción de puntero nulo en Java 17. ¿Qué significa <T>  en Java?  - 2

¿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.
En pocas palabras, el usuario puede decidir si este número es entero, cadena, flotante, etc. NOTA: sólo puedes utilizar Objetos . Los tipos primitivos no son compatibles porque los genéricos están pensados ​​para usarse en tiempo de compilación. Cuando usamos Genéricos, T reemplaza cualquier cosa que pueda extender la clase Objeto , y las primitivas no tienen esta propiedad. Digamos que queremos que doorNumber sea una cadena.
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?
  1. Mejor verificación en tiempo de compilación : si usa un tipo de objeto distinto al que especificó, el compilador se lo indicará.
  2. Reutilizabilidad : puede usar una clase, método o interfaz varias veces porque decide qué tipo de objeto usar dependiendo de lo que intenta lograr.
  3. Es excelente para estructuras de datos y algoritmos : ArrayList y HashMap son solo algunos ejemplos en los que se usa Generic.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION