//看了别人写的,结合自己的理解加了和减了一点东西
泛型:
1.为何有泛型?
首先,泛型是在编译期间进行校验的以保证类型安全。
第二就是,集合不会保证对象的类型,统一用父类object类型来指代,由于java的特性,在编译期间,父类和子类都可以用父类来指代,虽然运行时都是自己的实际类型,集合这个是这样的,他们用object这个统一的父类来指代,但是在编译期间你要使用子类特有的方法时的话还是要转换成子类类型,现在问题来了,集合类里面什么元素几乎都可以添加,毕竟都是object的子类,但是我们要使用的话,就会出现问题了,我们不知道到底是不是我们要使用的子类,万一集合里面添加了一个不是我们要用的子类,我们转换使用的时候就会报错:java.lang.ClassCastException
2.最简单的泛型实例
List<String> list = new ArrayList<String>();
就像这个加了String这个限制,放到集合里面的元素必须是String类型,取出数据的时候也没必要转换为string类型了,因为编译器已经知道了,不需要转换了(额外说下这个多态,多态的原理也正是这个原理,父类可以在编译期间指代子类,但是实际运行还是本身的类型,要是想用子类特有的方法,父类是不行的,虽然确实可以使用,但是编译时不会通过的,会报错,说找不到这个方法。)
3.自定义泛型接口、泛型类和泛型方法
class Box<T> {
private T data;
public Box() {
}
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
public class DemoTest {
public static void main(String[] args) {
Box<String> name = new Box<String>("dh");
Box<Integer> age = new Box<Integer>(123);
System.out.println("name class:" + name.getClass()); // com.dh.Box
System.out.println("age class:" + age.getClass()); // com.dh.Box
System.out.println(name.getClass() == age.getClass()); // true
}
}
发现在泛型接口泛型类中我们一般使用E,K,V等常数来接收来自外部的类型实参,而且大家发现这个类型是一样的,终究发现泛型只是编译期的东西,不会带到运行期,主要就是校验所传信息是否正确罢了,当然在逻辑上我们可以理解这是一些不同类,但是实际上这些都是相同的类,就是我们在生成对象的时候,给这个对象传了一个类型参数过去,就是这个类型参数是这个类的一点限制,多了一个参数,一个校验参数罢了
4.类型通配符
public class DemoTest {
public static void main(String[] args) {
Box<String> name = new Box<String>("dh");
Box<Integer> age = new Box<Integer>(123);
Box<Number> number = new Box<Number>(456);
getData(name);
getData(age);
getData(number);
getUpperNumberData(name); // 1
getUpperNumberData(age); // 2
getUpperNumberData(number); // 3
}
public static void getData(Box<?> data) {
System.out.println("data :" + data.getData());
}
public static void getUpperNumberData(Box<? extends Number> data){
System.out.println("data :" + data.getData());
}
}
我们用?来代替具体的类型实参,?可以说是所有的泛型类型的父类,可以指代任何泛型类型。是实参,不是形参。
<? extends T>必须是T和T的子类
<? Super T>必须是T或T的父类