彻底理解java中泛型

news2025/1/24 2:30:52

一、什么是泛型?

  泛型是JDK5引入的一种特性,是一种类型安全检测机制,开发者在编译阶段发现类型相关的报错。

  泛型即参数类型化,将操作的数据类型定义为参数,可定义在类、接口、方法中。

  可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。

二、为什么有泛型?

  我们都知道java中泛型又称为“伪泛型”,为什么称为伪泛型呢?是因为泛型只存在编译阶段,编译完成之后泛型会被擦除,并没有作用在程序的执行阶段,所以他存在的目的就是“为了规范”。

1、类型安全

  泛型的主要目标是提高 Java 程序的类型安全,保证程序的可读性和安全性。

2、消除强制类型转换

  泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

3、潜在的性能收益

  泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。

三、泛型的使用

1、泛型类、泛型接口、泛型方法

public class Test<T> {

    public T test2(T params){}
}

public interface Test1<T>{}

2、泛型通配符

  比如常见的?,T,K,V 就是通配符,比如其中的T换成A-Z其中任何一个都可以,java中是讲究约定的,就是大家共同约定,某个字符代表什么意思,这样也有利于代码维护。

  • ? 表示不确定的 java 类型
  • T (type) 表示具体的一个java类型
  • K V (key value) 分别代表java键值中的Key Value
  • E (element) 代表Element

3、上界通配符(<? extends T>)

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

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

public class Test<T> {
    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
    }
}

小结:

  • 通配符上界? extends A, 表明所有的是A的类或者子类型可以传入,比如本例中的Integer和Double都是Number的子类,String不是。
  • 通配符上界? extends A,确定了类型是A或者是A的子类,那么向集合容器get获取数据,肯定是它的上界类A,因为其他放的类都是A的子类,比如例子中的 Number o = list3.get(0);
  • 如果向通配符上界集合中添加元素时,会失败。 List<? extends A>, 说明容器可以容纳的是A或者A的子类,但A的子类有很多,不确定放哪个,为了安全性,就直接不让你add,比如例子中的list3.add(5); ,5虽然是Number的子类,依然不能add。

4、下界通配符(<? super T>)

  上界通配符:用 super关键字声明,表示类型为T类型及T类型的父类

<? 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
    }
  • 通配符上界? super A, 表明所有的是A的类或者A的父类可以传入。
  • 通配符上界? super A,确定了类型是A或者是A的父类,那么向集合容器get获取数据,无法确定是A还是A的某个父类,所以不能get, Integer o = list3.get(0); // compile error,比如例子中用Integer接收,万一list3中放的是Object类型,就凉凉了。
  • 如果向通配符下界集合中添加元素时,只能添加下届类的子类。比如例子中的:list3.add(5), list3的通配符是<? super Integer>,说明该集合存放的是Integer或者Integer的子类,我只要向容器中放Integer和它的子类都是成立的。

源码中使用例子:

类Collections 中binarySearch方法 【List<? extends Comparable<? super T>> list】入参list中存储对象A或者A的父类是Comparable子类都可以。

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

可通过以下代码辅助理解 <T extends Comparable<T>> 与<T extends Comparable<? super T>>

public class Test2 {

    public static <T extends Comparable<T>> void sort1(List<T> list) {
        Collections.sort(list);
    }

    public static <T extends Comparable<? super T>> void sort2(List<T> list) {
        Collections.sort(list);
    }

    public static void t1() {
        List<Animal> animals = new ArrayList<Animal>();
        animals.add(new Animal(20));
        animals.add(new Animal(30));

        List<Dog> dogs = new ArrayList<Dog>();
        dogs.add(new Dog(5));
        dogs.add(new Dog(10));

        sort1(animals);
        // sort1(dogs); 会报错

        sort2(animals);
        sort2(dogs);
    }
}

class Animal implements Comparable<Animal> {
    public int age;
    public Animal(int age) {
        this.age = age;
    }
    public int compareTo(Animal other) {
        return this.age - other.age;
    }
}
class Dog extends Animal {
    public Dog(int age) {
        super(age);
    }
}

5、T 和 ?的区别 

  T 是一个确定的类型,通常用于泛型类和泛型方法的定义,?是一个不确定的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。

四、泛型常见面试问题 

