允许在定义类、接口时通过一个标识表示类中某个属性的类型、方法返回值、参数类型。这个标识将在使用时确定。 参数T必须为类,且可为多个。
ArrayList<Integer> list = new ArrayList<>();//类型推断,该集合仅可存储Integer类型数据
list.add(78);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
8.1 自定义泛型结构—类
// 自定义泛型类,指明参数T
public class order<T>{
String orderName;
T orderT;
public Order(){}
public Order(String orderName,T orderT){
this.orderName = orderName;
this.orderT = orderT;
}
public T orderT(){
return orderT;
}
}
// 实例化未指明参数类型时,默认为Object类型
Order order = new Order();
order.setOrderT(123);
order.setOrderT("123");
// 实例化指明参数类型(建议),则参数类型特定
Order<String> order1 = new Order<String>();
//order1.setorderT(123); 报错,仅可为String
// 定义泛型类,
class Person<T extends Info>{}
泛型不同的引用不能相互赋值,泛型要使用就一路都用,要不用就一路都不用。
例如:
类A是类B的父类,G<A>与G<B>不具备子父类关系,二者为并列关系,共同的父类是G<?>
类A是类B的父类,A<G>是B<G>的父类
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,在静态方法中不能使用类的泛型。
- 异常类不能是泛型。
泛型数组的声明:
T[] arr = new T[10]; // 编译不通过
T[] arr = (T[])new Object[10]; // 编译通过
子类与父类中的泛型 ```java class Father
{}
// 子类不保留父类的泛型 // 1)没有类型 擦除 class Son1 extends Father {// 等价于class Son extends Father
// 子类保留父类的泛型
// 1)全部保留
class Son3
<a name="uRyFm"></a>
## 8.2 自定义泛型结构--方法
泛型方法在调用时才指明参数的类型,可以是static的,因为泛型确定与是否为类、对象是没有关系的。<br />`[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称])`
```java
public <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e:arr)
list.add(e);
return list;
}
8.3 通配符
类型通配符?
用于所有泛型的引用
。如:List<?>
是List<String>、List<Object>
等各种泛型List
的父类。
读取List<?>
中的元素永远都是安全的,因为不论其真实类型是什么其包含的都是Object
,所以读出的数据也是Object类型。写入元素是不行的,因为不知道其元素类型,因此不能向其添加对象,唯一的例外是null,它是所有类型的成员。
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
c.add(null); // 编译通过
List<String> l1 = new ArrayList<String>();
read(l1);
// 通用的List遍历方法
public static void read(List<?> list) {
for (Object o : list) // 元素一定为Object类型
System.out.println(o);
}
8.4 有限制条件的通配符
<? extends Number> (无穷小 , Number] // 只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大) // 只允许泛型为Number及Number父类的引用调用声明下限
<? extends Comparable> // 只允许泛型为实现Comparable接口的实现类的引用调用
List<? extends Person> list1 = null; // 可以引用下面的list3和list4
List<? super Person> list2 = null; // 可以引用下面的list4和list5
List<student> list3 = new ArrayList<student>():
List<Person> list4 = new ArrayList<Person>();
List<object> list5 = new ArrayList<object>();
//读取数据:
list1 = list4;
Person p= list1.get(0); // 获取的对象类型最小为Person,这是为了满足定义中的引用条件
list2 = list4;
Object obj = list2.get(0); // 获取的对象类型最小为Object,这是为了满足定义中的引用条件
//写入数据
//list1.add(new Person()); // 子类可能无穷小,因此extends界限不能添加类型
list2.add(new Student()); // Person为下界,最大为Person,子类即父类,因此Person及其子类均可