0

0

如何使用Java泛型方法

王林

王林

发布时间:2023-05-01 14:16:06

|

3162人浏览过

|

来源于亿速云

转载

泛型方法

一般定义如下,即方法的前面加了个<T>

public class FTest {
	public <T> List<T> f(T t){...};
}

三种泛型参数推断方式:

1、直接在f()前面加确定泛型

fTest.<Integer>f(xxx)

2、通过输入参数确定, 下面这个推断为Integer

int number = 0;
fTest.f(number)

3、可通过 返回值 确定

List<Integer> list = fTest.f(xxx);

Q: 下面这段代码哪里有问题? 是toString()那里吗?

public class A<T> {
	public static void  test(T t){
  		System.out.println(t.toString());  
  }
}

A:test是static方法, 因此无法感知A<T>实例里的T
需要改成
public static <T> void test(T t)

toString()那里没问题,toString就是Object的方法。

泛型参数和类型消除

Q: 泛型参数T在运行时,会变成什么?
A: 统一变成Object且不包含任何类型信息。

Q: 泛型参数T可以可以使用instanceof做比较吗?

class A<T> {
   void f(Object arg)
   if(arg instanceof T) {
	  ...
   }
}

A: 不能,编译器会报错。

Q: 泛型参数T可以进行new T()或者new T[]操作吗?
A: 不能,编译器会报错。

如何使用Java泛型方法

Q: 能调用泛型参数对象里的方法吗?

T.f();

A: 只能调用Object的方法。

Q: 可以用T做强制转化吗?

T t = (T)object;

A: 能运行, 但不会真正发生转型, 编译时会触发waring警告。

新建泛型对象时的问题

先假定有2个类, 基类Parent 和子类Child

class Parent{}
class Child extends Parent{}

回答以下问题:
Q:下面这句话有问题吗?

List<Parent> list = new ArrayList<Child>()

A:有问题,编译就错误了。 List<Parent>和ArrayList<Child>并不存在父子类的关系

Q:

List<? extends Parent> list = new ArrayList<Child>();

这个list有什么特点?

A:这个list可以调用A a = list.get(), 但是不能list.add(new Parent())

  • 原因:
    list.get()所做的操作是在返回时, 把内部的<? extend parent> 强转成parent, 是合理的,任何parent的子类都可以转成parent
    list.add(new parent())所做的操作是在输入时, 把外部的a转成内部的<? extend parent>, 这是不合理的,因为我们不知道这个parent对象可以转成哪个parent的子类。

Q:

List<? super Child> list = new ArrayList<Parent>();

这个list有什么特点?
下面谁会报错

Khroma
Khroma

AI调色盘生成工具

下载
list.add(new Child())
list.add(new Parent())
Parent a= list.get();
Child b = list.get()

A:截图如下:

如何使用Java泛型方法

  • Child c = list.get() 或者Parent p = list.get()所做的操作是在返回时, 把内部的<? super Child> 强转成外部的Parent或者child, 是不合理的, 因为编译器觉得child的父类 不一定 能转成parent或者child,所以禁止了这种行为( 比如parent的父类是object, 但object不一定就能转成parent或者child)。*list.add(new Child())所做的操作是在输入时, 把外部的child或者parent转成内部的<? super Child>, 这是合理的,因为child和parent一定能转成child的父类。

Q:

List<?> list = new ArrayList<A>();

这个list有什么特点?

A:get和add都不行,只能做remove等无返回值无输入A的操作。
PS: 注意,不是说不能调用get或add方法, 而是调用get或add时,不能使用A这个对象去操作。
即无法做add(A) 或者 A a = get(0)
但是可以做add(object) 或者Object o = get(0)
因为?可以转为Object, 但是无法转为A。

Q:下面这个代码会报错吗?

   List<Fruit> fruitList = new ArrayList<>();
   fruitList.add(new Fruit());
   List<Apple> appleList = new ArrayList<>();
   appleList.add(new Apple());
   fruitList.addAll(appleList);
   System.out.println(fruitList);

A:不会报错。会正常打印结果。

如何使用Java泛型方法

PECS原则
注意PECS原则和上面的区别!
上面之前提到的? extend或者? supert, 都是在声明对象的时候用的。
而PECS原则是用于泛型对象的方法输入参数!

假设有一个类定义如下:

public static class MyList<T> {
    List<T> list = new ArrayList<>();

    // 把输入参数塞给自己,类似于生产操作
    public void pushList(List<T> t) {
        list.addAll(t);
    }

    // 把自己的内容塞给输入参数,类似于让输入参数做消费。
    public void pollList(List<T> t) {
         t.addAll(list);
    }
}

则T就是泛型参数。

Q:下面代码能正常运行吗?

MyList<Number> myList = new MyList<>();

List<Integer> intList = new ArrayList<>();
myList.pushList(intList);

List<Object> objectList = new ArrayList<>();
myList.pollList(objectList);

A:不能正常运行, pushList和pollList都会报错

因为编译器检查后,认为 List<Integer>和List<Number>不是一个东西!

Q: 如果上文要支持pushList,应该怎么修改pushList方法的定义?
A:改成这样:

// 把输入参数塞给自己,类似于生产操作
public void pushList(List<? extends T> t) {
    list.addAll(t);
}

即编译器认为,List<Integer> 和List<? extend Number>是一个东西,允许!

Q: 如果要支持pollList,怎么修改定义?
A:

// 把自己的内容塞给输入参数,类似于让输入参数做消费。
public void pollList(List<? super T> t) {
    t.addAll(list);
}

因为是把自己的东西塞给输入参数, 而想要能塞进去,必须保证自己这个T,是输入参数的子类,反过来说,输入参数必须是T的父类,所以用super
于是编译器认为,List<Object> 和List<? super Number>是一个东西,允许!

PECS原则出自Effective Java, 注意只是一个编程建议而已!

  • 如果有一个类A,泛型参数为T

  • 如果他一般只用于接收输入容器List后,塞入自己内部的T容器, 则类A就叫生产者, 因此输入参数最好定义为<? extend T>最好, 以便能接收任何T子类的容器。

  • 如果他一般只用于接收输入容器后List, 把自己内部的T元素塞给它, 那么这个类A就叫消费者, 输入参数最好定义为<? super T>\ 最好, 以便自己的T元素能塞给任何T元素的父类容器。

    立即学习Java免费学习笔记(深入)”;

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

186

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

134

2025.11.27

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

64

2026.03.13

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

48

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

88

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

270

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

59

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

99

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

105

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 82.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号