【Java】泛型 常用使用方式

Java泛型:定义、使用与实战 泛型是Java SE 5.0中引入的一个新特性,它提供了编译时类型安全,减少了类型转换的代码,并提高了代码的可重用性。泛型,顾名思义,就是广泛的数据类型。在Java中,泛型允许我们在定义类、接口和方法时使用类型参数。这些类型参数在类、接口或方法被实例化时(即创建对象时)被具体的类型替换。这样,我们可以编写更加通用的代码,提高代码的可重用性。当我们需要自定义一些数据结构(如栈、队列等)时,泛型可以帮助我们编写更加通用的代码。通过使用泛型,我们可以使这些数据结构支持任意类型的元素。 阅读详情

简单学学泛型

1.前言

泛型是我们学习和工作中,接触到的常见语法糖之一。其主要作用是用于规定一些类型或者作为通配符,让我们更方便地进行类型管理与使用。泛型广泛应用于集合、工具类等。我们有必要对泛型的常用使用方式进行学习与了解。

学习目标
学习泛型相关概念并能逐步熟练使用泛型,通过使用泛型,提高代码重用性、安全性,高效率开发。

阅读本文,我们将对泛型的主要使用方式进行学习,至于更深一步的学习,请参考以下参考资料:

参考资料
菜鸟教程-Java泛型:https://www.runoob.com/java/java-generics.html

优快云-优秀参考博文:https://blog.youkuaiyun.com/weixin_45395059/article/details/126006369

2. 泛型

2.1 什么是泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是"参数化类型",也就是说所操作的数据类型被指定为一个参数。

泛型是Java中的一个重要概念,它允许我们编写可以处理各种类型数据的通用代码。泛型可以让我们在编写代码时不必关心数据类型,从而提高代码的可重用性和安全性。

泛型的一般格式:

// 其中,T代表的是引用类型
<T>

2.2 若不使用泛型

众所周知,集合是一种容器。我们在学习与使用集合的时候常常带上泛型来规定当前集合的数据类型。当我们不使用泛型的时候,集合是可以一次性装下不同类型的数据的。

我们来做个测试,首先我们定义几个用于测试的类:

创建用于测试的类

public class Animal {
    String name;
    Animal(){

    }
    Animal(String name){
        this.name = "dog";
    }
}
public class Cat extends Animal {
    private String color;

    public void voice(){
        System.out.println("mao mao");
    }
    Cat(String name){
        this.name = name;
    }
    
    Cat(){
        
    }
}
public class Car {
    private int price;

    public void move(){
        System.out.println("the car is move");
    }
}

测试不用泛型

public static void main(String[] args) {
        List miscellaneous = new ArrayList();
        miscellaneous.add(new Animal());
        miscellaneous.add(new Car());
        miscellaneous.add(new Cat());

        miscellaneous.forEach(System.out::println);
}

当不使用泛型时,显而易见,各种数据类型的数据都可以加入列表。当数据量大的时候,数据的管理将会变得异常麻烦。

2.3 如何使用泛型

泛型标记符

表记符含义
EElement,表示集合的元素
TType,表示类型。实际使用中,其实使用A、B等都可以,一般约定俗称用Type
KKey 键
VValue 值
NNumber 数值类型
?通配符,表示不确定的类型

实际使用中,由于使用方便与约定俗成的关系,我们最常用的泛型标记符还是 T和 ?

2.3.1 泛型接口

语法
在接口名后添加泛型:

interface GenericsInterface<T> {
	T method(T t);
	// other methods ...
}

作用
如果一个接口使用了泛型,那么实现该接口的类可以就可以指定类型,举个例子:

interface GenericsInterface<T> {
	/**
	 * 泛型接口演示
	 * @param t 泛型对象t
	 * @return 返回泛型对象
	 */
	T method(T t);
}
public class Cat extends Animal implements GenericsInterface<Cat> {
    private String color;

    public void voice(){
        System.out.println("mao mao");
    }

