泛型中的通配符
在没有使用通配符时:
package zhai.Fx;
import java.util.List;
public class FxDemo7 {
// 在不适用通配符的编写方法
public void a(List<Object> list) {
}
public void a(List<String> list) {
// 这时候虽然重载了 a 方法参数是不一样,但是还会报错
// 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
}
public void a(List<Integer> list) {
// 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
// 这样的创建方法只是重复定义方法
}
}
使用通配符后:<?>
package zhai.Fx;
import java.util.ArrayList;
import java.util.List;
public class FxDemo8 {
public static void main(String[] args) {
// 使用通配符后的编写
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
List<?> list = null;
list = list1;
list = list2;
list = list3;
}
}
案例:如:A和B是继承关系,G <A>和G<B> 并不是继承关系,只是并列关系;
注意:加入通配符 <?> 后,G<?>就变成了G<A>和G<B>的父类。
package zhai.Fx;
import java.util.ArrayList;
import java.util.List;
public class FxDemo7 {
// 在不适用通配符的编写方法
// public void a(List<Object> list) {
//
// }
//
// public void a(List<String> list) {
// // 这时候虽然重载了 a 方法参数是不一样,但是还会报错
// // 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
// }
//
// public void a(List<Integer> list) {
// // 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
// // 这样的创建方法只是重复定义方法
// }
class Test{
public void a(List<?> list){
// 遍历使用 Object 进行接收
for (Object o:list) {
System.out.println(o);
}
Test test = new Test();
// 使用当前类调用当前类中的方法
// 使用<?> 通配符后,此时这个<?>就相当于是整个泛型参数的父类,可以传入任何类型的泛型参数
test.a(new ArrayList<Integer>());
test.a(new ArrayList<String>());
test.a(new ArrayList<Double>());
}
}
}
注意:使用通配符<?>后,其实就是相当于给整个泛型参数加上一个父类,既然是父子类关系后,就可以定义任何参数类型来进行使用。
遍历:就是使用通配符后的遍历,可以直接拿Object类型进行接收,<?> 不能为接收类型。
使用通配符进行写入和读取操作:
package zhai.Fx;
import java.util.ArrayList;
import java.util.List;
public class FxDemo7 {
// 在不适用通配符的编写方法
// public void a(List<Object> list) {
//
// }
//
// public void a(List<String> list) {
// // 这时候虽然重载了 a 方法参数是不一样,但是还会报错
// // 因为在泛型标签中不存在继承关系 它 Object和String只是并列关系
// }
//
// public void a(List<Integer> list) {
// // 它这样其实就不是重载方法,因为在底层它们是一样的,都是把List接口作为参数进行传入
// // 这样的创建方法只是重复定义方法
// }
class Test{
public void a(List<?> list){
// 写入数据
// list.add("abc"); ---> 错误,不能随意添加数据
// 读取数据
Object o1 = list.get(0); // 读取的时候,因为不知道是什么类型的数据,所以使用Object类型来进行接收数据
for (Object o:list) {
System.out.println(o);
}
Test test = new Test();
// 使用当前类调用当前类中的方法
// 使用<?> 通配符后,此时这个<?>就相当于是整个泛型参数的父类,可以传入任何类型的泛型参数
test.a(new ArrayList<Integer>());
test.a(new ArrayList<String>());
test.a(new ArrayList<Double>());
}
}
}
泛型受限:
package zhai.Fx;
import java.util.ArrayList;
import java.util.List;
// 测试类
public class FxDemo9 {
public static void main(String[] args) {
// 这个泛型参数中,并没有父子级关系,而是并列关系
List<Object> a = new ArrayList<>();
List<Person> b = new ArrayList<>();
List<Student> c = new ArrayList<>();
// 受限:
/*
* 上限
*/
List<? extends Person> list = null; // 使用?extends 父类时为上限
// list = a; ---> 错误代码 使用 extends 就不能使用父类以上的祖父类参数类型
list = b; // 这是父类不报错
list = c; // 这是子类也不报错
/*
* 下限
*/
List<? super Person> list1 = null;
list1 = a;
list1 = b;
// list1 = c; ---> 错误,因为使用super的话就是只能放入父类的参数类型
}
}
// 父类
class Person {
}
// 子类
class Student extends Person {
}
上下限总结:
-
上限:参数中使用<? extends 父类>时,就为上限,不能传入父类以上的参数,只能传入父类本身以及子类。
-
下限:参数中使用<? super 父类>时,就为下限,不能传入父类一下的参数,只能传入父类以上的祖父类等…