泛型详解及使用及通配符、数组(二)

参考资料文档见上一节

目录

一、通配符概述

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类,以及自定义的有类(有共同父类或构成继承关系)

  • 2.方法的形参是一个可填泛型的方法、数据结构
    //用泛型方式实现
    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.ArraynewInstance(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);
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PH = 7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值