泛型的上界

简介: 泛型的上界

一、泛型的上界
class Myclass<类型参数 extends 类型上界> {

}
1
2
3
类型的上界决定了泛型的范围。

class MyArray {

}
public static void main(String[] args) {

    MyArray<Integer> myArray = new MyArray<>();
    MyArray<Boolean> myArray1 = new MyArray<Boolean>();
}

1
2
3
4
5
6
7

我们发现指定了泛型的上界为数值类Number时,传入Boolean类型就会报错。
如果没有指定类型的边界,可以认可 T extends Object,当指定了某个类型为上界,那么只接受某类型本身和子类型作为E的类型实参

上界为接口
我们要实现一个类去找数组的一个的最大值

这里报错了,因为我们这里是Object类型,如果是类型实参是对象的话不就能这样比较了,所以我们将上界定为Comparable接口。

class MyArray> {

public T findMax(T[] arr) {
    T max = arr[0];
    for (int i = 1; i < arr.length - 1; i++) {
        if (arr[i].compareTo(max) > 0) {
            max = arr[i];
        }
    }
    return max;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
我们来求一个Integer类型的最大值。

public static void main(String[] args) {

    MyArray<Integer> myArray = new MyArray<>();
    Integer[] arr = {1,4,6,3,2};
    System.out.println(myArray.findMax(arr));
}

1
2
3
4
5

我们来求一个Person类的最大值。

我们发现使用Person作为类型实参,未法创建对象,因为我们将泛型上界设置为了实现了Comparable的类类型。

class Person implements Comparable{

public int age;

public Person(int age) {
    this.age = age;
}

@Override
public int compareTo(Person o) {
    return this.age - o.age;
}

@Override
public String toString() {
    return "Person{" +
            "age=" + age +
            '}';
}

}
public static void main(String[] args) {

    MyArray<Person> myArray = new MyArray<>();
    Person[] per = {new Person(15),new Person(18),new Person(20)};
    System.out.println(myArray.findMax(per));
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

二、泛型方法
1 静态方法
刚刚我们实现的求某个类型数组的最大值必须得创建一个对象,那我们可以不创建对象直接调用吗?

我们直接给方法加上static时,系统报错了,因为static方法是在类加载指定,擦除机制是在编译时检查和强制转换,在类加载时,并不知道是什么类型,所以不能直接加static。
静态方法语法:

public static<泛型形参> T findMax(T[] arr)
1
class MyArray {

public static<T extends Comparable<T>>  T findMax(T[] arr) {
    T max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i].compareTo(max) > 0) {
            max = arr[i];
        }
    }
    return max;
}

}
public static void main(String[] args) {

    Integer[] arr = {1,5,4,7,9,2};
    Integer max = MyArray.findMax(arr);
    System.out.println(max);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

这样我们就可以不依赖对象求出最大值了,那类型实参在那里传?

一般在引用点的后面,一般可以省略。

2 普通方法
静态方法语法:

public <泛型形参> T findMax(T[] arr)
1
class MyArray {

public <T extends Comparable<T>>  T findMax(T[] arr) {
    T max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i].compareTo(max) > 0) {
            max = arr[i];
        }
    }
    return max;
}

}
public static void main(String[] args) {

    Integer[] arr = {1,5,4,7,9,2};
    MyArray myArray = new MyArray();
    System.out.println(myArray.findMax(arr));
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

三、通配符
什么是通配符:? 用于在泛型的使用

1 通配符的引入
class Data {

public T data;

public T getData() {
    return data;
}

public void setData(T data) {
    this.data = data;
}

}
public static void main(String[] args) {

    Data<Integer> data = new Data<>();
    data.setData(18);
    print(data);
}
public static void print(Data<Integer> data) {
    System.out.println(data.getData());
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

如果我们想输入类型实参为String类型呢?重写一个方法吗?支持重载吗?

我们当写入两种不同泛型类型的方法时,系统报错了,因为在运行阶段是没有泛型这个概念的,相当于他们的类型都是Data类型。
我们来验证一下,打印两种不同泛型实参类型的对象:

public static void main(String[] args) {

    Data<Integer> data = new Data<>();
    Data<String> data1 = new Data<>();
    System.out.println(data);
    System.out.println(data1);
}

1
2
3
4
5
6

我们发现打印出来对象的类型是一样的。

相关文章
|
机器学习/深度学习 PyTorch 算法框架/工具
Pytorch CIFAR10图像分类 Swin Transformer篇(一)
Pytorch CIFAR10图像分类 Swin Transformer篇(一)
|
Linux Shell
在Linux中如何一次性运行多个命令?
在Linux中如何一次性运行多个命令?
938 0
|
Web App开发 JavaScript 前端开发
ChatGPT与基于GUI的自动化测试
ChatGPT与基于GUI的自动化测试,chrome浏览器+ cypress +HTML代码需要主机名脚本语言和测试目标的URL。
212 10
|
人工智能 搜索推荐 UED
还没排上SearchGPT?比Perplexity更好用的国产开源平替了解一下?
【8月更文挑战第24天】近日发布的一项研究成果提出了一种革新性的信息检索系统——MindSearch,该系统通过模仿人脑思维方式,有效解决了传统信息检索方法面对复杂查询时的不足。MindSearch利用多代理框架,将用户查询拆解成子问题逐步扩展查询图谱,实现复杂查询的精准定位;通过多层次信息检索,整合不同网页中的相关数据,提高信息提取的准确率;并且能高效处理大规模网页,3分钟内即可检索300多个网页。实验显示,MindSearch不仅提升了响应的深度与广度,还在封闭及开放式问答中表现出色,更符合用户的偏好。不过,MindSearch仍面临查询意图理解、噪音处理及可扩展性等方面的挑战。
228 4
|
设计模式 测试技术
《怎样实现代码的可维护性和可扩展性》
实现代码的可维护性和可扩展性,需关注命名与注释、遵循编程规范、模块化设计、应用设计模式、编写单元测试、使用版本控制、文档化及定期重构等方面。这些措施有助于提升代码质量,促进团队协作,确保项目长期健康发展。
386 12
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的全量日志文件
MySQL全量日志记录所有操作的SQL语句,默认禁用。启用后,可通过`show variables like %general_log%检查状态,使用`set global general_log=ON`临时开启,执行查询并查看日志文件以追踪SQL执行详情。
215 4
|
人工智能 调度 算法框架/工具
【AI系统】计算图的调度与执行
深度学习训练过程涉及前向计算、计算损失及更新权重参数。AI框架通过计算图统一表示训练过程,算子作为计算图的节点,由后端硬件高效执行。计算图调度包括算子间的调度、并发调度和异构调度,确保计算资源的有效利用。图执行模式分为单算子执行、整图下沉执行和图切分多设备执行,适应不同场景需求。以PyTorch为例,其算子执行通过两次调度选择合适的Kernel进行张量操作,并支持自动求导。
562 5
|
IDE Java 数据库连接
Lombok注解大全
这些是Lombok中的一些常见注解,它们可以显著减少Java代码中的冗余代码,提高代码的可读性和可维护性。不过,在使用Lombok之前,请确保你的开发环境已经配置好支持Lombok,通常需要安装相应的插件或进行设置以使IDE(如Eclipse、IntelliJ IDEA)能够正确解析Lombok注解。
230 4
|
JavaScript Java 测试技术
基于SpringBoot+Vue的城市公交调度系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的城市公交调度系统的详细设计和实现(源码+lw+部署文档+讲解等)
198 5
|
消息中间件 Java Linux
Linux Docker 安装方法
Linux Docker 安装方法
455 1