Resumen de programación avanzada de JavaSE y programación genérica de formación 2

Resumen de programación avanzada de JavaSE y programación genérica de formación 2

Cuarto, el principio de realización de los genéricos.

4.1, principio de descripción general

Dado que los genéricos solo se producían en JDK1.5, antes de eso, los genéricos de Java usaban objetos Object para aceptar todo tipo de objetos. Pero la JVM debe mantener la compatibilidad con versiones anteriores, es decir, la versión inferior del JDK debe poder ejecutarse en la versión superior del JDK. Debido a esta compatibilidad, nuestros genéricos deben convertirse en el mismo archivo de clase que el código de bytes antes de JDK1.5 después de la compilación.
Por lo tanto, el principio de los genéricos todavía está relacionado con Object ~~

4.2, mira el ejemplo

Ejemplo 1: clase genérica común y función genérica común


/**
 * @author jiangzl
 */
public class MyGeneric7 {
    
    

    public static <T> void getTemplateValue(MyNumber<T> myNumber){
    
    
        System.out.println(myNumber.getValue());
    }

    public static void main(String[] args) {
    
    
        MyNumber<Double> doubleMyNumber = new MyNumber<>(3.14);
        getTemplateValue(doubleMyNumber);
        MyNumber<Integer> integerMyNumber = new MyNumber<>(520);
        getTemplateValue(integerMyNumber);
    }
}

class MyNumber<T>{
    
    
    private T value;

    public MyNumber(T value){
    
    
        this.value = value;
    }

    public T getValue(){
    
    
        return value;
    }
}
Eche un vistazo a la salida del ejemplo:

Inserte la descripción de la imagen aquí

Mira los resultados del desmontaje:
Primero: el resultado de MyNumber.class

Inserte la descripción de la imagen aquí

El punto clave, consulte: Valor del campo

Es java / lang / Object ;! ! ! Esto muestra que después del desmontaje, este valor se convierte en un objeto de objeto. Entonces el método de construcción también es Objeto. El invocadoespecial es simplemente decir que significa una función específica, no una función virtual ~~

Segundo: el resultado de MyGeneric7.class

Inserte la descripción de la imagen aquí

Al ver los parámetros del método genérico, después del desmontaje, la parte getValue () y Field, es decir, la parte de parámetro, se han convertido en objetos Object ~~

Entonces, ¿cómo se crea una instancia del tipo genérico cuando se llama específicamente? ? ? Mire lo siguiente: ~
Inserte la descripción de la imagen aquí
Aquí hay una instanciación genérica, que es parte del método principal, aquí podemos ver:

Después de comentar los números 8 y 9, al llamar al método estático, Double.valueOf () y Integer.valueOf () se realizan en el objeto Object. ~ Entonces se completa la instanciación y se llama al método genérico.

Ejemplo 2: genérico con restricciones

import java.security.Security;
import java.util.Comparator;
import java.util.Scanner;

/**
 * 泛型类型的限定
 * @author jiangzl
 */
public class MyGeneric3 {
    
    

    public static <T extends Comparable> T getMax(T... e){
    
    
        if(null == e || e.length <= 0){
    
    
            return null;
        }
        T ret = e[0];
        for(T var : e){
    
    
            if(ret.compareTo(var) < 0){
    
    
                ret = var;
            }
        }
        return ret;
    }

    public static void main(String[] args) {
    
    
        int n = 5;
        Student[] s = new Student[n];
        Scanner sc = new Scanner(System.in);
        for(int i = 0;i < n;++i){
    
    
            String name = sc.next();
            int score = sc.nextInt();
            s[i] = new Student(name, score);
        }
        sc.close();
        System.out.println(getMax(s));

        String Str[] = {
    
    "b", "a", "c", "d", "e"};
        System.out.println(getMax(Str));
    }
}

class Student implements Comparable<Student> {
    
    
    private String name;
    private int score;

