Java泛型extends及super区别实例解析

Java中的泛型可以指定一个类型参数,例如List,这表示这个List只能添加String类型的元素,否则编译器会报错。此外,泛型中还有一个重要的概念:泛型通配符。泛型通配符可以用来表示某个类的任意类型参数,例如List<?>,这表示这个List可以添加任意类型的元素。

当我们使用泛型通配符时,有时候需要限制可以添加的元素类型,这时可以使用extends或super关键字,本文就是要讲解extends及super的区别。

1. extends

extends关键字用于限制泛型的上界,表示只能添加该类型及其子类。例如:

public class Box<T extends Number> {
    private List<T> list = new ArrayList<>();

    public void add(T t) {
        list.add(t);
    }

    public T get(int index) {
        return list.get(index);
    }

    public static void main(String[] args) {
        Box<Integer> box = new Box<>();
        box.add(1);
        box.add(2);
        System.out.println(box.get(0) + box.get(1));
    }
}

上面这个例子中,Box限制了Box只能添加Number及其子类,这样在add方法中添加Integer类型的元素是没有问题的。

2. super

super关键字用于限制泛型的下界,表示只能添加该类型及其父类。例如:

public class Box<T> {
    private List<? super T> list = new ArrayList<>();

    public void add(T t) {
        list.add(t);
    }

    public Object get(int index) { // 注意这里返回类型为Object
        return list.get(index);
    }

    public static void main(String[] args) {
        Box<Integer> box = new Box<>();
        box.add(1);
        box.add(2);
        System.out.println(box.get(0) + (int)box.get(1));
    }
}

上面这个例子中,Box<? super T>限制了Box只能添加T及其父类,这样在add方法中添加Integer类型的元素是没有问题的。注意到get方法返回类型为Object,需要将第二个元素转换为int类型才能进行加法运算。

3. 示例

下面给出一个更加具体的例子,说明extends和super的区别。

假设有一个类Person和其子类Employee,代码如下:

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class Employee extends Person {
    private int salary;

    public Employee(String name, int salary) {
        super(name);
        this.salary = salary;
    }

    public int getSalary() {
        return salary;
    }
}

现在有一个类Company,表示一家公司,它有一个泛型属性staff,表示公司员工,代码如下:

public class Company<T> {
    private List<T> staff = new ArrayList<>();

    public void add(T person) {
        staff.add(person);
    }

    public T get(int index) {
        return staff.get(index);
    }

    public void printSalary() {
        for (T person : staff) {
            if (person instanceof Employee) {
                System.out.println(person.getName() + "的工资是" + ((Employee) person).getSalary());
            }
        }
    }
}

注意到在printSalary方法中,需要将person转换为Employee类型才能获取其工资。现在我们来测试一下这个类。

public static void main(String[] args) {
    Company<Person> company1 = new Company<>();
    company1.add(new Person("张三"));
    company1.add(new Person("李四"));
    company1.printSalary();

    Company<Employee> company2 = new Company<>();
    company2.add(new Employee("王五", 5000));
    company2.add(new Employee("赵六", 6000));
    company2.printSalary();

    Company<? extends Person> company3 = company2;
    company3.printSalary();

    Company<? super Employee> company4 = new Company<>();
    company4.add(new Employee("钱七", 7000));
    company4.add(new Person("吴八")); // 编译器报错
}

