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

Java 泛型(Generic)

Java 泛型(Generic)

一、理论说明

1. 泛型的定义

Java 泛型是 JDK 5.0 引入的一项特性,它提供了一种参数化类型的机制,允许在定义类、接口或方法时使用类型参数。通过泛型,开发者可以编写更加通用、类型安全的代码,减少强制类型转换,提高代码的可读性和可维护性。泛型的本质是类型参数化,即把类型作为参数传递,使得类、接口或方法能够处理多种不同类型的数据,同时保持编译时的类型安全。

2. 泛型与普通类的区别

  • 类型安全性
    • 普通类在处理不同类型的数据时,通常需要进行强制类型转换,这可能会在运行时导致ClassCastException异常。例如,使用普通的ArrayList存储不同类型的元素,在取出元素时需要进行类型转换。
    • 泛型类在定义时就指定了具体的类型参数,编译器会在编译时进行类型检查,确保只能存储指定类型的元素,从而避免了运行时的类型转换异常。例如,ArrayList<String>只能存储String类型的元素,在编译时就会对不匹配的类型进行错误提示。
  • 代码复用性
    • 普通类需要为不同的数据类型编写重复的代码,例如,为处理Integer类型和String类型的数据,可能需要编写两个几乎相同的类。
    • 泛型类通过类型参数可以处理多种不同类型的数据,实现了代码的复用。例如,ArrayList<E>可以处理任意类型的数据,只需要在使用时指定具体的类型参数。
  • 编程效率
    • 使用普通类时,由于需要进行强制类型转换,代码会变得冗长,并且容易出错。
    • 泛型类消除了强制类型转换,使代码更加简洁、清晰,提高了编程效率。

二、常用语法与示例

1. 泛型类

泛型类是在类名后面添加类型参数声明,使用尖括号<>括起来,可以有一个或多个类型参数,多个参数之间用逗号分隔。例如:

public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}

2. 泛型方法

泛型方法是在方法返回类型前添加类型参数声明,使用尖括号<>括起来。泛型方法可以在普通类中定义,也可以在泛型类中定义。例如:

public class GenericMethodExample {public static <T> void printArray(T[] array) {for (T element : array) {System.out.print(element + " ");}System.out.println();}public static void main(String[] args) {Integer[] intArray = {1, 2, 3, 4, 5};String[] stringArray = {"Hello", "World"};printArray(intArray);printArray(stringArray);}
}

3. 泛型接口

泛型接口的定义与泛型类类似,在接口名后面添加类型参数声明。例如:

public interface Generator<T> {T generate();
}public class StringGenerator implements Generator<String> {@Overridepublic String generate() {return "Generated String";}
}

4. 通配符

通配符?用于表示未知类型,主要有三种形式:

四、面试题

题目:

答案:

五、自我总结

