java generics(泛型)

在定义类、接口和方法时,泛型使类型(类和接口)成为参数。与方法声明中使用的形参非常相似,类型参数为您提供了一种方法,可以用不同的输入重用相同的代码。不同之处在于形式参数的输入是值,而类型参数的输入是类型。

使用泛型有许多好处:

1、在编译时加强类型检测

通过使用泛型,可以在编译时捕获和修复类型错误,从而避免在运行时出现 ClassCastException 等类型转换异常。这提高了代码的可靠性和稳定性。

2、消除类型转换

使用泛型可以避免一些操作的强制类型转换

3、提高代码重用性

泛型可以使代码更加通用,可以编写一次代码来处理多种类型的数据。

4、提高性能

泛型是在编译时进行类型检查的,因此可以避免在运行时进行类型转换,从而提高了程序的性能。

泛型定义

泛型可以定义在类,接口和方法上。泛型使用 < >来指定泛型类型。

public class Aminal<T> {private T flag;public T getFlag() {return flag;}public Aminal(T x){this.flag = x;}public static void main(String[] args) {Aminal<String> a1 = new Aminal<>("a");Aminal<Integer> a2 = new Aminal<>(2);System.out.println(a1.getFlag());System.out.println(a2.getFlag());}
}

如上,类变量flag在class定义时候指定为泛型,在对应使用泛型变量flag的地方都需要使用泛型进行接收和传递。

常见的泛型类型标识:

E - Element(表示元素,常见于JDK的集合框架中)

K - Key(键)

V - Value(值)

N - Number(数字)

T - Type (类型)

S, U, V等 - 第2个、第3个、第4个类型

上面这些泛型类型标识只是一种约定,不会强制进行校验,你也完全可以自定义,如下

public class Fruit<XXX> {private XXX price;XXX getPrice(){return price;}void setPrice(XXX price){this.price = price;}public static void main(String[] args) {Fruit<Double> f1 = new Fruit<>();f1.setPrice(2.1d);Fruit<Integer> f2 = new Fruit<>();f2.setPrice(5);}
}

上面使用XXX来表示类型,一样可以正常编译使用。

多个泛型

定义泛型时,可以指定多个泛型类型,多个之间使用,隔开

public class Pair<K,V> {K key;V value;public Pair(K k,V v){this.key = k;this.value = v;}public static void main(String[] args) {Pair<Integer,String> pair = new Pair<>(666,"泛型");System.out.println(pair.value);}
}
泛型方法

泛型方法相比于普通方法的声明,还会在返回值前使用 < >来声明使用的泛型参数列表

public static <T> List<T> fromArrayToList(T[] a) {return Arrays.stream(a).collect(Collectors.toList());
}

这里需要主要一点类上的泛型在类方法上都可以直接使用(注意是非静态方法),不用在方法上声明。

泛型类型限定

可以限定泛型为某个类的子类或实现了某个接口,使用extends来指定父类。

public static <T extends Number> float plus(T a ,T b){
return a.floatValue() + a.floatValue();
}

如果要限定多个条件可以使用 &来连接。

<T extends Number & Comparable>
通配符限定

在泛型代码中,问号(?)被称为通配符,用来表示未知类型。通配符可以在多种情况下使用:作为参数、字段或局部变量的类型;有时作为返回类型(尽管最好的编程实践是更加具体)。通配符永远不会被用作泛型方法调用的类型参数,泛型类的实例创建,或者超类型。

通配符限定只能使用在引用类型上,是是对泛型的限定。可以限定泛型的上界和下界。

<? extends Foo>
<? super Foo> 

上界:? extends Foo表示泛型最高类型是Foo,只能是Foo及其子类。

下界:? super Foo表示泛型最低类型是Foo,只能是Foo及其父类。

无界:? 表示没有类型限制

例如:

public void printFruits(List<? extends Fruit> fruits) {for (Fruit fruit : fruits) {System.out.println(fruit);}
}

这里入参约束成Fruit的上界,也就是入参只能是实现了Fruit接口的类,这样在方法体中就可以调用Fruit接口统一的方法来完成逻辑操作。这里一定要理解 ?extends和 T extends的区别。?extends是针对引用类型,也就是实际参数,而T extends是方法或类的定义上

类型擦除(Type Erasure)

Java 中的泛型在编译时会进行类型擦除(Type Erasure)。类型擦除是 Java 泛型实现的一种机制,它允许你在编译时使用泛型类型(也就是在编码是进行检测),但在运行时使用的是原始类型。在编译时,泛型类型参数被擦除并替换为其边界或 Object 类型。

