Java 方法前面加 <T> 是做什么?泛型方法 原理、样例

在 Java 中,方法前面加上 <T> 表示该方法是一个泛型方法泛型方法允许你在方法签名中指定一个或多个类型参数,从而使得该方法可以处理多种类型的对象。这增加了代码的灵活性和复用性。

一、基本语法

<T1, T2, ..., Tn> 返回类型 方法名(形参列表) {// 方法体
}
  • <T1, T2, ..., Tn>:类型参数列表,可以有一个或多个类型参数。
  • 返回类型:方法的返回类型,可以是具体的类型,也可以是类型参数。
  • 方法名:方法的名称。
  • 形参列表:方法的参数列表,可以使用类型参数作为参数类型。

 二、代码示例

1. 单个类型参数的泛型方法

 假设现在富士康(Foxconn)要生产一批手机,它给手机厂商定下了一个规范:

package com.study.genericity.entity;/*** 富士康的手机生产规范*/
public abstract class MobilePhone {abstract void produce();
}

 OPPO、Huawei 都按照 富士康 的规范(extends MobilePhone)生产手机:

package com.study.genericity.entity;
import lombok.AllArgsConstructor;@AllArgsConstructor
public class OPPO extends MobilePhone {/** 型号 */private String model;/** 颜色 */private String color;/** 运行内存 */private String ram;/** 存储 */private String rom;@Overridepublic void produce() {System.out.println("正在生产 OPPO手机 :型号-"+model+" 颜色-"+color+" 运行内存-"+ram+" 存储容量-"+rom);}
}
----------------------------------------
package com.study.genericity.entity;
import lombok.AllArgsConstructor;@AllArgsConstructor
public class Huawei extends MobilePhone {/** 型号 */private String model;/** 颜色 */private String color;/** 是否折叠 */private boolean foldOrNot;/** 运行内存 */private String ram;/** 存储 */private String rom;@Overridepublic void produce() {String description = "正在生产 华为手机 :"+(foldOrNot?"折叠屏 ":"")+model+" "+color+" "+ram+" "+rom;System.out.println(description);}
}

 富士康 为他们开了一条通用生产线生产手机:

package com.study.genericity.entity;public class Foxconn {/** 富士康通用生产线 */public static void produce(MobilePhone mobilePhone) {mobilePhone.produce();}public static void main(String[] args) {OPPO oppo = new OPPO("Find X7", "白日梦想家", "12GB", "256GB");produce(oppo);Huawei huawei = new Huawei("Pocket 2", "洛可可白", true, "12GB", "256GB");produce(huawei);}
}
输出:
正在生产 OPPO手机 :型号-Find X7 颜色-白日梦想家 运行内存-12GB 存储容量-256GB
正在生产 华为手机 :折叠屏 Pocket 2 洛可可白 12GB 256GB

 这个时候来了苹果,他们委托 富士康 生产新版 iPhone。

不过苹果 它财大气粗,它有自己的手机生产规范:

package com.study.genericity.entity;/*** 苹果自己的移动产品生产规范*/
public abstract class AppleMobile {abstract void producePhone();
}
----------------------------------------
package com.study.genericity.entity;import lombok.AllArgsConstructor;@AllArgsConstructor
public class Apple extends AppleMobile {/** 型号 */private String model;/** 颜色 */private String color;/** 运行内存 */private String ram;/** 存储 */private String rom;@Overridepublic void producePhone() {System.out.println("正在生产 尊贵的iPhone :"+model+" "+color+" "+ram+" "+rom);}
}

 富士康 本来想拒绝,因为苹果的生产流程已经继承了 AppleMobile 规范, 无法再继承 MobilePhone 规范,两个规范并不兼容(Java 单继承)。但如果为苹果单开一条生产线,成本又特别高昂。

