[02] Principio genérico de Java y mecanismo de borrado

(1) Mientras una persona no se rinda a sí misma, el mundo entero no se dará por vencido contigo.
(2) Nací para ser de gran utilidad . (3) Si no
puedo soportar el sufrimiento del aprendizaje, debo soportar el sufrimiento de la vida. Qué doloroso es Comprensión profunda.
(4) Debes ganar al hacer cosas difíciles . (
5) El espíritu es la verdadera espada.
(6) Conquistar oponentes dos veces, la primera vez en el corazón.
(7) Escribir no es realmente fácil. Si te gusta o tienes algo para ti Ayuda a recordar que te gusta + seguir o marcar como favorito ~

Principio genérico de Java y mecanismo de borrado

1. ¿Cómo lidiar con los genéricos en Java?

1.1 Borrado genérico

1.1.1 ¿Por qué necesito utilizar el método puente para el borrado genérico?

(1) El método puente se utiliza para garantizar que después del borrado genérico, la subclase aún pueda garantizar que se implemente el método de interfaz, y el método puente llama al método de subclase después del borrado genérico.

(2) El código de muestra es el siguiente:

(3) La visualización del método puente se puede ver a través del complemento de visualización de código de bytes ASM ByteCode Viewer. El método de uso específico se mostrará en otros blogs.

Inserte la descripción de la imagen aquí

1.2 Residuos de borrado genéricos

(1) Ejemplo de código de bytes
Inserte la descripción de la imagen aquí

(2) La imagen de arriba es una captura de pantalla del código de bytes después del borrado genérico, por qué hay una T residual genérica en el archivo de código de bytes.
(A) La razón es que lo que ves aquí es solo la firma del método y el formato definido por la interfaz genérica, de esta manera es bueno para analizar el bytecode.
(B) Esta información se almacenará en el grupo constante de la clase.

1.3 Genéricos y reflexión

1.3.1 ¿No se borran los genéricos? ¿Por qué sigue relacionado con la reflexión?

Inserte la descripción de la imagen aquí

(1) La razón es el borrado. De hecho, la información genérica se retiene en la reserva constante de la clase.
(2) ¿Para qué sirve la información genérica?
(A) Obtenga el tipo específico a través de la reflexión y observe el código fuente en Retrofit.

1.4 ¿Cuál es el principio de los genéricos de Java? ¿Qué es el mecanismo de borrado genérico?

(1) Java genéricos es una característica recientemente introducida de JDK5. Para ser compatible con versiones anteriores, la máquina virtual no admite genéricos, por lo que Java implementa un mecanismo pseudo-genérico, lo que significa que Java se borra durante la compilación. Toda la información genérica, de modo que Java no necesita generar nuevos tipos de código de bytes, todos los tipos genéricos son en última instancia un tipo primitivo y no hay información genérica cuando Java se está ejecutando.

1.5 ¿Cómo controla el compilador de Java los genéricos?

(1) Marque el tipo genérico para obtener el tipo de destino.
(2) Borre la variable de tipo y reemplácela con un tipo limitado.

(a)如果泛型类型的类型变量没有限定(<T>),则用Object作为原始类型。
(b)如果有限定(<T extends XClass>),则用XClass作为原始类型
(c)如果有多个限定(T extends XClass1&XClass2),则使用第一个边界XClass1作为原始类

(3) Inserte conversiones de tipos cuando sea necesario para mantener la seguridad de tipos
(4) Genere métodos de puente para mantener el polimorfismo al expandirse.

2. El impacto del uso de genéricos y supresión de genéricos

2.1 Las variables de tipo genérico no pueden utilizar tipos de datos básicos

1)比如没有ArrayList<int>,只有ArrayList<Integer>.当类型擦除后,ArrayList的原始类中类的类型变量(T)替换成Object,但Object类型不能存放int值。

2.2 No se puede utilizar el operador instanceof

1)不能使用instanceof运算符判断一个泛型类型是否与另一个有具体类型的泛型类型相同
(2)因为泛型擦除之后,ArrayList<String>只剩下原始类型,泛型信息String不存在了,所以没法使用instanceof。
(3)示例代码如下:
    public static void test2(){
    
    
        ArrayList<String> strings = new ArrayList<>();
        //s1.ArrayList<?> 可以使用instanceof,因为ArrayList<?>就是代表的是一种未知的类型,所以可以使用。
        if(strings instanceof ArrayList<?>){
    
    

        }

        //s2.因为ArrayList<String>泛型擦除之后,String类型为丢失,所以不能使用instanceof运行符
        if(strings instanceof ArrayList<String>){
    
    

        }
    }   

