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的父类
看起来像不像多态