    public Student(String name, int score){
    
    
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString(){
    
    
        return new String("name = " + name + ", score = " + score);
    }

    @Override
    public int compareTo(Student s) {
    
    
        if(score != s.score){
    
    
            return score - s.score;
        }
        else{
    
    
            return s.name.compareTo(name);
        }
    }
}

Aquí requerimos que la clase que puede instanciar métodos genéricos debe ser una clase que implemente la interfaz Comparable. ! !

Echemos un vistazo al resultado del desmontaje: (Demasiado contenido, solo extractos)

Inserte la descripción de la imagen aquí
Aquí encontramos que después de public static <T extends Comparable> T getMax(T... e)desensamblar el método genérico ( ), el parámetro se convierte en el tipo Comparable. Aquí tenemos el siguiente resumen:

Primero: si hay una clase en la clase y la interfaz de extiende, la clase debe escribirse al frente y el tipo de esta clase es el tipo después del desmontaje.
Segundo: si no hay clases para extensiones, pero interfaces, no importa. ¡La primera clase (la más cercana a extensiones) se usará como tipo genérico!

Cinco, covarianza y contravarianza

5.1 ¿Qué es la covarianza y la contravarianza, y cuál es la relación?

Si decimos que A <= B significa que A es una subclase de B, supongamos que f (x) denota que una determinada clase x está encapsulada en una determinada estructura de datos. Como matrices, colecciones, etc. Luego, después de la encapsulación, si f (A) yf (B) tienen una relación de herencia, se dice que tiene una relación ~

La relación es la siguiente:

el primero:

Si A <= B yf (A) <= f (B), se llama covarianza, lo que significa que A es un subtipo de B, y después de la encapsulación, A sigue siendo un subtipo de B. Por lo general, hay matrices. Por ejemplo, A es un subtipo de B, luego la matriz A [] sigue siendo un subtipo de B [] ~

segundo:

Si A <= B yf (A)> = f (B), se llama contravarianza, lo que significa que A es un subtipo de B, y después de la encapsulación, B es un subtipo de A. Normalmente, está limitado por comodines y limitado por el límite inferior ~

tercero:

Si A <= B, se dice que f (A) <> f (B) no cambia, lo que significa que A es una subclase de B. Después de la encapsulación, A y B no tienen relación de herencia. Por lo general, hay genéricos, genéricos sin restricciones, y las colecciones posteriores a los genéricos, como List <A> y List <B>, no tienen nada que ver con ~

Esto puede no estar claro, use una imagen para mostrarlo:
Inserte la descripción de la imagen aquí

5.2 Covarianza de los valores de retorno de la función y el principio de sustitución de Richter

De acuerdo con el principio de sustitución de Richter, los parámetros reales pasados ​​a la función deberían poder ser recibidos por los parámetros formales. Entonces, escriba (parámetro actual) <= tipo (parámetro formal), lo que significa que el parámetro real es el tipo o subtipo del parámetro formal en sí. El valor de retorno establecido debería poder ser recibido por el valor de retorno de la llamada, es decir, tipo (llamada)> = tipo (retorno).

Mira un ejemplo:



/**
 * @author jiangzl
 */
public class MyGeneric7 {
    
    
    public static void main(String[] args) {
    
    
        ClassFather classFather = new ClassSon();
        System.out.println(classFather.method(3.14));
    }
}

class ClassFather{
    
    
    public Number method(Number value){
    
    
    	System.out.println(value.getClass());
        System.out.println("father");
        return value;
    }
}

class ClassSon extends ClassFather{
    
    
    @Override
    public Double method(Number value){
    
    
        System.out.println("son");
        return Double.valueOf(value.toString());
    }
}

A partir de JDK1.5, cuando se permite que las subclases reescriban los métodos principales, la covariante (subclase del tipo de valor de retorno del método principal anulado) se utiliza como valor de retorno. Pero echemos un vistazo a la salida de este código:

Inserte la descripción de la imagen aquí

llegó a una conclusión:

Después de JDK1.5, la subclase anula el método de superclase para permitir la covarianza, es decir, el valor de retorno puede ser de un tipo más específico que el método de superclase. !

5.3, covarianza de matriz

Primero mira el código de muestra:

Módulo 1: Diseño de clases
class FirstClass{
    
    
    public FirstClass(){
    
    
        System.out.println("FirstClass is constructed!!");
    }

