本文分享自华为云社区《15个问题掌握java泛型》,原文作者:breakDraw 。
Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
一般定义如下,即方法的前面加了个
public class FTest {
public List f(T t){...};
}
三种泛型参数推断方式:
1、直接在f()前面加确定泛型
fTest.f(xxx)
2、通过输入参数确定, 下面这个推断为Integer
int number = 0;
fTest.f(number)
3、可通过 返回值 确定
List list = fTest.f(xxx);
Q: 下面这段代码哪里有问题? 是toString()那里吗?
public class A {
public static void test(T t){
System.out.println(t.toString());
}
}
A:test是static方法, 因此无法感知A
需要改成
public static
toString()那里没问题,toString就是Object的方法。
Q: 泛型参数T在运行时,会变成什么?
A: 统一变成Object且不包含任何类型信息。
Q: 泛型参数T可以可以使用instanceof做比较吗?
class A {
void f(Object arg)
if(arg instanceof T) {
...
}
}
A: 不能,编译器会报错。
Q: 泛型参数T可以进行new T()或者new T[]操作吗?
A: 不能,编译器会报错。
Q: 能调用泛型参数对象里的方法吗?
T.f();
A: 只能调用Object的方法。
Q: 可以用T做强制转化吗?
T t = (T)object;
A: 能运行, 但不会真正发生转型, 编译时会触发waring警告。
先假定有2个类, 基类Parent 和子类Child
class Parent{}
class Child extends Parent{}
回答以下问题:
Q:下面这句话有问题吗?
List list = new ArrayList()
A:有问题,编译就错误了。 List
Q:
List extends Parent> list = new ArrayList();
这个list有什么特点?
A:这个list可以调用A a = list.get(), 但是不能list.add(new Parent())
Q:
List super Child> list = new ArrayList();
这个list有什么特点?
下面谁会报错
list.add(new Child())
list.add(new Parent())
Parent a= list.get();
Child b = list.get()
A:截图如下:
Q:
List> list = new ArrayList();
这个list有什么特点?
A:get和add都不行,只能做remove等无返回值无输入A的操作。
PS: 注意,不是说不能调用get或add方法, 而是调用get或add时,不能使用A这个对象去操作。
即无法做add(A) 或者 A a = get(0)
但是可以做add(object) 或者Object o = get(0)
因为?可以转为Object, 但是无法转为A。
Q:下面这个代码会报错吗?
List fruitList = new ArrayList<>();
fruitList.add(new Fruit());
List appleList = new ArrayList<>();
appleList.add(new Apple());
fruitList.addAll(appleList);
System.out.println(fruitList);
A:不会报错。会正常打印结果。
PECS原则
注意PECS原则和上面的区别!
上面之前提到的? extend或者? supert, 都是在声明对象的时候用的。
而PECS原则是用于泛型对象的方法输入参数!
假设有一个类定义如下:
public static class MyList {
List list = new ArrayList<>();
// 把输入参数塞给自己,类似于生产操作
public void pushList(List t) {
list.addAll(t);
}
// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List t) {
t.addAll(list);
}
}
则T就是泛型参数。
Q:下面代码能正常运行吗?
MyList myList = new MyList<>();
List intList = new ArrayList<>();
myList.pushList(intList);
List
A:不能正常运行, pushList和pollList都会报错
因为编译器检查后,认为 List
Q: 如果上文要支持pushList,应该怎么修改pushList方法的定义?
A:改成这样:
// 把输入参数塞给自己,类似于生产操作
public void pushList(List extends T> t) {
list.addAll(t);
}
即编译器认为,List
Q: 如果要支持pollList,怎么修改定义?
A:
// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List super T> t) {
t.addAll(list);
}
因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List
PECS原则出自Effective Java, 注意只是一个编程建议而已!
点击关注,第一时间了解华为云新鲜技术~