package com.study.genericity.entity;public class Foxconn {/** 富士康通用生产线 */public static void produce(MobilePhone mobilePhone) {mobilePhone.produce();}/** 为苹果单开一条流水线 */public static void produce(AppleMobile appleMobile) {appleMobile.producePhone();}public static void main(String[] args) {OPPO oppo = new OPPO("Find X7", "白日梦想家", "12GB", "256GB");produce(oppo);Huawei huawei = new Huawei("Pocket 2", "洛可可白", true, "12GB", "256GB");produce(huawei);Apple apple = new Apple("iPhone 16 Pro", "白", "16GB", "128GB");produce(apple);}
}
输出:
正在生产 OPPO手机 :型号-Find X7 颜色-白日梦想家 运行内存-12GB 存储容量-256GB
正在生产 华为手机 :折叠屏 Pocket 2 洛可可白 12GB 256GB
正在生产 尊贵的iPhone :iPhone 16 Pro 白 16GB 128GB

 这可愁坏了 富士康 的老总,这个时候,聪明的工程师 小林 为老板想了一个办法,他用 泛型方法 的方式,定义了一条通用的流水线,可以忽略类型规范:

package com.study.genericity.entity;import java.util.function.Consumer;public class Foxconn {/** 用 泛型方法 定义通用生产流水线 */public static <T> void produce(Consumer<T> consumer, T phone) {consumer.accept(phone);}public static void main(String[] args) {OPPO oppo = new OPPO("Find X7", "白日梦想家", "12GB", "256GB");produce(OPPO::produce, oppo);Huawei huawei = new Huawei("Pocket 2", "洛可可白", true, "12GB", "256GB");produce(Huawei::produce, huawei);Apple apple = new Apple("iPhone 16 Pro", "白", "16GB", "128GB");// 苹果 定制化生产produce(Apple::producePhone, apple);}
}
输出:
正在生产 OPPO手机 :型号-Find X7 颜色-白日梦想家 运行内存-12GB 存储容量-256GB
正在生产 华为手机 :折叠屏 Pocket 2 洛可可白 12GB 256GB
正在生产 尊贵的iPhone :iPhone 16 Pro 白 16GB 128GB

富士康 老板高兴坏了,因为这条流水线太好用,老板甚至放弃了自定义的手机生产规范 MobilePhone,给手机厂商更高的自由度(不用再继承 MobilePhone),去生产定制化的手机产品:

package com.study.genericity.entity;
import lombok.AllArgsConstructor;@AllArgsConstructor
public class Huawei {/** 型号 */private String model;/** 颜色 */private String color;/** 是否折叠 */private boolean foldOrNot;/** 运行内存 */private String ram;/** 存储 */private String rom;/** 定制化生产 */public void produceHuawei() {String description = "正在生产 华为手机 :"+(foldOrNot?"折叠屏 ":"")+model+" "+color+" "+ram+" "+rom;System.out.println(description);}
}
---------------------------------------------
package com.study.genericity.entity;
import lombok.AllArgsConstructor;@AllArgsConstructor
public class OPPO {/** 型号 */private String model;/** 颜色 */private String color;/** 运行内存 */private String ram;/** 存储 */private String rom;/** 定制化生产 */public void produceOPPO() {System.out.println("正在生产 OPPO手机 :型号-"+model+" 颜色-"+color+" 运行内存-"+ram+" 存储容量-"+rom);}
}
---------------------------------------------
package com.study.genericity.entity;import java.util.function.Consumer;public class Foxconn {/** 用 泛型方法 定义通用生产流水线 */public static <T> void produce(Consumer<T> consumer, T phone) {consumer.accept(phone);}public static void main(String[] args) {OPPO oppo = new OPPO("Find X7", "白日梦想家", "12GB", "256GB");// OPPO 定制化生产produce(OPPO::produceOPPO, oppo);Huawei huawei = new Huawei("Pocket 2", "洛可可白", true, "12GB", "256GB");// 华为 定制化生产produce(Huawei::produceHuawei, huawei);Apple apple = new Apple("iPhone 16 Pro", "白", "16GB", "128GB");// 苹果 定制化生产produce(Apple::producePhone, apple);}
}
输出:
正在生产 OPPO手机 :型号-Find X7 颜色-白日梦想家 运行内存-12GB 存储容量-256GB
正在生产 华为手机 :折叠屏 Pocket 2 洛可可白 12GB 256GB
正在生产 尊贵的iPhone :iPhone 16 Pro 白 16GB 128GB

2、返回类型也是泛型的泛型方法

 输入:

一个列表,和 几个数据。

输出:

数据包含在 列表 中的一个新的列表。

示例:

输入 [2,5,7,9,10] 和 5,27 输出 [5]

输入 ["福建", "江西", "浙江"] 和 "江苏","福建" 输出 ["福建"]

 一种 泛型方法 的实现:

package com.study.genericity.entity;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class Test {@SafeVarargspublic static <T> List<T> filter(List<T> list, T... args) {List<T> result = new ArrayList<T>();for (T t : args) {if (list.contains(t)) {result.add(t);}}return result;}public static void main(String[] args) {List<Integer> list1 = Arrays.asList(2,5,7,9,10);System.out.println( filter(list1, 5, 27) );List<String> list2 = Arrays.asList("福建", "江西", "浙江");System.out.println( filter(list2, "江苏", "福建") );}
}
输出:
[5]
[福建]

 在这个例子中,filter 方法是一个泛型方法,它的入参是类型参数<T>的 泛型列表 List<T> 和 类型参数<T>的可变参数;它的返回类型还是 类型参数<T>的 泛型列表 List<T>。

这种返回类型也是泛型的泛型方法,在很多框架中都有大量的使用。

比如 cn.hutool.json.JSONUtil :

// 根据 JSON 字符串和 bean Class 类型,解析 JSON 数据 为 指定类型
public static <T> T toBean(String jsonString, Class<T> beanClass) {return toBean(parseObj(jsonString), beanClass);
}

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

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

相关文章

pytorch搭建神经网络(手搓方法)

假如我们有一个数据集形状为(348,14)。即有348个记录&#xff0c;每个记录有14个特征值。 我们想要搭建一个如下的神经网络&#xff1a; import torch import numpy as np# 创建数据集: 每个样本有14个特征 x_train np.array([[0.5, -1.2, 0.3, 0.8, 1.0, -0.5, 2.3, 1.2, -0…

基于单片机汽车尾灯控制系统

**单片机设计介绍&#xff0c;基于单片机汽车尾灯控制系统设计 文章目录 前言概要设计思路 软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、…

【Kubernetes】常见面试题汇总(五十一)

目录 114. K8S 集群服务访问失败&#xff08;情况一&#xff09;&#xff1f; 115. K8S 集群服务访问失败&#xff08;情况二&#xff09;&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff…

探索未来:hbmqtt,Python中的AI驱动MQTT

文章目录 **探索未来&#xff1a;hbmqtt&#xff0c;Python中的AI驱动MQTT**1. 背景介绍2. hbmqtt是什么&#xff1f;3. 安装hbmqtt4. 简单的库函数使用方法4.1 连接到MQTT服务器4.2 发布消息4.3 订阅主题4.4 接收消息4.5 断开连接 5. 应用场景示例5.1 智能家居控制5.2 环境监测…

3 个简单的微分段项目

与许多大型网络安全项目一样&#xff0c;微分段似乎很复杂、耗时且成本高昂。 它涉及管理有关设备间服务连接的复杂细节。 一台 Web 服务器应连接到特定数据库&#xff0c;但不连接到其他数据库&#xff0c;或者负载平衡器应连接到某些 Web 服务器&#xff0c;同时限制与其他…

鸿蒙网络管理模块01——HTTP与WebSocket请求数据

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 1、概述 鸿蒙的网络管理模块主要提供以下功能&#xff1a; HTTP数据请求&#xff1…

信息学奥赛复赛复习09-CSP-J2020-03表达式求值前置知识点-中缀表达式求值、模运算、模运算性质、栈

PDF文档回复:20241002 **1 P1981 [NOIP2013普及组] 表达式求值 ** [题目描述] 给定一个只包含加法和乘法的算术表达式&#xff0c;请你编程计算表达式的值 [输入格式] 一行&#xff0c;为需要你计算的表达式&#xff0c;表达式中只包含数字、加法运算符 “” 和乘法运算符 …

Stream流的中间方法

一.Stream流的中间方法 注意1&#xff1a;中间方法&#xff0c;返回新的Stream流&#xff0c;原来的Stream流只能使用一次&#xff0c;建议使用链式编程 注意2&#xff1a;修改Stream流中的数据&#xff0c;不会影响原来集合或者数组中的数据 二.filter filter的主要用法是…

SpringCloud-基于Docker和Docker-Compose的项目部署

一、初始化环境 1. 卸载旧版本 首先&#xff0c;卸载可能已存在的旧版本 Docker。如果您不确定是否安装过&#xff0c;可以直接执行以下命令&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logro…

十一不停歇-学习ROS2第一天 (10.2 10:45)

话题通信 1.1 发布第一个节点&#xff1a; import rclpy #导入此类模块 rcl类型 from rclpy.node import Node #从这个子模块中导入这类函数 def main(): #定义这个函数 rclpy.init() #使用初始化函数 node Node(hello_python) 将类函数里面的内容调给…

基于SpringBoot原创歌曲分享平台设计与实现

1.1课题背景 随着科学技术发展&#xff0c;电脑已成为人们生活中必不可少的生活办公工具&#xff0c;在这样的背景下&#xff0c;网络技术被应用到各个方面&#xff0c;为了提高办公生活效率&#xff0c;网络信息技术飞速发展。在这样的背景下人类社会进入了全新的信息化的时代…

【CT511N-A(T0)大夏龙雀4G模块】GPS定位实操和各个参数解释(详细简单,一看就懂)

总览 1.前言 2.硬件软件需求 3.具体操作 3.1 重置&&冷启动&#xff08;重要&#xff09; 4.注意事项&#xff08;重要&#xff01;重要&#xff01;&#xff09; &#xff01;&#xff01;&#xff01;警告&#xff01;&#xff01;&#xff01; &#xff01;&#x…

信息安全实验2

文件链接&#xff1a; 通过网盘分享的文件&#xff1a;信息安全实验2 链接: https://pan.baidu.com/s/1Fs35ZE5xx52eFBusyx7GYg?pwdfcss 提取码: fcss

写出第一个php程序

一、打开vscode&#xff0c;下载chinese插件、php debug、phpintelephense 二、下载完上方图片插件后&#xff0c;创建一个PHP文件&#xff0c;1.php 三、执行命令&#xff0c;成功输出

Prometheus Metrics和PromQL的使用

Metrics 官方解释是 Metrics are numerical measurements in layperson terms. (通俗地讲&#xff0c;Metrics就是数字测量) Prometheus fundamentally stores all data as time series &#xff08;Prometheus把所有数据都存储为时间序列&#xff09; Every time series is u…

【数据分享】2001-2023年我国省市县镇四级的逐月平均气温数据(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月平均气温栅格数据&#xff0c;该数据来源于国家青藏高原科学数据中心。为方便大家使用&#xff0c;我们还基于上述平均气温栅格数据将数据处理为Shp和Excel格式的省市县三级逐月平均气温数据&#xff08;可查看之前的文章获悉详情&#…

基于SSM的高校勤工助学管理系统的设计与实现(源码+定制+参考文档)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

linux文件编程_线程

1. 基本概念 1.1. 进程与线程的概念 典型的UNIX/linux进程可以看成是只有一个控制线程&#xff0c;一个进程在同一时刻只做一件事情&#xff0c;有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。…

【重学 MySQL】五十、添加数据

【重学 MySQL】五十、添加数据 使用INSERT INTO语句添加数据基本语法示例插入多行数据注意事项 使用LOAD DATA INFILE语句批量添加数据其他插入数据的方式注意事项 在MySQL中&#xff0c;添加数据是数据库操作中的基本操作之一。 使用INSERT INTO语句添加数据 使用 INSERT IN…

多维度柱状图绘制

图形结果 绘制过程 数据如下 调整柱子宽度 Z轴设置 、 配色表