JAVA基础之----泛型

 泛型的好处

  在程序中进行java转换时,可能会出现ClassCastException类型转换异常 List list = new ArrayList();,如果你想在List里面存放String类型,当你add进去一个int类型时, 编译不会出错,运行报错.

   在程序编码时,如果遇到错误,越早发现越好。引用泛型 List<String> list = new ArrayList<String>(); 如果往list里面add进去一个非String类型,则会在编译阶段就进行错误提醒。

定义泛型类

  这里的Bag类的 T 先不告诉需要成员变量的类型,具体类型要等用Bag这个类后才确定

public class Bag<T>{
    private T content;
    public Bag(T content){
        
    }
    public T getContent() {
        return content;
    }

    public void setContent(T content) {
        this.content = content;
    }
    
    public static void main(String[] args) {
        Bag<String> bag = new Bag<String>("book");
        String content1=    bag.getContent();
        int content2 = bag.getContent();//编译出错
    }
}

 上个例子new Bag()的时候 T传String,那么content也是String,如果用int来接收bag.getContent(),那么编译期间就会报错(省的到运行时候在出现ClassCastException)

用extends关键字限定类型参数

  在定义泛型类时,可以用extends关键字限定类型参数

  <T extends 类名(接口名)>的子类(接口的实现类)意思就是:泛型的参数只能是类名(接口名)的子类

定义泛型方法

  在一个方法中,如果一个方法的参数或者返回值类型带有<T>形式的类型参数,那个这个方法称为泛型方法。

   下面方法max(T x,T y),参数T必须实现Comparable接口

public class MethodTest<T>{
     Student s1 =new Student();
     Student s2 =new Student();//泛型方法max()
    public static<T extends Comparable<T>> T max(T x,T y){
        return x.compareTo(y)>0 ? x:y;
    }
    class Student{
        
    }
  public void test() { max(s1,s2);//编译报错 因为Student类没有实现泛型方法的Comparable接口 } }

使用“?“通配符

  •   在泛型机制中,编译器认为HashSet<String>和Set<String>之间存在继承关系,因此下列赋值是合法的:

         Set<String> s1 = HashSet<String>();//合法,允许向上转型

  •    但编译器认为 HashSet<Object>与HashSet<String>之间不存在继承关系,因此下列赋值是不合法的:

     HashSet<Object> s2 = new HashSet<String>();//编译出错 为了解决这种报错printNew()方法中 使用<?>通配符表示可以存放任意类型

public class CastTest<T>{
    public static void print(List<Object> list){
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
    public static void printNew(List<?> list){
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
   
    public static void main(String[] args) {
        List<Integer> integer = new ArrayList<>();
        integer.add(11);
        print(integer); //编译出错
        printNew(integer); //使用了"?"通配符 合法<?>表示可以放任意类型的原色  
    }    
}

通配符和extends super连用

  •  通配符和extends关键字连用,用来限定类型参数的上限

    TreeSet<? extends 类型1> x = new TreeSet<类型2>(); 类型1表示特定的类型,类型2只能是类型1或者是类型1的子类

  •  通配符和super关键字连用,用来限定类型参数的下限

   TreeSet<? super类型1> x = new TreeSet<类型2>(); 类型1表示特定的类型,类型2只能是类型1或者是类型1的父类

  看起来像不像多态

   但是,如果通过反射动态加载可以绕过泛型编译期间的检查

原文地址:https://www.cnblogs.com/ssskkk/p/8507511.html