无界通配符

“?”表示类型通配符,用于代替具体的类型。它只能在“<>”中使用。可以解决当具体类 型不确定的问题

public void showFlag(Generic generic){
}

  1. public class Generic<T> { //仅限制为定义时给定的类型,不存在继承一说
  2. private T flag;
  3. public void setFlag(T flag){
  4. this.flag=flag;
  5. }
  6. public T getFlag(){
  7. return this.flag;
  8. }
  9. }
  1. public class ShowMsg {
  2. public void showFlag(Generic<?> generic){
  3. System.out.println(generic.getFlag());
  4. }
  5. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. ShowMsg showMsg=new ShowMsg();
  4. Generic<Integer> generic=new Generic<>();
  5. generic.setFlag(20);
  6. showMsg.showFlag(generic);
  7. Generic<Number> generic1=new Generic<>();
  8. generic1.setFlag(30);
  9. showMsg.showFlag(generic1);
  10. Generic<String> generic2=new Generic<>();
  11. generic2.setFlag("耿");
  12. showMsg.showFlag(generic2);
  13. }
  14. }

通配符上限界定(可适用于泛型)

  1. 上限限定表示通配符的类型是 T 类以及 T 类的子类或者 T 接口以及 T 接口的子接口。 该方式同样适用于与泛型的上限限定。

public void showFlag(Generic <? extends Number> generic){
}

image.png

public class Generic<T> {
    private T flag;

    public void setFlag(T flag){
        this.flag=flag;
    }

    public T getFlag(){
        return this.flag;
    }
}
public class ShowMsg {
    public void showFlag(Generic<? extends Number> generic){
        System.out.println(generic.getFlag());
    }
}
public class Test {
    public static void main(String[] args) {
        ShowMsg showMsg=new ShowMsg();

        Generic<Integer> generic=new Generic<>();
        generic.setFlag(20);
        showMsg.showFlag(generic);

        Generic<Number> generic1=new Generic<>();
        generic1.setFlag(50);
        showMsg.showFlag(generic1);

//        Generic<String> generic2=new Generic<>();
//        generic2.setFlag("geng");
//        showMsg.showFlag(generic2);  //限定了范围,这个无法通过编译
    }
}

通配符的下限界定

下限限定表示通配符的类型是 T 类以及 T 类的父类或者 T 接口以

public void showFlag(Generic<? super Integer> generic){
}

逻辑同上线界定,若把上面的代码中的extends 换成 super 将会报错,原因是integer是number的子类

总结

泛型主要用于编译阶段,编译后生成的字节码 class 文件不包含泛型中的类型信息。 类
型参数在编译后会被替换成 Object,运行时虚拟机并不知道泛型。因此,使用泛型时,如下
几种情况是错误的:

  1. 基本类型不能用于泛型。
    Test t; 这样写法是错误,我们可以使用对应的包装类;Test t ;
  2. 不能通过类型参数创建对象。
    T elm = new T(); 运行时类型参数 T 会被替换成 Object,无法创建 T 类型的对象,容
    易引起误解,所以在 Java 中不支持这种写法