当前位置: 首页 > news >正文

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. 类型擦除后,编译器会确保类型安全
http://www.jsqmd.com/news/99525/

相关文章:

  • 重庆到广州、深圳、东莞、佛山搬家公司排行、搬家费用明细 - 物流人
  • LobeChat能否引用权威来源?知识准确性保障
  • Simulink模型转.so实战:高效部署到Qt项目的操作指南
  • GPT-SoVITS模型架构与S1、S2模块详解
  • 2025年拉力试验机实力厂家权威推荐榜单:电子拉力试验机/电子万能拉力试验机/液压万能拉力试验机源头厂家精选 - 品牌推荐官
  • Keepalived详解:安装与高可用集群配置
  • Perl在鸿蒙PC上的使用方法
  • AI 原生落地成果获认可,阿里云云原生多项案例入选信通院「AI 云」典型示范
  • 使用npm安装GPT-SoVITS前端控制台常见报错解决
  • 语音合成新突破:GPT-SoVITS实现跨语言TTS只需1分钟音频
  • AutoGPT入门与本地部署安装指南
  • Raft算法在大数据领域的应用:原理与实践
  • HMI动画使用戒律:何时动?如何动?
  • Dify智能体平台 vs 若依框架:谁更适合企业AI转型?
  • 重庆到成都、昆明、贵阳、遵义搬家公司排行、搬家费用明细 - 物流人
  • GNU make在鸿蒙PC上的使用方法
  • 大数据领域 OLAP 的实时数据分析框架
  • 【分析式AI】-机器学习的分类以及学派
  • LobeChat能否识别面部表情?情感反馈闭环
  • FaceFusion显卡利用率低?解决cuDNN加载失败问题
  • StarRocks报错解决方案Failed to find enough host in all backends. need: 3, Current alive backend is [10003]
  • YOLOv5车辆与车牌识别全功能实现
  • AWS成本优化的五个高阶战术:实战经验让你至少节省30%
  • 深度剖析:如何通过数据即服务释放大数据商业价值?
  • 数据库计算题解析:关系模式R的函数依赖与范式分析
  • Dify平台深度解析:降低大模型应用开发门槛的关键
  • 从零开始配置TensorFlow环境:推荐使用清华镜像源
  • 《计算机组成原理与汇编语言程序设计》期末复习:3道核心问答题详解(每题10分)
  • LobeChat适合做AI客服吗?对比专业客服系统的差距
  • 阿里云服务器虚拟化技术的特点,为什么要使用虚拟化技术?