第一个公司company1没有任何员工的工资,输出为空。第二个公司company2有两个员工,输出他们的工资。第三个公司company3是company2的子类,因此也可以成功输出员工的工资。最后一个公司company4只能添加Employee类型的员工,而添加Person类型的员工会导致编译器报错。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java泛型extends及super区别实例解析 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • PHP:微信小程序 微信支付服务端集成实例详解及源码下载

    PHP:微信小程序微信支付服务端集成实例详解 在本文中,我们将为大家讲解如何在 PHP 中集成微信支付服务端,并包含了两个具体的示例。 准备工作 在开始集成之前,需要完成以下准备工作: 注册微信支付账号 在微信支付后台配置公众号或小程序,并设置回调地址 安装 curl 扩展 集成微信支付服务端 首先,我们需要在 PHP 代码中引用微信支付 SDK,可以使用 …

    Java 2023年5月23日
    00
  • 如何在Java中实现一个散列表

    散列表(Hash Table)是一种以键值对结构存储数据的数据结构,它可以高效地实现插入、删除和查找操作。在Java中,我们可以使用HashMap来实现一个散列表。 下面是实现一个散列表的步骤: 定义一个HashMap对象 在Java中,我们可以使用HashMap来实现散列表。因此,首先要定义一个HashMap对象。我们可以使用以下语法: HashMap&l…

    Java 2023年5月19日
    00
  • SpringBoot SSMP 整合案例分享

    SpringBoot SSMP整合案例分享 SpringBoot是一个快速开发框架,SSM是一个经典的JavaWeb开发框架,它们的整合可以让我们更加高效地进行JavaWeb开发。本文将分享一个SpringBoot整合SSM的案例,包括如何整合MyBatis和SpringMVC,并提供两个示例说明。 1. 创建SpringBoot项目 首先,我们需要创建一个…

    Java 2023年5月18日
    00
  • Java+Mysql学生管理系统源码

    Java+Mysql学生管理系统源码攻略 什么是Java+Mysql学生管理系统源码? Java+Mysql学生管理系统源码是一个基于Java编写并使用Mysql作为后台数据库的学生管理系统。 该系统使用了Java Swing编写前端GUI界面,并使用Mysql作为后台数据库,实现了登录、菜单、学生信息管理、成绩管理、教师信息管理等核心功能,是一款很好的Ja…

    Java 2023年5月20日
    00
  • JSP常见的文件操作小结

    JSP常见的文件操作小结 在JSP开发中,文件的操作是比较常见的一个任务,下面整理了关于JSP常见文件操作的攻略。 1. 文件的读取 1.1 读取文本文件 读取文本文件的方法非常简单,只需要使用Java IO库中的BufferedReader来读取文件即可。示例如下: <% String fileName = "example.txt&quo…

    Java 2023年6月15日
    00
  • java中最易犯错的特殊字符示例详解

    Java中最易犯错的特殊字符示例详解 在Java的开发过程中,有些特殊字符容易被忽略或错误使用,这会导致程序出现难以发现的错误,本文将详细介绍这些特殊字符及其正确使用方法。 转义字符 转义字符是由反斜杠()后面跟上一个特殊字符组成的。它们的作用是告诉编译器,“我不是一个普通字符,而是需要特殊处理的字符。”以下是常见的转义字符及其用途: \n:换行符 \t:制…

    Java 2023年5月27日
    00
  • tomcat6_apache2.2_ajp 负载均衡加集群实战分享

    Tomcat6、Apache2.2、AJP 负载均衡加集群实战分享 一、引言 本文将介绍如何使用Tomcat6、Apache2.2和AJP实现负载均衡加集群,并提供了两个示例进行演示。本文假设读者已经熟悉Linux基础知识,并且已经安装了Tomcat6和Apache2.2。 二、负载均衡加集群 2.1 集群模式 为了实现负载均衡加集群,我们需要将多个Tomc…

    Java 2023年5月19日
    00
  • Java 日志打印的15个好建议

    Java 日志打印的15个好建议 在Java开发中,日志是一个非常重要的工具。它可以帮助开发人员定位和解决问题。在使用日志时,遵循以下的15个好建议将会让日志发挥最大的作用。 1. 使用不同的日志级别 在Java中,常用的日志级别从低到高分别是DEBUG、INFO、WARN、ERROR、FATAL。在使用日志时,应该根据需要选择不同的日志级别。例如,在调试时…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部