文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文带你搞懂Java中的泛型和通配符

2024-04-02 19:55

关注

概述

泛型机制在项目中一直都在使用,比如在集合中ArrayList<String, String>, Map<String,String>等,不仅如此,很多源码中都用到了泛型机制,所以深入学习了解泛型相关机制对于源码阅读以及自己代码编写有很大的帮助。但是里面很多的机制和特性一直没有明白,特别是通配符这块,对于通配符上界、下界每次用每次百度,经常忘记,这次我就做一个总结,加深自己的理解。

泛型介绍和使用

泛型在类定义时不会设置类中的属性或方法参数的具体类型,而是在类使用时(创建对象)再进行类型的定义。会在编译期检查类型是否错误, 保证程序的可读性和安全性。

泛型定义根据实际情况可以分为泛型类和泛型方法:

泛型类

public class Point<T, U> {

    private T pointX;

    private U pintY;

    public Point(T pointX, U pintY) {
        this.pointX = pointX;
        this.pintY = pintY;
    }

    public void showPoint() {
        System.out.println(pointX);
        System.out.println(pintY);
    }
}

泛型方法

public class FxMethod {

    public static <T> T getMiddleNumber(T ... numbers) {
        return null;
    }

    public <T, U> void showNumber(T t, U u) {
        System.out.println("t = " + t);
        System.out.println("u = " + u);;
    }
}

类型变量的限定

前面讲解了泛型一般定义的两种方式,其中的类型变量没有任何限定, 这样在导致一方面在定义泛型的时候无法使用一些API, 需要强转,另一方面在使用的时候也容易出错,那么如何给类型变量添加限定呢?

通配符使用

泛型的引入的确解决了很大问题,那它是完美的吗?

class AnimalWrapper<T extends Animal> {
    private T animal;

    AnimalWrapper(T animal) {
        this.animal = animal;
    }

    public void eat() {
       animal.eat();
    }

}

class Animal {
    private String name;

    public void eat() {
        System.out.println("animal eat -----");
    }
}

class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println(" cat eat -----");
    }
}

定义一个AnimalWrapper,泛型变量中限定为Animal,如果是下面的测试类,会怎么样呢?

会编译报错,因为AnimalWrapper并不是AnimalWrapper的子类,不能直接传入。为了解决个问题,我们引入了通配符,通配符一般是在方法中或者泛型类使用中用到。

AnimalWrapper可以作为AnimalWrapper<?extends Animal>的子类型,这就是利用通配符带来的好处。

无边界通配符

通配符无边界,可以传入任何类型,没有限制,相当于Object.

基本语法:

<?>

例子:

public static void printList1(List<?> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // ok

        
        List<?> list3 = list;
        // get只能用Object接受, 
        Object o = list3.get(0);
        list3.add(5);   // compile error
        list3.add(new Object()); // compile error
    }

小结:

通配符上界

通配符上界,可以限制传入的类型必须是上界这个类或者是这个类的子类。

基本语法:

<? extends 上界> 
<? extends Number>//可以传入的实参类型是Number或者Number的子类

例子:

public static void printList1(List<? extends Number> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }


    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<Double> list1 = new ArrayList<>();
        list1.add(1.0D);
        printList1(list1);  // ok
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // compile error


        List<? extends Number> list3 = list;
        // get能用上界
        Number o = list3.get(0);
        // 不能add
        list3.add(5);   // compile error
        list3.add(new Object()); // compile error

    }

小结:

通配符下界

通配符下界,可以限制传入的类型必须是这个类或者是这个类的父类。

基本语法:

<? super 下界> 
<? super Integer>//代表 可以传入的实参的类型是Integer或者Integer的父类类型

例子:

public static void printList1(List<? super Integer> list) {
        for (Object x:list) {
            System.out.println(x);
        }
    }


    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        printList1(list);  // ok
        List<Double> list1 = new ArrayList<>();
        list1.add(1.0D);
        printList1(list1);  // compile error
        List<String> list2 = new ArrayList<>();
        list2.add("1");
        printList1(list2); // compile error


        List<? super Integer> list3 = list;
        // 不能用下界接收
        Integer o = list3.get(0); // compile error
        // 能add
        list3.add(5);   // ok
        list3.add(new Number(5)); // compile error

    }

到此这篇关于一文带你搞懂Java中的泛型和通配符的文章就介绍到这了,更多相关Java泛型 通配符内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