2.3 El problema de los genéricos en métodos estáticos y clases estáticas

1)因为泛型类中的泛型参数的实例化是在定义泛型类型对象(比如ArrayList<Integer>)的时候指定的,而静态成员是不需要使用对象来调用的,所有对象都没创建,如何确定这个泛型参数是什么。所以静态方法与静态类中是不能够使用泛型的。
(2)示例代码如下:
public class Test2<T> {
    
    
    //s1.报错是因为泛型参数是要创建对象的时候才确定
    public static T one;

    public static T test(T t){
    
    }

    //s2.这里可以,是因为这是泛型方法,此T不是指的Test2<T>中的T
    public static <T> T test1(T t){
    
    
        return t;
    }
}3)为什么静态的泛型方法可以使用泛型呢?
是因为泛型方法是在调用的过程中来确定类型的,因此静态的泛型方法中是可以使用泛型的。

2.4 Conflictos de métodos en tipos genéricos

1)因为擦除后两个equals方法变成一样的了
(2)示例代码如下:
    //s1.因为泛型擦除之后,类型会变成Object,会和Object的equals()方法一样,相当于方法重复定义
    @Override
    public boolean equals(T t){
    
    

    }

    @Override
    public boolean equals(Object obj) {
    
    
        return super.equals(obj);
    }

2.5 No se puede crear una instancia genérica

1)因为类型不确定,所以就无法创建泛型实例
(2)示例代码:
public class Test2 {
    
    
    //s1.无法创建一个类型参数的实例。例如:下面代码就会引起编译时错误:
    public static <E> void append(List<E> list){
    
    
        E elem = new E();
        list.add(elem);
    }

    //s2.通过反射创建一个参数化类型的实例
    public static <E> void append(List<E> list,Class<E> cls) throws Exception {
    
    
        E elem = cls.newInstance();
        list.add(elem);
    }
}

2.6 No hay argumento para matrices genéricas

2.6.1 ¿Cuál es la covarianza de las matrices de Java?

(1) Apple extiende Fruit
(2) Se puede considerar que la clase madre de Apple [] es Fruit [], que se denomina covarianza de matrices Java.

2.6.2 Problemas causados ​​por la covarianza de matrices Java

1)为什么不能有泛型数组
(2)是因为当泛型信息被擦除之后,在运行期虚拟机就不知道它是什么类型了,就没办法满足Java数组的协变原则了,并且也不知道数组是什么类型的,所以就不允许有泛型数组。
(a)List<Apple>[]
(b)List<Fruit>[]

(2) Código de muestra 1:

    public static <T> void test1(){
    
    
        Apple[] apples = new Apple[10];
        Fruit[] fruits = new Fruit[10];
        System.out.println(apples.getClass());
        System.out.println(fruits.getClass());
        fruits = apples;
        //s1.编译通过,运行时会报ArrayStoreException异常
        fruits[0] = new Banana();
        //s2.下列语句可以为什么?
        //(1)因为Plate<?>表示的是不知道类型的任意类型,所以是可以的,相当于Object
        Plate<?>[] plates = new Plate<?>[10];
    }

(3) Código de muestra 2:

    public static <T> void test2(){
    
    
        //s1.Fruit是Apple的父类
        //s2.Fruit[]是Apple[]的父类,这就是Java数组的协变.
        //s3.如果加入泛型后,由于泛型的擦除机制,运行时将无法知道数组的类型。
        //s4.所以下列方式创建泛型数组是不允许的。
        Plate<Apple>[] applePlates = new Plate<Apple>[10];
    }
le[]的父类,这就是Java数组的协变.
        //s3.如果加入泛型后,由于泛型的擦除机制,运行时将无法知道数组的类型。
        //s4.所以下列方式创建泛型数组是不允许的。
        Plate<Apple>[] applePlates = new Plate<Apple>[10];
    }

Supongo que te gusta

Origin blog.csdn.net/xiogjie_67/article/details/108628411
Recomendado
Clasificación