参考资料文档见上一节
目录
一、通配符概述
1.概述
2.使用条件
3.使用方法
(1)简介
?(2).通配符上限
(3).通配符下限
4.拓展
?二、泛型数组
一、通配符概述
1.概述
- 在使用泛型方法时可以发现,虽然这样处理可以扩大使用范围,但是由于范围太大了,导致很多功能书写起来很困难,比如:
- 我们定义了一个类??Grandfather
@Data
public class Grandfather {
private String Name;
private Integer Age;
}
- 我们要获取? List<Grandfather>? 第一个元素的name值 ,用泛型的话只能用反射来做
private <T> String getName(List<T> list){
/**
* 这里只能用反射来获取到
* list第一个元素的 name
*/
return null;
}
2.使用条件
- 通配符的使用前提是:
- 1.必须共用同一个父类,或者构成继承关系,
如:Integer 和 Number类,以及自定义的有类(有共同父类或构成继承关系)
//用泛型方式实现
private <T> String method_01(List<T> list){
return null;
}
将尖括号里的T替换成通配符为
//用上限式通配符实现
private String method_02(List<? extends Father> list){
return null;
}
?
那么错误的写法是:

不能替换没有方法或者数据结构包裹的泛型?
3.使用方法
(1)简介
- 既然通配符必须使用在继承系统中的类,那么约束的话就是约束公用的父类和共用的子类,即通配符的上限和下限

@Data
public class Grandfather {
private String Name;
private Integer Age;
}
@Data
public class Father extends Grandfather{
}
@Data
public class Son extends Father{
}
?(2).通配符上限
<? extends TopClass>
即所有的类都必须是TopClass自身以及子类
(3).通配符下限
<? super BottomClass>
即所有的类都必须是BottomClass自身以及父类
(4).综合使用
- 根据上面定义的三个类,给出下面的综合使用,目的是统计输入list的年龄和
//测试通配符
public class Demo01 {
public static Random random = new Random();
//用泛型方式实现
private <T> String method_01(List<T> list) {
//泛型方式是无法统计年龄的总数的
StringBuilder str = new StringBuilder();
list.forEach(x -> {
str.append(x.toString());
});
return str.toString();
}
//用上限式通配符实现
private String method_02(List<? extends Father> list) {
Integer result = 0;
for (Father father : list) {
result = +father.getAge();
}
return String.valueOf(result);
}
//用下限式通配符实现
private String method_03(List<? super Father> list) {
StringBuilder str = new StringBuilder();
list.forEach(x -> {
str.append(x.toString());
});
return str.toString();
}
}
- 可以看到,用泛型和下限方式是实现不了的,用上限方式是可以实现的,并且上限和下限都规定在了father这一层,那么对这些方法的调用
//测试通配符
public class Demo01 {
public static Random random = new Random();
//用泛型方式实现
private <T> String method_01(List<T> list) {
//泛型方式是无法统计年龄的总数的
StringBuilder str = new StringBuilder();
list.forEach(x -> {
str.append(x.toString());
});
return str.toString();
}
//用上限式通配符实现
private String method_02(List<? extends Father> list) {
Integer result = 0;
for (Father father : list) {
result = +father.getAge();
}
return String.valueOf(result);
}
//用下限式通配符实现
private String method_03(List<? super Father> list) {
StringBuilder str = new StringBuilder();
list.forEach(x -> {
str.append(x.toString());
});
return str.toString();
}
@Test
public void test_01()throws Exception{
List<Grandfather> list1 = (List<Grandfather>) getList(Grandfather.class);
List<Father> list2 = (List<Father>) getList(Father.class);
List<Son> list3 = (List<Son>) getList(Son.class);
System.out.println(method_01(list1));
System.out.println(method_02(list1));
System.out.println(method_02(list2));
System.out.println(method_02(list3));
System.out.println(method_03(list1));
System.out.println(method_03(list2));
System.out.println(method_03(list3));
}
private List<? extends Grandfather> getList(Class<? extends Grandfather> clazz) throws Exception{
List<Grandfather> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Grandfather instance = clazz.newInstance();
instance.setAge(random.nextInt(100));
instance.setName(RandomStringUtils.randomAlphanumeric(5));
list.add(instance);
}
return list;
}
}
?

4.拓展
- 当然,泛型也是支持通配符的,但是仅仅是起到约束作用
public class Demo02 <T extends Father>{
public <E extends Son> void getName(List<E> list){
for (E e : list) {
}
}
}
?二、泛型数组
- 创建方式1:可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象
@Test
public void test_01(){
ArrayList<String>[] listArr = new ArrayList[5];
ArrayList<String> strList = new ArrayList<>();
strList.add("abc");
listArr[0] = strList;
String s = listArr[0].get(0);
System.out.println(s);
}
- ?创建方式2:可以通过java.lang.reflect.Array的newInstance(Class<T>,int)创建T[]数组
public class Fruit<T> {
private T[] array;
public Fruit(Class<T> clz, int length){
//通过Array.newInstance创建泛型数组
array = (T[]) Array.newInstance(clz, length);
}
/**
* 填充数组
* @param index
* @param item
*/
public void put(int index, T item) {
array[index] = item;
}
/**
* 获取数组元素
* @param index
* @return
*/
public T get(int index) {
return array[index];
}
public T[] getArray() {
return array;
}
}
?
@Test
public void test_02(){
Fruit<String> fruit = new Fruit<>(String.class,3);
fruit.put(0,"苹果");
fruit.put(1,"西瓜");
fruit.put(2,"香蕉");
System.out.println(Arrays.toString(fruit.getArray()));
String s1 = fruit.get(2);
System.out.println(s1);
}
|