news 2026/6/24 12:03:58

java : 泛型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java : 泛型

1.泛型类的定义

泛型类是Java中一种可以参数化的类,它允许在定义类时不指定具体的类型,而是在实例化时再确定具体的类型参数。这种机制提高了代码的复用性和类型安全性。

1.1基本语法

  • 泛型类的定义语法
  • class 类名称 <泛型标识、泛型标识,...> { private 泛型标识 变量名; ...... }
  • 常用的泛型标识T、E、K、V

其中:

  • <T>表示类型参数声明
  • T是类型参数名(可以是任何有效的标识符,但通常使用单个大写字母)
  • 可以在类定义中使用T作为实际的类型

1.2 示例代码

​ /** * 泛型类的定义 * @param <T> 泛型标识-----类型形参 * T 创建对象的时候里面具体制定的数据类型 */ public class Generic<T> { // T 是由外部使用类的时候来指定的。 private T key; public Generic(T key) { this.key = key; } public T getKey() { return key; } public void setKey(T key) { this.key = key; } @Override public String toString() { return "Generic{" + "key=" + key + '}'; } } ​

1.3 使用场景

  1. 容器类:如集合框架中的ArrayList、HashMap等
  2. 工具类:如比较器Comparator
  3. 数据包装类:如Optional
  4. 自定义数据结构:如树、图等通用数据结构

1.4 多类型参数

泛型类可以定义多个类型参数:

public class Pair<K, V> { private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; } // getter和setter方法 }

1.5 类型参数约束

可以使用extends关键字对类型参数进行约束:

public class NumberBox<T extends Number> { private T number; public double getDoubleValue() { return number.doubleValue(); } }

1.6 注意事项

  1. 泛型类不能是基本数据类型(如int、char等)
  2. 类型擦除:Java泛型是通过类型擦除实现的,运行时类型信息会被擦除
  3. 静态成员不能使用类型参数
  4. 不能实例化类型参数(如new T()是不允许的)

2. 泛型类的使用语法

泛型类是Java中实现参数化类型的重要机制,它允许在定义类时指定类型参数,在使用时再确定具体类型。以下是泛型类的详细使用说明:

2.1. 泛型类的定义

  • 使用语法
类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
  • java 1.7以后,后边的<>中具体的数据类型可以省略不写
类名<具体的数据类型> 对象名 = new 类名<>();

2.2 案例:

public static void main(String[] args) { // 泛型类在创建对象的时候来指定操作的具体数据类型 Generic<String> stringGeneric = new Generic<>("a"); String key = stringGeneric.getKey(); System.out.println("key:" + key); System.out.println("------------------------"); Generic<Integer> integerGeneric = new Generic<>(100); Integer key1 = integerGeneric.getKey(); System.out.println("key1:"+key1); // 总结:泛型的本质是参数化类型,也就是所操作的数据类型被指定为一个参数。 System.out.println("----------注意点1:--------------"); // 泛型类在创建对象的时候,没有指定泛型类,将按照Object类型来操作 Generic generic = new Generic("ABC"); Object key3 = generic.getKey(); System.out.println("key3:"+key3); System.out.println("----------注意点2:--------------"); // 泛型类不支持基本数据类型,原因就是我们在编译期间会将这个 T 编译成 Object // 基本数据类型无法转化为 object类型 // Generic<int> intGeneric = new Generic<>(100); System.out.println("----------注意点3:--------------"); // 同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型 System.out.println(integerGeneric.getClass() == stringGeneric.getClass()); }

总结:泛型类使用要点

  1. 未指定具体数据类型时,操作类型默认为Object
  2. 类型参数仅支持类类型,不支持基本数据类型
  3. 逻辑上可视为不同类型,但实际运行时属于同一类型

年终抽奖器(可能会是奖金,也可能是奖品)

/** * 抽奖器 * @param <T> */ public class ProductGetter<T> { //奖金或者奖品 private T product; // 定义奖品、奖金池 ArrayList<T> arrayList = new ArrayList<>(); // 添加奖品到奖品池 public void addProduct(T t){ arrayList.add(t); } // 定义一个随机数,用来抽选奖品 Random random = new Random(); //抽奖 public T getProduct(){ product = arrayList.get(random.nextInt(arrayList.size())); return product; } }
public static void main(String[] args) { ProductGetter<String> stringProductGetter = new ProductGetter<>(); String[] strPro = {"苹果手机","华为手机","扫地机器人","咖啡机"}; //将奖品放入奖金池 for (int i = 0;i< strPro.length;i++){ stringProductGetter.addProduct(strPro[i]); } String product = stringProductGetter.getProduct(); System.out.println("恭喜您抽中了:"+product); System.out.println("******************************"); ProductGetter<Integer> IntegerProductGetter = new ProductGetter<>(); Integer[] intPro = {100,1000,10000,20000}; //将奖品放入奖金池 for (int i = 0;i< intPro.length;i++){ IntegerProductGetter.addProduct(intPro[i]); } Integer product1 = IntegerProductGetter.getProduct(); System.out.println("恭喜您,获的了:"+product1+"元"); }

3. 从泛型类派生子类(2种情况)

  • 子类也是泛型类,子类和父类的泛型类型要保持一致
class ChildGeneric<T> extends Generic<T>
  • 子类不是泛型类,父类要明确泛型类的数据类型
class ChildGeneric extends Generic<String>

第一种情况:子类和父类的泛型类型要保持一致

定义父类

public class Parent<E> { private E value; public E getValue() { return value; } public void setValue(E value) { this.value = value; } }

定义子类

/** * 泛型类派生子类,如果子类也是泛型类,子类的泛型标识要和父类一致。 * @param <T> */ public class ChildFirst<T> extends Parent<T> { @Override public T getValue() { return super.getValue(); } }

测试类

public static void main(String[] args) { ChildFirst<String> childFirst = new ChildFirst<>(); childFirst.setValue("123"); String value = childFirst.getValue(); System.out.println(value); }

第二种情况:子类没有使用 泛型

总结:子类不是泛型类,父类要明确泛型类的数据类型

4. 泛型接口

4.1 泛型接口的语法定义

interface 接口名称 <泛型标识,泛型标识,...>{ 泛型标识 方法名(); ...... }

4.2 泛型接口的使用(2种情况)

情况1:实现类不是泛型类,接口要明确数据类型

当实现类不是泛型类时,需要在实现接口时明确指定具体的数据类型。这种情况下,接口的泛型参数会被具体化为特定的类型。

示例:

// 泛型接口定义 interface DataContainer<T> { void add(T item); T get(int index); } // 非泛型实现类 class StringContainer implements DataContainer<String> { private List<String> items = new ArrayList<>(); @Override public void add(String item) { items.add(item); } @Override public String get(int index) { return items.get(index); } }

应用场景:

  • 当实现类只需要处理特定类型数据时
  • 例如专门处理字符串、整数等具体类型的容器类
  • 可以避免在实现类中使用泛型带来的复杂性

情况2:实现类也是泛型类,实现类和接口的泛型类型要一致

当实现类也是泛型类时,实现类的泛型参数必须与接口的泛型参数保持一致,这样才能确保类型安全。

示例:

// 泛型接口定义 interface DataContainer<T> { void add(T item); T get(int index); } // 泛型实现类 class GenericContainer<T> implements DataContainer<T> { private List<T> items = new ArrayList<>(); @Override public void add(T item) { items.add(item); } @Override public T get(int index) { return items.get(index); } }

应用场景:

  • 当需要创建通用的、可重用的组件时
  • 例如集合框架中的ArrayList、LinkedList等
  • 可以保持代码的灵活性和可扩展性

注意事项:

  1. 实现类的泛型参数名可以与接口不同,但类型参数数量必须一致
  2. 可以在实现类中添加额外的泛型参数
  3. 类型擦除后,编译器会确保类型安全
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 14:59:24

Keepalived详解:安装与高可用集群配置

Keepalived详解&#xff1a;原理、编译安装与高可用集群配置 在高可用架构中&#xff0c;避免单点故障至关重要。Keepalived正是为了解决这一问题而生的轻量级工具。本文将深入浅出地介绍Keepalived的工作原理&#xff0c;并提供从编译安装到实战配置的完整指南。 1. Keepaliv…

作者头像 李华
网站建设 2026/6/24 17:33:49

LangChain与AutoGPT:AI工作流引擎深度对比

LangChain与AutoGPT&#xff1a;AI工作流引擎深度对比 在智能助手逐渐从“问答机器人”演变为“任务执行者”的今天&#xff0c;一个核心问题浮现出来&#xff1a;我们究竟需要一个听命行事的工具&#xff0c;还是一个能独立思考的代理&#xff1f;这个问题的答案&#xff0c;…

作者头像 李华
网站建设 2026/6/24 11:03:06

Excalidraw代码贡献指南:如何参与开源社区开发

Excalidraw代码贡献指南&#xff1a;如何参与开源社区开发 在远程办公成为常态、敏捷协作愈发重要的今天&#xff0c;团队对轻量级可视化工具的需求从未如此迫切。传统的图表软件往往过于“规整”——线条笔直、颜色统一、风格冰冷&#xff0c;反而让头脑风暴变得拘谨。而当你…

作者头像 李华
网站建设 2026/6/24 19:46:51

LangChain-Chatchat本地部署与配置指南

LangChain-Chatchat 本地部署与配置实战指南 在企业知识管理日益依赖 AI 的今天&#xff0c;如何构建一个安全、可控且高效的私有化问答系统&#xff0c;成为不少技术团队关注的核心问题。尤其当涉及敏感文档、内部流程或客户数据时&#xff0c;将信息上传至公有云模型显然不可…

作者头像 李华
网站建设 2026/6/24 12:41:04

shared_ptr 快照用于安全地并发读取,无需拷贝

需求&#xff1a;A线程会修改T类型的变量x&#xff0c;B线程要读取x&#xff0c;由于x很大&#xff0c;B读取和操作的时候需要加锁&#xff0c;这样会占用很长的x的时间。解决办法&#xff1a;方法1&#xff1a;B线程先加锁拷贝x到x_copy&#xff0c;然后锁可以释放&#xff0c…

作者头像 李华
网站建设 2026/6/24 18:08:17

官方适配完的命令行ruby在鸿蒙PC上的使用方法

ohos-ruby 是为 OpenHarmony 平台编译的 Ruby 编程语言解释器。本文档详细介绍如何在鸿蒙PC上安装和使用官方适配完成的 Ruby 工具&#xff0c;包括 HNP 包的打包、安装、gem 包管理以及 Ruby 脚本的运行方法。 &#x1f4cb; 目录 一、项目概述二、为什么需要 HNP 包三、HNP …

作者头像 李华