验证泛型擦除可以使用反射来操作class。

如下定义类

public class ErasureTest<T,X extends Number> {T t;X x;public void setT(T t){this.t = t;}    
}

通过反射打印类信息:

Class c = ErasureTest.class;
for (Field field : c.getDeclaredFields()) {System.out.println(field.getName()+":"+field.getType());
}
for (Method method : c.getDeclaredMethods()) {System.out.println(method.getName()+":");Class[] params = method.getParameterTypes();for (int i = 0; i < params.length; i++) {System.out.println("参数"+params[i].getName()+",类型:"+params[i].getTypeName());
}
/**
输出内容:
t:class java.lang.Object
x:class java.lang.Number
setT:
参数java.lang.Object,类型:java.lang.Object
*/

这里可以看到X extends Number转换成了其上界Number,T转换成了其原始类型Object。

擦除带来的问题

由于擦除,通过反射在对方法进行调用时可以跳过类型约束:

List<String> list = new ArrayList<>();
list.add("haha");
Method addMethod = list.getClass().getDeclaredMethod("add", Object.class);
addMethod.invoke(list,Integer.valueOf(1));
System.out.println(list);

如上代码,定义了一个String型的list,但是我们通过反射成功的往list添加了一个Integer类型的,上面的代码可以正常执行。这就可以绕过泛型限定。

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

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

相关文章

Elasticsearch7.17.7操作geo_point类型数据

目前使用的elasticsearch版本是7.17.7 有一个index&#xff0c;其中mapping的内容如下&#xff1a; {"city" : {"aliases" : { },"mappings" : {"properties" : {"city" : {"type" : "keyword"},"…

嵌入式学习 Day 29

函数: 1.函数的定义 2.函数的调用 3.函数的声明 1.函数传参: 1.赋值传递&#xff08;复制传递&#xff09; 函数体内部想要使用函数体外部变量值的时候使用复制传递 2.全局变量传递 3.地址传递 函数体内部想要修改函数体外部变量值的时候使用地址传递 函数…

代码随想录算法训练营第48天| Leetcode 121. 买卖股票的最佳时机、Leetcode 122.买卖股票的最佳时机II

文章目录 Leetcode 121. 买卖股票的最佳时机Leetcode 122.买卖股票的最佳时机II Leetcode 121. 买卖股票的最佳时机 题目链接&#xff1a; Leetcode 121. 买卖股票的最佳时机 题目描述&#xff1a; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股…

W5300驱动说明

W5300是一款带有硬件协议栈的网络芯片&#xff0c;内部拥有128K的缓存&#xff0c;最大支持8路socket通信&#xff0c;与MCU之间通过16位数据总线通信&#xff0c;通信速度远超W5500之类以SPI作为通信接口的网络芯片&#xff0c;特别适合对高速网络传输有需求的应用。 本次使用…

使用 helm repo add istio添加了一个helm chart repo,如何查看istio的版本呢

1. 添加chart repo helm repo add istio https://istio-release.storage.googleapis.com/charts helm repo update2. 查看版本 helm search repo istio 3. 查看版本详细信息 helm show chart istio/cni 4. 查看某个chart的历史版本 helm search repo <chart-name> --…

【Linux】信号的保存

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 信号在Linux中的保存主要涉及方面 信号的类型&#xff1a; 信号处理程序&#xff1a; 信号的传递和处理&#xff1a; 信号的阻…

面试官:你用过Collections工具类吗?

Collections工具类 1. 常用的 Collections 方法2. 代码示例 Java中的 Collections 工具类提供了一系列静态方法&#xff0c;用于对集合进行各种操作&#xff0c;如排序、查找、替换等。下面我们来看一些 Collections 工具类中常用的API和使用示例。 1. 常用的 Collections 方…

回溯算法套路③排列型回溯+N皇后【基础算法精讲 16】

46 . 全排列 链接 : . - 力扣&#xff08;LeetCode&#xff09; 思路 : 那么怎么确定选了那个数呢? 这里设置一个used表示i选没选过 ; class Solution { public:vector<vector<int>> ans;vector<int> path;void backtrack(vector<int>nums,vect…

2024年【天津市安全员B证】考试内容及天津市安全员B证实操考试视频

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 天津市安全员B证考试内容根据新天津市安全员B证考试大纲要求&#xff0c;安全生产模拟考试一点通将天津市安全员B证模拟考试试题进行汇编&#xff0c;组成一套天津市安全员B证全真模拟考试试题&#xff0c;学员可通过…

《Improving Calibration for Long-Tailed Recognition》阅读笔记

论文标题 《Improving Calibration for Long-Tailed Recognition》 改进长尾识别的校准工作 作者 Zhisheng Zhong、 Jiequan Cui、Shu Liu 和 Jiaya Jia 香港中文大学和 SmartMore 初读 摘要 深度神经网络在训练数据集类别极度不平衡时可能会表现不佳。最近&#xff0c…

pydub、playsound播放声音;gradio、streamlit页面播放声音;gradio 页面图像、视频及调用摄像头

1、pydub from pydub import AudioSegment from pydub.playback import playsong AudioSegment.from_wav(r"C:\Users\loong\Downloads\zh.wav") play(song)2、playsound from playsound import playsoundplaysound(r"voice.wav")3、streamlit import s…

Linux学习:初识Linux

目录 1. 引子&#xff1a;1.1 简述&#xff1a;操作系统1.2 学习工具 2. Linux操作系统中的一些基础概念与指令2.1 简单指令2.2 ls指令与文件2.3 cd指令与目录2.4 文件目录的新建与删除指令2.5 补充指令1&#xff1a;2.6 文件编辑与拷贝剪切2.7 文件的查看2.8 时间相关指令2.9 …

22.基于springboot + vue实现的前后端分离-汽车票网上预定系统(项目 + 论文PPT)

项目介绍 系统是一个B/S模式系统&#xff0c;采用Spring Boot框架&#xff0c;MySQL 数据库设计开发&#xff0c;充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得汽车票网上预订系统管理工作系统化、规范化。本系统的使用使管理人…

JavaScript作用域及预解析

文章目录 1. 作用域介绍2. 变量的作用域*3. JS中没有块级作用域4. 作用域链5. 预解析预解析案例 1. 作用域介绍 全局作用域局部作用域相同的变量名称在不同的作用域中是不会相互影响的&#xff01; 2. 变量的作用域 全局变量&#xff1a;在全局下都可以使用&#xff1b;局部变…

蓝桥杯——外卖店优先级

外卖店优先级 题目分析 这一题一看N&#xff0c;M&#xff0c;T的范围就知道不能暴力&#xff0c;要讨巧&#xff0c;怎么讨巧是重点。正常的思路是第一层for循环遍历订单&#xff08;或者外卖店&#xff09;&#xff0c;第二层for循环遍历外卖店&#xff08;或者订单&#x…

Vue中 computed 和 watch

在Vue框架中&#xff0c;computed和watch都用于响应数据的变化&#xff0c;但它们在使用上有着不同的侧重点和机制。具体分析如下&#xff1a; 1. 功能差异 computed是计算属性&#xff0c;它是基于它们的响应式依赖进行缓存的。只有当依赖的数据发生变化时&#xff0c;compu…

2827. 范围中美丽整数的数目

文章目录 题意思路代码 题意 题目链接 思路 按位dp暴力 代码 // 暴力 class Solution { public:int numberOfBeautifulIntegers(int low, int high, int k) {int l low / k;int r high / k;if (low % k)l;int ans 0;while (l < r){int tmp l * k;if (10 < tmp &…

华为数通方向HCIP-DataCom H12-821题库(多选题:61-80)

第61题 ACL 可分为如下哪些类别? A.用户自定义 ACL B.基本 ACL C.二层ACL D.高级ACL 【参考答案】ABCD 【答案解析】 A. 用户自定义 ACL (User-defined ACL): 这是用户根据自身需求自定义的 ACL,用于实现特定的访问控制策略。B.基本 ACL (Standard ACL): 基本 ACL 是基于源 …

OCP Secure boot必要特性

三点必需要求&#xff1a; The platform components must: 1. Provide a mechanism for securely anchoring a root of trust public key. // 提供一种用于安全地锚定信任根公钥的机制。 2. Verify the device firmware digital signature using the anchored public key /…

北京大学发布,将试错引入大模型代理学习!

引言&#xff1a;探索语言智能的新边界 在人工智能的发展历程中&#xff0c;语言智能始终是一个核心的研究领域。随着大语言模型&#xff08;LLM&#xff09;的兴起&#xff0c;我们对语言智能的理解和应用已经迈入了一个新的阶段。这些模型不仅能够理解和生成自然语言&#x…