Java-泛型-3

Posted 唐微港

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-泛型-3相关的知识,希望对你有一定的参考价值。

泛型类

public class Test<T extends Number> 
    private T key;

    public Test(T key) 
        this.key = key;
    

    public T getKey() 
        return key;
    

    public void setKey(T key) 
        this.key = key;
    

泛型接口

public interface Generator<T> 
    public T fun();

泛型方法

public class Test 
    public <T> T getT(T t) 
        return t;
    

    public <T extends List<Integer>> void getTs(T t) 
        System.out.println(t);
    

?无界限通配符

?表示不确定的类型

我们知道 Integer、Double、Float 等都是 Number 类的子类,所以下面的代码完全没问题的。基本类型 123 被自动装箱成 Integer 类型,而 Integer 又是 Number 类的子类,所以可以作为 printMsg 方法的实参。

public static void main(String[] args) 
    printMsg(123);

public static void printMsg(Number number) 
    System.out.println(number);

但泛型类 Generic<Number>Generic<Integer> 可以认为是两个完全没有关联的新类型,两者之间不具有任何继承关系,所以下面的代码会出现编译错误:

public static void main(String[] args) 
    Generic<Number> genericNumber = new Generic<>(123);
    Generic<Integer> genericInteger = new Generic<>(123);
    printMsg(genericNumber);  // 编译通过
    printMsg(genericInteger); // 编译出错,因为 Generic<Integer> 和 Generic<Number> 二者之间没有任何继承关系

public static void printMsg(Generic<Number> generic) //这里限定类型为Number
    System.out.println(generic.getKey());

而如果就是希望 printMsg 方法既能接收 Generic<Number> 又能够接收 Generic<Integer>类型,甚至是能够接收传入了任意实参类型的 Generic 泛型类(如 Generic<String>Generic<Random>等),则需要用到泛型通配符 ? 了:

public static void main(String[] args) 
    Generic<Number> genericNumber = new Generic<>(123);
    Generic<Integer> genericInteger = new Generic<>(123);
    printMsg(genericNumber);  
    printMsg(genericInteger); 

public static void printMsg(Generic<?> generic) 
    System.out.println(generic.getKey());

? 上限通配符

为泛型添加上边界,即传入的类型实参必须是指定类型或指定类型的子类。使用 extends 指定上限通配符。

因为 Generic<? extends Number> generic 指定了传入的类型实参必须是 Number 类或 Number 类的子类,(就是Number就为上限),所以printMsg(genericString); 出错,因为 String 不是 Number 的子类

public static void main(String[] args) 
    Generic<Number> genericNumber = new Generic<>(123);
    Generic<Integer> genericInteger = new Generic<>(123);
    Generic<Float> genericFloat = new Generic<>(0.5f);
    Generic<String> genericString = new Generic<>("Hello");
    printMsg(genericNumber);  
    printMsg(genericInteger); 
    printMsg(genericFloat);   
    printMsg(genericString);  // 编译出错

public static void printMsg(Generic<? extends Number> generic) 
    System.out.println(generic.getKey());

? 下限通配符

和上限通配符类似,下限通配符使用 super 关键字实现。(就是要为指定类的父类或该类才可以,这里下限为Integer)

因为 Generic<? super Integer> generic 指定了传入的类型实参必须是 Integer 类或 Integer 类的父类,所以 printMsg(genericFloat);printMsg(genericString); 出现编译错误,因为 Float 和 String 都不是 Integer 类的父类

public static void main(String[] args) 
    Generic<Number> genericNumber = new Generic<>(123);
    Generic<Integer> genericInteger = new Generic<>(123);
    Generic<Float> genericFloat = new Generic<>(0.5f);
    Generic<String> genericString = new Generic<>("Hello");
    printMsg(genericNumber);  
    printMsg(genericInteger); 
    printMsg(genericFloat);   // 编译出错
    printMsg(genericString);  // 编译出错

public static void printMsg(Generic<? super Integer> generic) 
    System.out.println(generic.getKey());

泛型擦除

  1. Java 的泛型只在编译阶段有效,编译过程中正确检验泛型结果后,会将泛型相关信息擦除,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法,即泛型信息不会进入运行时阶段:

    public static void main(String[] args)     Generic<Integer> genericInteger = new Generic<>(123);    Generic<String> genericString= new Generic<>("Hello");    System.out.println(genericInteger.getClass() == genericString.getClass());  // 返回true
    

    结果返回 true ,说明虽然编译时 Generic<Integer>Generic<String> 是不同的类型,但因为泛型的类型擦除,所以编译后 genericIntegergenericString 为相同的类型。

以上是关于Java-泛型-3的主要内容,如果未能解决你的问题,请参考以下文章

java泛型上限下限,通配符

java泛型上限下限,通配符

Java 泛型通配符上限和通配符下限(正在整理)

JAVA泛型之<? extends T>:(通配符上限)和<? super T>(通配符下限)

java泛型中的下限

泛型-类型通配符的下限