1、泛型为什么不能使用基本数据类型

  泛型在编译阶段会进行泛型擦除,擦除为原始类型,但是object并不是基本数据类型的父类。

2、类型擦除后保留的原始类型

3、通过上下边界 通配符 解决 泛型擦除问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CorelDRAW2023中文版矢量制图及设计软件更新发布

矢量制图及设计软件&#xff0c;CorelDRAW Graphics Suite 2023中文版&#xff08;以下简称CorelDRAW 2023&#xff09;对新手来说&#xff0c;对于自己多久才能学会cdr软件这个问题是比较关心的。如果你的学习能力比较强&#xff0c;一周时间是有可能完全学会cdr的。但由于每个…

您可以找到的 5 种最佳数据恢复软件

数据恢复软件对很多人来说是一个非常有价值的工具。无论您是否意识到&#xff0c;宝贵的数据都有被删除的风险&#xff0c;而且很多人直到丢失数据才知道数据的价值。 5 种数据恢复软件 如果发生这种情况&#xff0c;您需要最好的软件来恢复数据并确保这种情况不会再次发生。这…

PostgreSQL 函数(一) 数学函数和字符串函数

1.数学函数 1.1.符号函数sign 用于判断正负 1.2.求余函数mod 1.3.圆周率函数pi 1.4.平方根函数sqrt 1.5.向上取整函数ceil和ceiling 1.6.向下取整函数floor 1.7.绝对值函数abs 1.8.四舍五入函数round 第2位参数为保留位数 1.9.其他函数 正弦函数sin, 反正弦函数asin, 余弦…

考研复试确认神操作!

终于进行到了研究生考试的尾声&#xff0c;但让考生感到无力吐槽的事情&#xff0c;却还在继续上演&#xff0c;比如苏科大&#xff0c;再比如中地大、苏大&#xff0c;三所学校的神操作&#xff0c;着实让无数考生忍不住调侃&#xff1a;原来考研不仅拼实力&#xff0c;还得拼…

类ChatGPT代码级解读:如何从零起步实现Transformer、llama/ChatGLM

前言 最近一直在做类ChatGPT项目的部署 微调&#xff0c;关注比较多的是两个&#xff1a;一个LLaMA&#xff0c;一个ChatGLM&#xff0c;会发现有不少模型是基于这两个模型去做微调的&#xff0c;说到微调&#xff0c;那具体怎么微调呢&#xff0c;因此又详细了解了一下微调代…

欧拉回路问题

文章目录 欧拉回路程序设计程序分析欧拉回路 有一条名为Pregel的河流经过Konigsberg城。城中有7座桥,把河中的两个岛与河岸连接起来。当地居民热衷于一个难题:是否存在一条路线,可以不重复地走遍7座桥。这就是著名的七桥问题。它由大数学家欧拉首先提出,并给出了完美的解答…

MapReduce简介

MapReduce是一个编程模型&#xff0c;用于处理和生成大数据。用户通过编写Map函数处理输入键值对生成中间键值对&#xff0c;通过编写Reduce函数来合并所有的中间键值对并生成结果。在我们的日常生活中&#xff0c;大部分的任务都可以被抽象成一个MapReduce模型&#xff0c;并通…

6.1 总体和样本

学习目标&#xff1a; 要学习总体和样本&#xff0c;可以按照以下步骤进行&#xff1a; 了解总体和样本的概念&#xff1a;总体是指研究对象的全体&#xff0c;样本是从总体中随机抽取的一部分。了解它们的概念有助于后续学习。 掌握简单随机抽样的方法&#xff1a;简单随机…

HTML学习(1)

文章目录HTML初识第一个HTML程序HTML元素HTML属性HTML标题HTML段落HTML样式格式化标签HTML引用HTML注释HTMLCSSHTML链接HTML图片HTML表格HTML列表HTML块我的个人博客&#xff1a;欢迎来逛逛 HTML初识 HTML全称是&#xff1a;Hyper Text Markup Language HTML不是一种编程语言…

如何在Windows系统上制作U盘启动盘?

使用U盘重装Windows电脑系统&#xff0c;对于熟悉电脑的人来说十分常见&#xff0c;但是不少电脑小白并不会制作U盘启动盘。U盘启动盘是包含操作系统的外部硬盘驱动器&#xff0c;可用于启动计算机或笔记本电脑。下面我们就来了解一下如何制作U盘启动盘。 注意&#xff1a; U …