    @Override
    public Cat method(Cat cat) {
        return null;
    }
}

当我们实现泛型接口,而不指定泛型时,默认为Object:

public class Cat extends Animal implements GenericsInterface {
    private String color;

    public void voice(){
        System.out.println("mao mao");
    }

    @Override
    public Object method(Object o) {
        return null;
    }
}

2.3.2 泛型类

语法
在类名后添加泛型:

class GenericsClass<T> {
	T method(T t);
	// other methods ...
}

当我们实例化这个泛型类的对象时,就可以指定泛型了。

举例:

public class MyStack <T> {

    LinkedList<T> values = new LinkedList<>();

    public void push(T t){
        values.addLast(t);
    }

    public T pull(){
        return values.removeLast();
    }

    public T peek(){
        return values.getLast();
    }

    public static void main(String[] args) {
        MyStack<Car> carStack = new MyStack<>();
        carStack.push(new Car());
        carStack.push(new Car());
        carStack.peek();
        Car pull = carStack.pull();

        MyStack<Cat> catMyStack = new MyStack<>();
        catMyStack.push(new Cat());
        catMyStack.push(new Cat());
        catMyStack.push(new Cat());
        Cat cat = catMyStack.pull();
    }
}

2.3.3 泛型方法

语法

public <T> ReturnType methodName(Type typeName){

}

使用泛型方法的好处是可以在不同的数据类型上重用同一个方法,而不需要为每种数据类型编写重复的代码

举例
这里举一个工作中有概率用到的例子,当我们需要对一个列表进行手动分页时:

	/**
	 * @param list     分页前的集合
	 * @param pageNum  页码
	 * @param pageSize 页数
	 * @param <T> 泛型标记符
	 * @return 分页后的集合
	 */
	public <T> List<T> pageList(List<T> list, int pageNum, int pageSize) {
		//计算总页数
		int page = list.size() % pageSize == 0 ? list.size() / pageSize : list.size() / pageSize + 1;
		//兼容性分页参数错误
		pageNum = pageNum <= 0 ? 1 : pageNum;
		pageNum = pageNum >= page ? page : pageNum;
		// 开始索引
		int begin = 0;
		// 结束索引
		int end = 0;
		if (pageNum != page) {
			begin = (pageNum - 1) * pageSize;
			end = begin + pageSize;
		} else {
			begin = (pageNum - 1) * pageSize;
			end = list.size();
		}
		return list.subList(begin, end);
	}

2.3.4 类型通配符

在上面的小节中,我们提到过通配符?,相信小伙伴们肯定或多或少见过,特别是在底层源码中,用得很多。

?extends
很好理解,表示一个泛型或者其子类型,举个例子:
复用上文提到过的 Cat 类, 并让它继承 Aniaml

public class Cat extends Animal {
    private String color;

    public void voice(){
        System.out.println("mao mao");
    }
    Cat(String name){
        this.name = name;
    }
    
    Cat(){
        
    }
}
public class Test {
    public static void main(String[] args) {
        // 定义 3 个 list
        List<Cat> catList = new ArrayList<>();
        List<Car> carList = new ArrayList<>();
        List<Animal> animalList = new ArrayList<>();

        catList.add(new Cat());
        carList.add(new Car());
        animalList.add(new Cat("cat"));
        animalList.add(new Animal("dog"));

        getCars(carList);
        getAnimals(animalList);
        // 通用
        getCars(animalList);
    }

    public static void getCars(List<?> list){
        System.out.println(list.get(0));
    }

    public static void getAnimals(List<? extends Animal> list){
        System.out.println(list.get(0).name);
    }

}

? super
也很好理解,表示只能接受 该类型及上层父类类型。
这里也举一个 实际工作中可能用到的例子:

	/**
	 * 去重Predicate,filter参数
	 * @param keyExtractor 去重依据
	 * @param <T> 泛型类型
	 */
	public <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
		Map<Object,Boolean> seen = new ConcurrentHashMap<>();
		return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
	}

