1.泛型定义:
即参数化类型,在创建接口,类,方法时可将类型参数化传入<E>,用法同方法参数void speak(String str)。
***定义泛型的意义不在于将类或者接口规定为某一种类型,而是在你定义接口,类的时候,在何时何地去用这个传入进来的参数化类型,eg:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
//...省略掉其他具体的定义过程
}
2.自定义泛型接口,泛型类,泛型方法
class Box<T> {
private T data;
public Box() {
}
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
自定义的泛型类,通畅T、V、E之类的字母都属于类型形参
对于不同传入的类型实参,生成的相应对象实例的类型也是一样的
比如new Box<String>()和new Box<Integer>(),两个实例的类型都是Box!!!!!
3.通配符泛型
Box<Number>在逻辑上不能视为Box<Integer>的父类,为了迎合JAVA多态性,因此,我们需要一个在逻辑上可以用来表示同时是Box<Integer>和Box<Number>的父类的一个引用类型,
类型通配符一般是使用 ? 代替具体的类型实参。注意了,此处是类型实参,而不是类型形参!且Box<?>在逻辑上是Box<Integer>、Box<Number>...等所有Box<具体类型实参>的父类。由此,我们依然可以定义泛型方法,来完成此类需求
泛型类作为方法参数时的,需要使用通配符!!!!!
public class GenericTest {
public static void main(String[] args) {
Box<String> name = new Box<String>("corn");
Box<Integer> age = new Box<Integer>(712);
Box<Number> number = new Box<Number>(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(Box<?> data) {
System.out.println("data :" + data.getData());
}
}
4.类型通配符上限:比如
public static void getUpperNumberData(Box<? extends Number> data){
System.out.println("data :" + data.getData());
}
类型通配符上限通过形如Box<? extends Number>形式定义,相对应的,类型通配符下限为Box<? super Number>形式,其含义与类型通配符上限正好相反