What is generic?
Generic(泛型)是指在创建class,method或者interface时规定一个参数类型,可以是确定类型(String,Integer,Double...)或者是不确定类型(E,T,K,V)来规定其中的参数类型,可以将未在规定内的参数类型的代码在complie时报错进行修改。(默认泛型为Object)
public class A<E>{}
//创建一个泛型E的classA(不知道具体什么类型的数据),此泛型可以在class中使用
public static <E>void B(E e){}
//创建一个泛型为E的methodB,此泛型可以在method中使用
public abstract interface C<E>{}
//创建一个泛型为E的interface C,此泛型可以在interface中使用
Java中的泛型被称为伪泛型,可以认为泛型为其所在的部分加了一个门,门口检测你是否为规定泛型,如果是,就放行,如果不是,则报错进行修改。
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//规定String类型的list 并调用add方法
但在包装后泛型会被清除,全部的对象都被视为Object类,并在运算后内部强转为规定类型,予以输出。
泛型可以将error转到complie-time bugs进而增加代码的稳定性
How to use generic
generic class
public class ArrayList<E>{
.........}
ArrayList<String> list1 = new ArrayList<>();
list1.add("aaa");
list1.add("bbb");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(123);
list2.add(456);
list1.add(123);//error 因为规定为String型
如果不知道类型,便可以定义为泛型类型,我们也可以利用泛型自己写一个类。
public class MyList<E>{ //不知道什么类型的参数 设为E
Object obj = new Object[6]; //new一个新的object数组给MyList为参数
int size =0; //初始size为0
public boolean add(E e){
obj[size] = e;
size ++;
return true;
}
public E get(int index){
return (E)obj[index];}
}
则我们可以在另一个类中调用这个类,new一个新对象。
.....class A{
MyList<> list =new Mylist<>(); //报错,因为要规定泛型的具体类型
MyList<Integer> list =new Mylist<>();} //正确
generic method
在一个类中定义泛型表示整个类中都可以用这个泛型,如果我们想定义一个泛型只适用于一个方法,则需要在方法上进行泛型的定义。
public static <E>void A(E e){}
例如,写一个addAll方法进行list中元素的增加。
public class A{
public static <E>boolean addAll(ArrayList<E> list,E...e){
for(E element:e){
list.add(element);}}}
在classb中进行addAll的调用。
...class B{
ArrayList<Integer> list1 =new ArrayList<>();
A.addAll(list1,1,2,3,4,5); //自动变为int类型
ArrayList<String> list2 =new ArrayList<>();
A.addAll(list2,"aa","bb","cc","dd"); //自动变为String类型
}
generic interface
public abstract interface List<E>{}
泛型接口重要的是如何使用。
1.在实现的class给出具体类型。
public class A implements List<String>{
.........}
A list = new A();//不需要用<>来规定
2.在实现class继续使用泛型,在创建新对象时再进行具体类型的补充。
public class A implements List<E>{
.........}
A<String> list = new A<>();//不需要用<>来规定
Wildcards(通配符)
通配符为?,表示一个未知的变量类型。
"?"
public class A<?>{}
这个用的不多,与上面的E可以说是一个东西。
"? extends X"
? extends X表示一个泛型,但范围为X与X的子类。
class A{}
class B extends A{}
class C extends B{}
ArrayList<A> list1 = new ArrayList<>();
ArrayList<B> list2 = new ArrayList<>();
ArrayList<C> list3 = new ArrayList<>();
public void method(ArrayList<? extends B> list){}
method(list1); //错误
method(list2);
method(list3);
"? super X"
? extends X表示一个泛型,但范围为X与X的父类。
class A{}
class B extends A{}
class C extends B{}
ArrayList<A> list1 = new ArrayList<>();
ArrayList<B> list2 = new ArrayList<>();
ArrayList<C> list3 = new ArrayList<>();
public void method(ArrayList<? super B> list){}
method(list1);
method(list2);
method(list3); //错误
泛型不具备继承性
class B extends A{}
public static void method(ArrayList<A> list){}
ArrayList<B> list =new ArrayList<>();
method(list);//错误 因为泛型不能继承
但是数据可以继承。
class A{}
class B extends A{}
class C extends B{}
ArrayList<A> list =new ArrayList<>();
list.add(new ArrayList<B>()); //正确
list.add(new ArrayList<C>()); //正确