3. 总结

通过本文,我们简单 学习/回顾 了泛型的概念与常用方式。通过泛型,我们可以在使用集合等一些场合指定操作的数据类型,方便数据类型管理;也可以借助泛型类、泛型方法、泛型接口的特性,做一些通用工具类或工具方法,方便日常开发使用。

Java泛型:详解使用技巧及举例说明 Java泛型是一项强大的编程概念,它允许我们编写通用的代码,在编写代码时不需要预先指定具体的数据类型。泛型的引入解决了在传统的编程中需要频繁进行类型转换的问题,提高了代码的安全性和可读性。 阅读详情

相关推荐

【Java基础知识 39】Java泛型方法的定义和使用

Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

学Java,找哪吒 2万+

JAVA泛型的使用(超详细)

泛型的使用

weixin_45531755的博客 1万+

轻量级替代方案:用AIFlowy + Ollama在本地快速搭建一个可用的AI智能体平台

本文介绍了如何使用AIFlowy和Ollama在本地快速搭建轻量级AI智能体平台,涵盖从环境准备到智能体集成的全流程。通过简化部署步骤和优化性能,15分钟内即可完成搭建,适用于原型验证和小团队协作,显著提升开发效率。

weixin_29207533的博客 221

【JavaSe】高级特性篇(一) Java高级特性泛型