    public void sayHello(){
    
    
        System.out.println("Helo World!");
    }
}

class SecondClass extends FirstClass{
    
    
    public SecondClass(){
    
    
        System.out.println("SecondClass is constructed!!");
    }
}

class LastClass extends SecondClass{
    
    
    public LastClass(){
    
    
        System.out.println("LastClass is constructed!!");
    }
}
Módulo 2: Covarianza de matrices
		FirstClass[] firstClasses = new SecondClass[2];
        firstClasses[0] = new SecondClass();
        try {
    
    
            firstClasses[1] = new FirstClass();
            firstClasses[1].sayHello();
        }
        catch (Exception e){
    
    
            System.out.println("Runtime error!");
        }

        System.out.println();
        SecondClass[] secondClasses = new SecondClass[2];
        firstClasses = secondClasses;
        firstClasses[0] = new LastClass();
        try {
    
    
            firstClasses[1] = new FirstClass();
            firstClasses[1].sayHello();
        }
        catch (Exception e){
    
    
            System.out.println("Runtime error!");
        }

Aquí solo intercepté el código sobre la parte covariante de la matriz, que está en el método principal. El resultado de la ejecución es:
Inserte la descripción de la imagen aquí
desde aquí podemos ver que la matriz es covariante, pero también plantea un nuevo problema:

¿Por qué la subclase crea una instancia del objeto de la clase principal hasta que se ejecuta el constructor de la clase principal?

La compilación pasará aquí y la excepción no se lanzará hasta que finalice el constructor de la clase principal. ! ! ¿Por qué la JVM es tan retrospectiva? Cualquiera que sepa, por favor déjeme un mensaje o envíeme un mensaje privado, ¡gracias! ~

5.4, ​​covarianza genérica

Mira el ejemplo:

import java.util.ArrayList;

/**
 * @author jiangzl
 */
public class MyGeneric6 {
    
    
    public static void main(String[] args) {
    
    
        int nA = 3, nB = 4, nC = 5;
        ArrayList<A> asA = new ArrayList<>();
        for(int i = 0;i < nA;++i){
    
    
            asA.add(new A());
        }
        ArrayList<B> asB = new ArrayList<>();
        for(int i = 0;i < nB;++i){
    
    
            asB.add(new B());
        }
        ArrayList<C> asC = new ArrayList<>();
        for(int i = 0;i < nC;++i){
    
    
            asC.add(new C());
        }

        sayName(asA, asB, asC);
    }

    public static void sayName(ArrayList<? extends A>... arrayList){
    
    
        int len = arrayList.length;
        for(int i = 0;i < len;++i){
    
    
            int size = arrayList[i].size();
            for(int j = 0;j < size;++j){
    
    
                arrayList[i].get(j).sayName();
            }
        }
    }
}

class A{
    
    
    public void sayName(){
    
    
        System.out.println("my name is A");
    }
}

class B extends A{
    
    
    @Override
    public void sayName(){
    
    
        System.out.println("my name is B");
    }
}

class C extends A{
    
    
    @Override
    public void sayName(){
    
    
        System.out.println("my name is C");
    }
}

Mira la salida:

Inserte la descripción de la imagen aquí

5. Escriba al dorso:

La covarianza y contravarianza genéricas, de hecho, ya se han mencionado en la sección anterior, las cosas a tener en cuenta son:

Covarianza, es decir, el límite superior de? Extends Class define genéricos, que solo pueden obtener, no establecer!

Contravarianza, es decir, el límite inferior de superclase limita los genéricos, por lo que solo puede establecer, pero no obtener.

Si no comprende los conceptos básicos de los genéricos, puede consultar mi último artículo:

Resumen de JavaSE Advanced Programming-Generic Foundation 1

Además, este artículo plantea dos dudas: debido a mi capacidad limitada, si hay una mala escritura o una comprensión inadecuada, me gustaría pedirles a todos que lo señalen. ¡Gracias por las críticas! También hay dos dudas, si hay alguna explicación, ¡no dude en aclararme! ¡Gracias de nuevo!

Supongo que te gusta

Origin blog.csdn.net/qq_44274276/article/details/108098107
Recomendado
Clasificación