第一次看到类型后面的<\? extends class>,请无视那个反斜杠。我十分迷惑,不知道这时干什么的。直到我学到了泛型,哦,原来泛型没有我想象的那么神秘。
因为Java集合有个缺点,将一个对象放进集合之后,集合就会忘记这个对象的数据类型,当再次取出对象时,这个对象就变成了Object类型(当然实际类型并没有发生变化)。因此泛型被提了出来就是为了解决这个问题
入门
List<String> strList = new ArrayList();
strList.add("aaaa");
strList.add("bbbb");
strList.add(5);
strList.forEach(str -> System.out.println(str.length()));
其中strList.add(5);会报错,因为在声明这个集合的时候,说明了这个集合只装String类型的变量。当然并不一定局限在变量里,自己定义的变量或者集合都是可以的。
深入泛型
可以在任何类,接口增加泛型声明
//定义Apple类时使用了泛型声明
public class Apple<T> {
//使用T类型形参定义实例变量
private T info;
public Apple(){}
//使用泛型定义构造器
public Apple(T info){
this.info = info;
}
public T getInfo() {
return this.info;
}
public void setInfo(T info) {
this.info = info;
}
public static void main(String[] args){
//传给T的为String类型,所以构造器参数只能为String
Apple<String> a1 = new Apple<>("苹果");
System.out.println(a1.getInfo());
//传给T的为Double类型,所以构造器参数只能为Double
Apple<Double> a2 = new Apple<>(63.2);
System.out.println(a2.getInfo());
}
}
不过需要声明:当创建了带泛型声明的接口,父类之后,可以为该接口创建实现类,或从该父类派生子类,需要指出,当使用这些接口,父类时不能再包含类型形参。
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号<\?>,写作:类型<\?>。但是这种通配符仅表示是各种泛型的父类,并不能添加元素,不过可以返回元素。
类型通配符的上限
部分代码如下所示:
public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
//实现画图方法,以打印字符串来模拟画图方法实现
public void draw(Canvas c){
System.out.println("在画布" + c + "上画一个圆");
}
}
public class Rectangle extends Shape {
@Override
public void draw(Canvas c) {
// TODO Auto-generated method stub
System.out.println("把一个矩形画在画布" + c + "上");
}
}
public class Canvas {
public void drawAll(List<? extends Shape> shapes){
for(Object obj : shapes){
Shape s = (Shape)obj;
s.draw(this);
}
}
}
其中List<\? extends Shape>就表示通配符的上限为Shape,通俗来说,就是这个问号代表以Shape为父类的所有子类,包括自身。
类型形参上限
Java泛型不仅允许在使用通配符形参时设定上限,而且可以在定义类型形参时设定上限。
public class Apple<T extends Number> {
public static void main(String[] args) {
// TODO Auto-generated method stub
Apple<Integer> ai = new Apple<>();
Apple<Double> ad = new Apple<>();
//Apple<String> as = new Apple<>();
}
}
定义Apple类时,定义了类型形参上限为Number类,这表明使用Apple类是为T形参传入的实际类型参数只能为Number或其子类,也可以更严格一下,设定多个上限(之多一个父类上限,多个接口上限),表明除了是父类的子类或本身之外,还需要实现这些接口。
public class Apple