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

yizhihongxing

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日

相关文章

  • Java 内存溢出的原因和解决方法

    Java 内存溢出的原因和解决方法 Java 内存溢出是 Java 开发中常见的问题之一,当程序运行需要的内存超过了 JVM 分配给程序的内存时,就会发生内存溢出的问题。本文将详细介绍 Java 内存溢出的原因和解决方法,以及两个示例说明。 常见内存溢出的原因 1. 对象无法被合理的回收 在 Java 中,内存的回收是通过垃圾回收机制(GC)实现的。当对象引…

    Java 2023年5月26日
    00
  • SpringBoot3整合MyBatis出现异常:Property ‘sqlSessionFactory’or ‘sqlSessionTemplate’ are required

    Spring Boot是目前非常受欢迎的开发框架,而MyBatis是一款优秀的数据库ORM框架,二者结合可以让我们开发高效率、高质量的Web应用。不过在整合Spring Boot和MyBatis的时候,有时候会遇到”Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”异常,那么该…

    Java 2023年5月20日
    00
  • Java中Lambda表达式用法介绍

    Java中Lambda表达式用法介绍 Lambda表达式简介 Lambda表达式是Java8中引入的一种新的语法特性,简化了匿名函数的实现方式。使用Lambda表达式语法可以使代码更加简洁、易读。Lambda表达式是一个匿名函数,它没有名称、修饰符以及返回类型。Lambda表达式的主要功能是用来定义匿名内部类的实例。 Lambda表达式适用于函数式接口,函数…

    Java 2023年5月26日
    00
  • 手撸一个Spring Boot Starter并上传到Maven中央仓库

    手撸一个Spring Boot Starter并上传到Maven中央仓库,可以大致分成以下步骤: 一、准备工作 1. 创建一个Maven项目 在本地创建一个Maven项目,包含一个POM文件和一个src目录。可以使用Eclipse、IntelliJ IDEA等开发工具,也可以手工创建。 2. 引入相关依赖 在POM文件中引入Spring Boot和相关依赖,…

    Java 2023年5月19日
    00
  • 关于在Java中反转数组的4种详细方法

    针对“关于在Java中反转数组的4种详细方法”,我可以给出以下几种方式: 1. 使用for循环逆序遍历数组 public static void reverseWithForLoop(int[] arr) { int len = arr.length; for (int i = len – 1; i >= len / 2; i–) { int tem…

    Java 2023年5月26日
    00
  • 详解Java合并数组的两种实现方式

    详解Java合并数组的两种实现方式 在Java中,合并数组是一个常见的操作,本文将介绍Java中合并数组的两种实现方式。 一、使用System.arraycopy()方法 Java中提供了System.arraycopy()方法来实现数组的复制和合并。以下是合并数组的示例代码: public static int[] mergeArrays(int[] ar…

    Java 2023年5月26日
    00
  • Java Collections.shuffle()方法案例详解

    Java Collections.shuffle()方法案例详解 在 Java 中,通常我们需要对数据集合进行一些元素的顺序处理,例如给一个列表的元素混淆顺序。Java Collections Framework 提供了许多工具类来帮助我们处理各种集合对象。其中,Collections 类拥有许多静态方法,其中 shuffle() 方法就是一种非常有用的工具…

    Java 2023年5月26日
    00
  • Springboot集成kafka高级应用实战分享

    为了让大家更好地理解 Springboot 集成 kafka 的应用,我将分别从以下几个部分展开: 环境准备 Springboot 集成 kafka 配置 生产者示例 消费者示例 1. 环境准备 首先需要确保已经正确安装了 Kafka,JDK和 Maven。然后在 pom.xml 文件中引入 Kafka client 相关依赖: <dependenci…

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