通过对 Java 泛型的学习,我们掌握了一种强大的类型参数化机制。与普通类相比,泛型类在类型安全性、代码复用性和编程效率方面具有明显优势。掌握泛型类、泛型方法、泛型接口和通配符的使用,能够让我们在实际编程中编写更加通用、类型安全的代码。在实际应用场景中,如集合框架、数据处理、设计模式等方面,泛型都能发挥重要作用。合理使用泛型可以避免类型转换异常,提高代码的可读性和可维护性,是 Java 编程中不可或缺的一项重要技术。

  • 无界通配符<?>,表示未知类型。例如:
    public static void printList(List<?> list) {for (Object element : list) {System.out.print(element + " ");}System.out.println();
    }

  • 上界通配符<? extends T>,表示类型必须是TT的子类。例如:
    public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number n : list) {sum += n.doubleValue();}return sum;
    }

  • 下界通配符<? super T>,表示类型必须是TT的父类。例如:
    public static void addNumbers(List<? super Integer> list) {for (int i = 1; i <= 10; i++) {list.add(i);}
    }

    三、应用实例

    以下代码展示了泛型的综合应用:

    import java.util.ArrayList;
    import java.util.List;// 泛型类:容器
    class Container<T> {private List<T> items;public Container() {this.items = new ArrayList<>();}public void addItem(T item) {items.add(item);}public T getItem(int index) {return items.get(index);}public int size() {return items.size();}// 泛型方法:交换容器中两个元素的位置public <E> void swap(int i, int j) {if (i < 0 || i >= size() || j < 0 || j >= size()) {throw new IndexOutOfBoundsException("索引超出范围");}T temp = items.get(i);items.set(i, items.get(j));items.set(j, temp);}// 使用上界通配符的方法:计算容器中所有元素的和(假设元素是Number或其子类)public double sum() {double sum = 0.0;for (T item : items) {if (item instanceof Number) {sum += ((Number) item).doubleValue();}}return sum;}
    }public class Main {public static void main(String[] args) {// 创建一个存储整数的容器Container<Integer> intContainer = new Container<>();intContainer.addItem(10);intContainer.addItem(20);intContainer.addItem(30);System.out.println("交换前的容器元素:");for (int i = 0; i < intContainer.size(); i++) {System.out.print(intContainer.getItem(i) + " ");}System.out.println();// 交换元素位置intContainer.swap(0, 2);System.out.println("交换后的容器元素:");for (int i = 0; i < intContainer.size(); i++) {System.out.print(intContainer.getItem(i) + " ");}System.out.println();// 计算元素的和double sum = intContainer.sum();System.out.println("元素的和: " + sum);// 创建一个存储字符串的容器Container<String> stringContainer = new Container<>();stringContainer.addItem("Hello");stringContainer.addItem("World");System.out.println("字符串容器的元素:");for (int i = 0; i < stringContainer.size(); i++) {System.out.print(stringContainer.getItem(i) + " ");}System.out.println();}
    }
    代码解释
  • 泛型类定义Container<T>是一个泛型类,使用类型参数T,内部使用List<T>存储元素,提供了添加元素、获取元素、交换元素位置和计算元素和等方法。
  • 泛型方法实现swap方法是一个泛型方法,用于交换容器中两个元素的位置,通过类型参数<E>实现了更灵活的类型检查。
  • 通配符使用sum方法使用了上界通配符<? extends Number>,确保只能处理Number或其子类类型的元素,从而实现了对数值类型元素的求和操作。
http://www.xdnf.cn/news/5213.html

相关文章:

  • 本地大模型工具深度评测:LM Studio vs Ollama,开发者选型指南
  • 每日算法刷题Day1 5.9:leetcode数组3道题,用时1h
  • Paging 3.0 + Kotlin 分页加载指南
  • 用go从零构建写一个RPC(仿gRPC,tRPC)--- 版本2
  • 实验四:网络编程
  • localStorage和sessionStorage
  • Day28 -js开发01 -JS三个实例:文件上传 登录验证 购物商城 ---逻辑漏洞复现 及 判断js的payload思路
  • [Linux网络_71] NAT技术 | 正反代理 | 网络协议总结 | 五种IO模型
  • 好用的播放器推荐
  • 蓝桥杯嵌入式第十一届省赛真题
  • Python企业级OCR实战开发:从基础识别到智能应用
  • 健康养生:开启活力生活的密码
  • JGL066生活垃圾滚筒筛分选机实验装置
  • MAD-TD: MODEL-AUGMENTED DATA STABILIZES HIGH UPDATE RATIO RL
  • Ubuntu22.04安装显卡驱动/卸载显卡驱动
  • JDBC工具类的三个版本
  • Windows系统Jenkins企业级实战
  • Redis经典面试题
  • 数据库实验10
  • 【经验总结】Ubuntu 22.04.5 LTS 将内核从5.15.0-140 升级到6.8.0-60后纽曼无线网卡无法使用解决措施
  • C++ 命令模式详解
  • R 语言科研绘图 --- 桑基图-汇总
  • Python网络爬虫:从入门到实践
  • uniapp-商城-51-后台 商家信息(logo处理)
  • 33号远征队 - SDKDump
  • Spring 必会之微服务篇(2)
  • 前端进化论·JavaScript 篇 · 数据类型
  • [学习]RTKLib详解:sbas.c与rtcm.c
  • Linux 阻塞和非阻塞 I/O 简明指南
  • [架构之美]linux常见故障问题解决方案(十九)