JavaSe·特性篇(一) 泛型 1. 泛型概述 我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。 public static void main(String[] args) { Collection coll = new ArrayList(); coll.add(...

不想当架构师的程序员不是好程序员 1028

Jetson Nano官方镜像下载&烧录

在NVIDIA Jetson Nano开发者套件上安装NVIDIA官方Ubuntu镜像

weixin_44222088的博客 8854

从亚稳态到流片失败:SpyGlass CDC在5G芯片设计中的避坑指南

本文深入探讨了在复杂5G芯片设计中,如何利用SpyGlass CDC工具构建高效的时钟域交叉验证流程,以避免因亚稳态问题导致的流片失败。文章结合实战经验,详细解析了从约束编写、时钟复位完整性检查到层次化验证和特殊场景处理的全过程,并强调了精准的检查约束是确保验证有效性的基石,旨在帮助设计团队安全跨越异步时钟域的雷区。

weixin_29168153的博客 446

java中如何使用泛型的例子

public static <T> T pop(String key, Class<T> clazz) { try { AMPRedisClient redis = new AMPRedisClient(); String data = redis.lpop(key); if ( data != null && data.length() > 0 ) { return JS

Session_s的博客 338

实战分享:如何用Dify和MaxKb实现文档智能切分与高效检索(附代码解析)

本文详细介绍了如何结合Dify和MaxKB构建文档智能切分与高效检索系统。针对传统全文检索的不足,提出了结构感知的文档切分方案,通过解析文档层级关系并构建标题链,实现了精准的章节级检索。文章包含完整的代码实现,涵盖文档解析、智能切分、向量化策略及双索引优化,并分享了性能调优和生产环境实践经验。

qsc90123456的博客 547

泛型一般有三种使用方式

泛型一般有三种使用方式:泛型类、泛型接口、泛型方法。 1.泛型类: //此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 //在实例化泛型类时,必须指定T的具体类型 public class Generic<T> { private T key; public Generic(T key) { this.key = key; } public T getKey() { return key;

li237的博客 1394

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划 前言 本人近期在工作中遇到需要对某场景下利用海康相机进行图像缺陷检测与对应路径规划。通过对海康相机示例代码进行吸收与借鉴,最终实现了对海康相机的控制,并增加HSmartWindowControl控件,实现图像的实时显示与平移缩放功能;通过listview+toolstrip实现日志显示与类型(提示、警告、错误)分类;同时自行编制算法实现对缺陷的识别以及缺陷外扩矩形范围内的路径规划。 1.日志记录 代码如下(示例):

weixin_37864926的博客 2717

《计算机网络》复试问答题总结

DNS 是一个联机分布式数据库系统,负责主机名和 IP 地址之间的转换,需要进行域名查询的机器主动发起域名解析请求,域名服务器则随时准备做出响应。域名服务器的数据库中存放着它所管辖范围的主机名和 IP 地址之间的映射表,域名服务器之间又可以相互联络和协作,以便分布在 Internet 各个域名服务器数据库中的域名都能被有效地搜索,从而实现主机名与 IP 地址的映射。为了提高解析效率,使用了域名缓存技术。在服务器、主机中设置一个专用的内存缓冲区。服务器用来存放近期解析过的域名及其对应的 IP 地址的映射。

weixin_45971154的博客 2030

常用泛型使用案例

泛型一般有三种使用方式:泛型类、泛型接口、泛型方法。 常用的通配符为: T,E,K,V,? ? 表示不确定的 java 类型 T (type) 表示具体的一个 java 类型 K V (key value) 分别代表 java 键值中的 Key Value E (element) 代表 Element 1.泛型类: //此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 //在实例化泛型类时,必须指定T的具体类型 public class Generic<T>{

weixin_43681813的博客 482

Codex 桌面端自定义模型列表为空 — 修复记录

摘要:Codex桌面端首次启动正常,但二次启动后出现中文界面且模型列表丢失。问题根源在于Electron的Chromium持久化状态损坏,导致UI渲染异常。解决方案包括:1) 将config.toml中的模型路径改为绝对路径;2) 删除损坏的状态文件.codex-global-state.json;3) 清除Chromium用户数据目录AppData\Roaming\Codex\web。验证显示修改后模型功能恢复正常,重装无效的原因是卸载未清除用户数据目录。

猿小白的博客 1156

java 方法泛型_陶贤斌详解“Java泛型”

Java泛型泛型大家都接触的不少,但是由于Java 历史的原因,Java 中的泛型一直被称为伪泛型,因此对Java中的泛型,有很多不注意就会遇到的“坑”,在这里详细讨论一下。一、什么是泛型?泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数的方式传递,类似于方法中的变量参数。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将...

weixin_39645019的博客 69

人形机器人电路板和算法分析

人形机器人电路板与算法深度剖析 电路板领域:人形机器人电子系统分为计算、驱动、感知、能源、通信五大模块。主控板采用高性能SoM(如NVIDIA Jetson AGX Orin),需满足严格电源完整性(PDN)与信号完整性(SI)要求;关节驱动板集成MCU、GaN/SiC功率器件及高精度编码器接口,采用刚柔结合PCB以适应狭小空间。挑战包括热-振可靠性(85°C/10G振动)、高密度互连(3mil线宽)及EMC兼容性。 算法领域:运动控制依赖MPC(模型预测控制)与强化学习(RL),实现实时动态平衡;感知算法

几十年资深高级架构师,技术专家的技术笔记。专注C、Java、Python、微服务、云原生、AI工程化及高并发系统分布式架构实战,分享源码剖析、性能调优与架构治理经验。 307

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java泛型(包括泛型+反射的应用)

泛型简介 Java 泛型(generics)是 JDK 5 中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说,所操作的数据类型被指定为一个参数。在创建对象或调用方法的时候才明确具体的类型。 类型擦除 正确理解泛型概念的首要前提是理解类型擦除。 更多关于类型擦除的问题,可以查看这篇文章:《Java泛型类型擦除以及类型擦除带来的问题》 什么是类型擦除? Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦

weixin_44471490的博客 529

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JAVA泛型数组ArrayList详解

泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。例如,我们并不希望为聚集String和File对象分别设计不同的类。下面来解释一下泛型数组ArrayList(泛型数组来解释一下这个原理): java没有增加泛型类之前: 在java增加泛型类之前,泛型设计是通过继承实现的。ArrayList类只维护一个Object引用的数组: public class ArrayList{ ...

qq_39429962的博客 3783

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

java 泛型枚举_java枚举泛型

有!泛型和枚举都是JDK1.5版本之后加入的新特性,泛型将程序代码的类型检查提前到了编译期间进行,枚举类型增强了程序代码的健壮性。1. 泛型在JDK1.5版本之前,如果在集合中添加了不同类型的数据,需要在程序的运行期间对类型之间的转换进行检查。例如:List arrayList=new arrayList();在arrayList中添加String类型的对象和Integer对象,但是我们定义如下一...

weixin_39580042的博客 914

Collection,泛型

今日内容:【Collection,泛型】 collection集合 迭代器 增强for循环 泛型 学习目标 能够说出集合和数组的区别 能够使用并说出Collection集合的常用功能 能够使用迭代器对集合进行取元素 能够说出集合的使用细节 能够使用存储自定义的类型 能够使用foreach循环遍历集合 能够使用泛型定义集合对象 能够理解泛型集合对象 能够理解泛型的上下限 能够阐述泛型通配符的作用 Collection集合 集合概述 前面我们已经学习过ArrayList集合了

weixin_51621893的博客 302

关于java中泛型类和泛型方法

1.先说一下泛型常用的字母    ? 表示不确定的java类型。     T 表示java类型。     K V 分别代表java键值中的Key Value。     E 代表Element。2.什么是泛型泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时...

Dream的博客 828

Java泛型

梳理Java泛型使用及实现原理

云原生Java Web领域技术博客 417

【Java杂记】泛型:泛型的三种使用方式

泛型概述: 泛型表现为一种类型,但泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数 泛型是在编译时被确定 常见通配符: ?:表示不确定的 java 类型,即可以存N种类型;即使初始化的时候指定了类型也可以存任意类型 T (type): 表示具体的一个java类型 E (element) :代表Element,与 T 意义基本无差 K V (key value): 分别代表java键值中的Key Value 可以根据使用泛型的位置分为:泛型类,泛型接口,泛型方法 参考链

A minor 4824

Java泛型详解:Java泛型集合、泛型类、泛型方法、泛型的使用

在 Java 1.5 之前没有泛型,通常需要使用强制类型转换的方式将一种数据类型转换为另一种数据类型,这种转换要求开发者对实际参数的类型具有可预知性。对于强制类型转换错误的情况,编译器可能不会提示错误,但是在运行时会出现异常,这是一个安全隐患。 为了解决这一隐患,从 Java 1.5 开始提供了泛型。泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。本节将详...

jijiangpeng的博客 7456

Java泛型使用

Java泛型使用 1. 泛型 1.1 什么是泛型,为什么引入泛型 在项目中,我们的功能代码往往要考虑之后的复用!!!这要求功能代码尽可能的支持更多类型,在不考虑泛型的情况下,如果需要更换数据类型,只能重新完成对应数据类型的功能代码。有可能出现各式各样的类型,工作是重复的!!! 这里不单单是对于功能模块的要求封装。同时需要对数据类型进行统一的约束!!!根据用户的要求对应数据类型。 Java...

LioTomcat的博客 5280

【11章Java泛型】全面解读Java泛型

【11章Java泛型:为什么要有泛型?集合中使用泛型、自定义泛型结构、在继承上的说明、通配符的使用】

小鳴人的博客 2164

java泛型详解

文章目录1 什么是范型2 实现范型构件2.1 使用Object表示范型2.2 基本类型的包装2.3 使用接口表示范型2.4 数组类型的兼容3 利用Java5范型特性时间范型构件3.1 范型类3.2 范型接口3.3 自动装箱拆箱3.4 范型的界限3.5 通配符3.5.1 <?>无界限的通配符3.5.2 <? extends T>有上限`Upper Bounds`的通配符3.5...

殷素素的博客 2453
上一篇: 【GitHub】Failed to connect to github.com port 443 的一种解决方案
下一篇: 【工具与中间件】Git 本地修改 remote 配置的几种方式
CoderSharry
博客等级 码龄4年 515粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值