在芯片行业,想要达到年薪百万难吗?

近两年芯片行业爆火&#xff0c;受到了方方面面的关注。新的一年新的开始&#xff0c;现在这个行业的真实情况到底如何&#xff1f;从事芯片行业有没有前途&#xff1f;下面就来具体谈一谈&#xff0c;希望能给想入高薪行业的你一些帮助。 芯片工程师为什么这么贵&#xff1f;…

ControlNet 1.1重磅发布,14个模型全部开源!

来源&#xff1a;https://github.com/lllyasviel/ControlNet-v1-1-nightly ControlNet 1.1 与 ControlNet 1.0 具有完全相同的体系结构,ControlNet 1.1 包括所有以前的模型&#xff0c;具有改进的稳健性和结果质量,并添加了几个新模型。 模型命名规则更新 从 ControlNet 1.1 开…

英汉互译在线翻译-英文翻译中文的翻译

您是否曾经遇到需要翻译英语文件&#xff0c;但被繁琐的翻译过程所拖慢了工作进度&#xff1f;或者遭遇了机器翻译的低准确率和翻译错误困扰&#xff1f;如果是这样&#xff0c;那么我们的英语翻译中文转换器将是您在这方面的最佳选择&#xff01; 我们的英语翻译中文转换器是…

CSS学习(2) - 边距与高宽 + 框模型

文章首发于&#xff1a;欢迎大佬们前来逛逛 文章目录CSS边框边框样式边框宽度边框颜色单独设置边框边框属性简写圆角边框CSS边距外边距外边距合并CSS内边距内边距与内容宽度CSS高度与宽度CSS框模型CSS边框 border 属性能够设置边框的属性&#xff0c;包括样式&#xff0c;颜色…

vscode连接Linux开发

vscode远程开发Linux项目 1、首先在vscode中下载安装 Remote SSH。 安装完成后 vscode 左侧就会出现下面的图标。 2、配置远程Linux的信息 # Read more about SSH config files: https://linux.die.net/man/5/ssh_config # Host centos # HostName 192.168.88.10 # …

14. unity粒子特效--速度、粒子环绕、力(重力、阻力、风力等)、噪音

1. 渐变速度&#xff08;Velocity over Time&#xff09; 可以分别指定x,y,z三个方向的速度&#xff0c;最终的速度是三个方向的速度合成&#xff0c;点击右侧的下拉三角&#xff0c;也可以使用曲线进行速度的控制调节&#xff0c;如下图所示&#xff1a; 2. 粒子环绕 粒子…

数据治理:1分钟教你认识和识别主数据

​我们讲元数据是企业数据管理的基石&#xff0c;主数据是企业经营运作的主体对象。一般而言&#xff0c;都是从元数据或主数据切入&#xff0c;再逐步展开数据治理的其他领域。企业数据的范围很广而且在不断的增加和演变&#xff0c;哪些数据应该作为主数据加以合理的管理&…

【JSON学习笔记】1.JSON 简介及语法

前言 本章介绍JSON及其语法。 JSON 教程 JSON: JavaScript Object Notation(JavaScript 对象表示法) JSON 是存储和交换文本信息的语法&#xff0c;类似 XML。 JSON 比 XML 更小、更快&#xff0c;更易解析。 JSON 易于人阅读和编写。 C、Python、C、Java、PHP、Go等编程…

python机器学习基础——监督学习算法之线性回归

定义 线性模型是在实践中广泛使用的一类模型&#xff0c;几十年来被广泛研究&#xff0c;它可以追溯到一百多年前。线性模型利用输入特征的线性函数 用于回归的线性模型 import mglearn import matplotlib.pyplot as pltmglearn.plots.plot_linear_regression_wave()plt.show…

使用vue实现分页

使用vue实现分页的逻辑并不复杂&#xff0c;接收后端传输过来的数据&#xff0c;然后根据数据的总数和每一页的数据量就可以计算出一共可以分成几页 我编写了一个简单的前端页面用来查询数据&#xff0c;页面一共有几个逻辑 具体的效果可以看下面的演示 下面就来看一下具体的实…