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日

相关文章

  • 深入理解Java中的构造函数引用和方法引用

    深入理解Java中的构造函数引用和方法引用 在Java中,构造函数引用和方法引用是两个很重要的概念。了解这两个概念可以帮助Java程序员更好地编写代码,提高代码的质量和可读性。 构造函数引用 构造函数引用可以用来创建对象。在Java 8之前,我们通常使用匿名内部类来创建对象。例如: Runnable runnable = new Runnable() { @…

    Java 2023年5月26日
    00
  • 浅谈jsp EL表达式取值过程、page和pagecontext的区别

    下面我将详细讲解“浅谈jsp EL表达式取值过程、page和pagecontext的区别”的完整攻略,希望能对你有所帮助。 什么是EL表达式 EL表达式(Expression Language)是一个用于在JSP中获取数据的表达式语言,主要用于在JSP页面中引用和显示Java Bean中的属性值、参数、方法调用等。它的语法类似于JavaScript和PHP等…

    Java 2023年6月15日
    00
  • Spring boot项目中异常拦截设计和处理详解

    下面我将详细讲解“Spring boot项目中异常拦截设计和处理详解”。 1. 为什么需要异常拦截设计和处理 在Spring Boot项目中,错误信息的处理一般都是通过错误页面或者日志来展示,但是使用错误页面很难定位错误,而且不能对错误进行有效的处理;而仅仅使用日志记录错误信息也无法立即响应和处理错误。 因此,为了更好地处理和定位错误,我们需要在Spring…

    Java 2023年5月27日
    00
  • Java如何获取对象属性及对应值

    获取Java对象属性及对应值是Java开发中的常见操作。下面我将为您提供一份完整攻略,包含以下几个步骤: 了解Java反射机制 获取对象类的Class对象 获取对象的属性名及类型 获取对象的属性值 示例说明 接下来我们来详细讲解: 了解Java反射机制 Java反射机制是指在运行时,通过使用Java类中的反射API获取类的信息及调用类的方法,完成程序的动态操…

    Java 2023年5月26日
    00
  • 将本地SpringBoot项目发布到云服务器的方法

    将本地Spring Boot项目发布到云服务器通常需要以下步骤: 选择云服务器和操作系统:云服务器的选择需要考虑到项目规模、负载以及所在地区等因素。常见的云服务器提供商有阿里云、腾讯云、AWS等。选择操作系统时,需要根据项目的技术栈来决定,常用的操作系统有Linux、Ubuntu等。 安装Java环境:在云服务器上安装Java环境是部署Spring Boot…

    Java 2023年5月20日
    00
  • Java 关系运算符详情及案例(上)

    下面是关于“Java 关系运算符详情及案例(上)”的完整攻略。 标题 Java 关系运算符详情及案例(上) 概述 本文将详细讲解 Java 中的关系运算符,包括如何使用它们以及它们的返回值类型。此外,我们还将通过两个示例说明如何使用关系运算符。 前置知识 在阅读本文之前,您需要熟悉 Java 编程语言的基本概念和语法,包括变量、数据类型、控制流语句等。 关系…

    Java 2023年5月26日
    00
  • Flink自定义Sink端实现过程讲解

    好的。首先,讲解Flink自定义Sink端实现过程,我们需要先了解Flink中DataStream API中对于Sink的定义。 Flink中,DataStream API提供了一些内置的Sink操作,如print、writeAsText等。这些内置的Sink操作可以满足大部分常见的业务需求,但对于一些特殊的需求,我们可能需要自己实现一些自定义的Sink操作…

    Java 2023年5月20日
    00
  • Java java.lang.InstantiationException异常案例详解

    Java java.lang.InstantiationException异常案例详解 什么是 java.lang.InstantiationException 异常? java.lang.InstantiationException 是 Java 异常类的一种,通常是由于实例化一个抽象类或没有公共构造方法的类而导致的。当一个类被实例化时,Java 实际上会…

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