1 泛型
1.1 作用
1),这个就是一种泛型,是对集合的一种限定。被标记上该符号的集合,被限定存储该类的数据。比如 ArrayList arr = new ArrayList<>(); 这就指定了 arr 这个集合只能存储 String 字符串。
2)提高安全性(将运行期的错误转移到编译期),如果存储了指定以外的其他类型数据,编译的时候就会报错。避免了强行转换导致的错误。
1.2 添加的方式
在创建类的时候写在类的后面
注意,类名内填写的必须是引用数据类型,即必须使用装箱后的数据类型,不允许使用int,char等基本数据类型,只能添加Integer、Character等数据类型。
怎么使用?
1)创建对象的时候,等号两侧使用。
2)前后泛型必须一致
在JDK1.7以后,可以这么写
ArrayList aL = new ArrayList<>();//菱形泛型
2 泛型类
public class Tool {//定义泛型Q,Q是什么类型只有在使用的时候被定义 private Q q;
public Q getObj() {
return q;
}
public void setObj(Q q) {
this.q = q;
}
public void print(Q q) {
}
}
//使用Tool t = new Tool<>();//在这里定义了泛型 Q 为 Student 类型
3 泛型方法
3.1 定义方式
public void print(T t) {
System.out.println(t);
}
//使用的时候直接带入即可 tool.print(new Student(24,"张三"));
3.2 作用
1)在方法中可以单独定义一个泛型。但是如果该泛型和类定义的泛型不一致,需要在使用的时候定义泛型代表的具体的类。
2)静态方法随着类的加载而加载,可能出现于创建对象前。所以静态方法如果要使用泛型必须指定自己的泛型。注意, 静态方法的泛型即便与类的泛型同名,也是不同的泛型。
4 泛型接口
interface Inter{
public void print(T t);
}
//使用class Demo implements Inter{//此处指定泛型类型 public void print(Student s) {
}
}
5 泛型通配符>
作用:
1)由于等号左右的泛型需要一致,但你可能不知道等号右侧的泛型是什么。
所以等号左侧可以使用泛型通配符
2)泛型通配符相当于 extends Object>,可以匹配一切类
3)使得一个集合当中可以放置父类和子类对象,即使用通配符去匹配子类对象。
为什么不使用,看看下面的代码
public void superAndExtends(){
ArrayList arr = new ArrayList<>();
arr.add(new Student(15, "张三"));
arr.add(new Student(25, "李四"));
arr.add(new Student(26, "王五"));
arr.add(new Student(13, "赵六"));
arr.add(new Student(27, "钱七"));
//Iterator it = arr.iterator();//此句话会报错Iterator extends Object> it = arr.iterator();
}
6 extends E> 与 super E>
6.1 前言
设指向对象为A,被指向对象为B,A->B
只有 B 是 A 的同类或子类的时候,该指向操作才被允许。当 B 是 A 的子类时,A 是多态。
以下比较难理解。
6.2 ? extends E
表示泛型固定的上边界
分为两种情况,
1) 用 extends E>指定 A 对象的类型
由于 A 对象没有确定下边界,所以不可以添加任何对象。举个例子,Student 是 Preson 的子类。因为 A 对象可能是 Teacher类,而 Teacher 类指向 Student 类对象。所以这种用法是无效的。
比如arr.add(new Student(15,"张三"));这句话,相当于在内存中新建一个 Student 类对象,再由一个 Preson 类指向该对象。
ArrayList extends Preson> arr = new ArrayList<>();
arr.add(new Student(15, "张三"));//这段代码不被编译器通过arr.add(new Preson(15, "张三"));//这段代码不被编译器通过
2)用 extends E>指定 B 对象的类型
已经指定了 ArrayList 中存储的是 Preson 类型,而 Iterator迭代器使用 extends E>指定的是传入对象强转后数据类型的上边界。比如 B 的上边界被指定为 Object 。则表明 Preson类型的数据在传入后,被向上转成 Object 类。这是被允许的,相当于新建一个 Object 对象再指向 Preson 对象,此对象为多态。
public void superAndExtends(){
ArrayList arr = new ArrayList<>();
arr.add(new Preson(15, "张三"));
arr.add(new Preson(15, "李四"));
Iterator extends Object> it = arr.iterator();//编译器通过Iterator extends Preson> it2 = arr.iterator();//编译器通过//Iterator extends Student> it2 = arr.iterator();//这段代码不被编译器通过}
6.3 ? super E
表示泛型固定下边界
1)用 super E>指定 A 对象的类型
泛型固定下边界,可以添加子类和同类对象。
ArrayList super Preson> arr2 = new ArrayList<>();
arr2.add(new Preson(15, "张三"));//编译器通过arr2.add(new Student(15, "张三"));//编译器通过ArrayList super Student> arr3 = new ArrayList<>();
//arr3.add(new Preson(15, "张三"));//这段代码不被编译器通过arr3.add(new Student(15, "张三"));//编译器通过
但是你会发现在这里好像没什么卵用,因为不加跟加了好像没什么区别。
ArrayList arr2 = new ArrayList<>();
arr2.add(new Preson(15, "张三"));//编译器通过arr2.add(new Student(15, "张三"));//编译器通过ArrayList arr3 = new ArrayList<>();
//arr3.add(new Preson(15, "张三"));//这段代码不被编译器通过arr3.add(new Student(15, "张三"));//编译器通过
具体能在哪里用上,如果有大佬知道的话,在评论区里说一下吧。
2)用 super E>指定 B 对象的类型
同样,比如Iterator super Object> it3 = arr2.iterator();这句话。
指定了 B 对象的下边界,但是 A->B 的操作,需要 B 是 A 的同类或者子类才行,此句话不能保证这个条件,所以会报错
//Iterator super Object> it3 = arr3.iterator();//这段代码不被编译器通过//Iterator super Preson> it4 = arr3.iterator();//这段代码不被编译器通过//Iterator super Student> it4 = arr3.iterator();//这段代码不被编译器通过