Java泛型
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者时某个方法的返回值及参数类型。泛型提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型。是jdk5.0新增的特性。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
1.在集合中使用泛型:
1.集合接口或集合类在jdk5.0时修改为带泛型的结构
集合中没有使用泛型的情况,如添加非法字符能通过编译,但运行时会报错,需要手动进行校验。
@Test
public void test0(){
ArrayList list = new ArrayList();
list.add(88);
list.add(67);
list.add(90);
list.add(54);
//list.add("Zane");//输入报错
for (Object score: list
) {
int stuscore = (Integer) score;
System.out.println(stuscore);
}
}
2.在实例化集合时,可以指明具体的泛型类型
@Test
public void test1(){
ArrayList<Integer> list = new ArrayList<>();
list.add(88);
list.add(67);
list.add(90);
list.add(54);
for(Integer score:list){
int stuscore = score;
System.out.println(stuscore);
}
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int stuscore = iterator.next();
System.out.println(stuscore);
}
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Tony",26);
map.put("Tom",24);
System.out.println(map);
}
3.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(如方法、构造器、属性)使用到类的泛型的位置,都指定为实例化的泛型类型
比如add(E e)–>实例化以后:add(Integer, e)
4.注意点:泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿包装类替换
5.如果实例化时,没有指明泛型的类型,默认类型为java.lang.Object类型
2.自定义泛型结构:泛型类,泛型接口,泛型方法
public class ETest<T> {
String eName;
int eId;
T eTestT;
public ETest(){};
public ETest(String eName,int eId, T eTestT){
this.eName = eName;
this.eId = eId;
this.eTestT = eTestT;
}
public T geteTestT(){
return eTestT;
}
public void seteTestT(T eTestT){
this.eTestT = eTestT;
}
@Override
public String toString() {
return("eName:" + eName + " eid:" + eId + " eTestT:" + eTestT);
}
//泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系
//换句话说,泛型方法所属的类是不是泛型类都没有关系
//泛型方法可以声明为静态,原因:泛型参数时在调用方法时确定的,并非在实例化类的时候确定
public static <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e: arr){
list.add(e);
}
return list;
}
}
调用自定义泛型类和调用泛型方法
public class GenericTest {
//如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类为Object类
//要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型
@Test
public void test0(){
ETest et = new ETest();
et.seteTestT(123);
et.seteTestT("ABC");
//指明泛型类型
ETest<String> et1 = new ETest<>("Zane",101,"HelloWorld");
System.out.println(et1.toString());//eName:Zane eid:101 eTestT:HelloWorld
}
//测试泛型方法
@Test
public void test1(){
ETest<String> et2 = new ETest<>("LYY",102,"HelloChina");
Integer[] arr = new Integer[]{1,2,3,4};
//泛型方法在调用时,指明泛型参数的类型
List<Integer> list = et2.copyFromArrayToList(arr);
System.out.println(et2);
System.out.println(list);
}
}
注意:
1.泛型不同的引用不能相互赋值
2.静态方法中不能使用泛型
3.异常类不能声明泛型
3.泛型在继承方面的体现
类A是类B的父类,G和G没有子父类关系,是并列关系,而A
/*
1.泛型在继承方面的体现
类A是类B的父类,G<A>和G<B>没有子父类关系,是并列关系,而A<G>是B<G>的父类
*/
@Test
public void test2(){
Object obj = null;
String str = null;
obj = str;
Object[] arr1 = null;
String[] arr2 = null;
arr1 = arr2;
List<Object> list1 = null;
List<String> list2 = null;
ArrayList<String> list3 = null;
AbstractList<String> list4 = null;
//此时的list1和list2不具备子父类关系,不能进行赋值
//list1 = list2;//不能赋值
list2 = list3;//可以赋值
list2 = list4;//可以赋值
}
4.通配符的使用
通配符:?
@Test
public void test3(){
List<Object> list1 = null;
List<String> list2 = null;
//通用父类
List<?> list = null;
list = list1;
list = list2;
// print(list1);
// print(list2);
List<String> list3 = new ArrayList<>();
list3.add("AAA");
list3.add("ABB");
list3.add("BBA");
list = list3;
//对于list<?>不能向其内部添加数据,只能添加null
//list.add("DDD");//不能添加
list.add(null);
//get
Object o = list.get(0);
System.out.println(o);//AAA
}
public void print(List<?> list){
Iterator<?> iterator = list.listIterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(obj);
}
}
5.1有限制条件的通配符的使用
? extends A:
G<? extends A>可以作为G和G的父类,其中B是A的子类 <= A
? super A:
G<? super A>可以作为G和G的父类,其中B是A的父类 >= A
/*
有限制条件的通配符的使用
? extends A:
G<? extends A>可以作为G<A>和G<B>的父类,其中B是A的子类 <= A
? super A:
G<? super A>可以作为G<A>和G<B>的父类,其中B是A的父类 >= A
*/
@Test
public void test4(){
List<? extends Customer> list1 = null;
List<? super Customer> list2 = null;
List<Student> list3 = null;
List<Customer> list4 = null;
List<Object> list5 = null;
list1 = list3;
list1 = list4;
//list1 = list5;//不能赋值
//list2 = list3;//不能赋值
list2 = list4;
list2 = list5;
//get
list2 = list4;
list2.add(new Customer());
list2.add(new Student());
}