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

Java 泛型和反射(15/30)

目录

Java 泛型和反射

1. Java 泛型

1.1 泛型类和泛型方法

泛型类

泛型方法

1.2 泛型的通配符

2. Java 反射

2.1 反射的基础

2.2 动态创建对象和调用方法

3. 泛型和反射的结合

3.1 类型擦除

总结与后续


Java 泛型和反射

泛型反射 是 Java 中的两个非常强大的特性,分别用于编写类型安全的代码和动态操作类与对象。泛型使得代码在编译时就能检测到类型错误,而反射则允许程序在运行时获取关于类的详细信息并操作它们。通过学习泛型和反射,开发者可以编写更加通用、灵活和强大的 Java 应用程序。本模块将详细介绍 Java 泛型的概念、使用方法以及反射的基本原理与应用。

1. Java 泛型

Java 的 泛型(Generics)是一个用于编写类型安全和通用代码的工具。通过泛型,开发者可以在类、接口或方法中定义类型参数,以确保在使用时能够处理不同的数据类型,同时避免不必要的类型转换。

1.1 泛型类和泛型方法

泛型类

泛型类是具有类型参数的类,类型参数可以在创建对象时指定。

示例:泛型类

public class Box<T> {private T item;public void setItem(T item) {this.item = item;}public T getItem() {return item;}public static void main(String[] args) {Box<String> stringBox = new Box<>();stringBox.setItem("Hello World");System.out.println(stringBox.getItem());Box<Integer> intBox = new Box<>();intBox.setItem(123);System.out.println(intBox.getItem());}
}

在这个例子中,Box<T> 是一个泛型类,T 是类型参数。在使用时可以指定不同的类型,例如 StringInteger,从而使代码更加灵活。

泛型方法

泛型方法是带有类型参数的方法,允许方法在调用时指定不同的类型。

示例:泛型方法

public class GenericMethodExample {public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}}public static void main(String[] args) {Integer[] intArray = {1, 2, 3};String[] strArray = {"A", "B", "C"};printArray(intArray);printArray(strArray);}
}

在这个例子中,printArray 是一个泛型方法,它可以接受任何类型的数组,并将数组元素打印出来。

1.2 泛型的通配符

Java 提供了 通配符(Wildcard)来增强泛型的灵活性。

  • ? 通配符:表示未知的类型。

  • 上界通配符 <? extends T>:表示类型必须是 T 或其子类。

  • 下界通配符 <? super T>:表示类型必须是 T 或其超类。

示例:使用通配符

import java.util.List;public class WildcardExample {public static void printList(List<? extends Number> list) {for (Number num : list) {System.out.println(num);}}public static void main(String[] args) {List<Integer> intList = List.of(1, 2, 3);List<Double> doubleList = List.of(1.1, 2.2, 3.3);printList(intList);printList(doubleList);}
}

在这个例子中,printList 方法使用上界通配符来接受任何类型为 Number 或其子类的列表。

2. Java 反射

反射(Reflection)是 Java 提供的一种机制,允许程序在运行时检查和操作类、方法、字段等信息。通过反射,开发者可以动态地创建对象、调用方法和修改字段值。

2.1 反射的基础

Java 反射的核心类是 Class,它表示运行时的类或接口。通过反射,开发者可以获取类的结构和方法信息。

示例:获取类的信息

public class ReflectionExample {public static void main(String[] args) throws ClassNotFoundException {Class<?> clazz = Class.forName("java.util.ArrayList");System.out.println("类名: " + clazz.getName());System.out.println("方法列表:");for (var method : clazz.getMethods()) {System.out.println(method.getName());}}
}

在这个例子中,我们使用 Class.forName() 方法获取了 ArrayList 类的 Class 对象,并打印了类名和方法列表。

2.2 动态创建对象和调用方法

反射不仅可以获取类的信息,还可以动态创建对象并调用方法。

示例:动态创建对象并调用方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;public class ReflectionInvocationExample {public static void main(String[] args) {try {// 获取类的引用Class<?> clazz = Class.forName("java.lang.StringBuilder");// 动态创建对象Constructor<?> constructor = clazz.getConstructor();Object stringBuilderInstance = constructor.newInstance();// 动态调用 append 方法Method appendMethod = clazz.getMethod("append", String.class);appendMethod.invoke(stringBuilderInstance, "Hello Reflection");// 调用 toString 方法Method toStringMethod = clazz.getMethod("toString");String result = (String) toStringMethod.invoke(stringBuilderInstance);System.out.println("结果: " + result);} catch (Exception e) {e.printStackTrace();}}
}

在这个例子中,我们使用反射动态创建了一个 StringBuilder 对象,并通过反射调用了其 appendtoString 方法。

3. 泛型和反射的结合

在使用泛型时,由于 类型擦除 的存在,泛型类型在运行时被擦除为原始类型,这使得泛型和反射的结合变得复杂。

3.1 类型擦除

类型擦除 是指 Java 编译器在编译时会将泛型信息擦除,替换为它们的边界类型。例如,List<T> 会被擦除为 List,类型参数 T 会被替换为 Object 或其边界类型。

示例:类型擦除的影响

import java.util.ArrayList;
import java.util.List;public class TypeErasureExample {public static void main(String[] args) {List<String> stringList = new ArrayList<>();List<Integer> intList = new ArrayList<>();System.out.println(stringList.getClass() == intList.getClass());  // 输出: true}
}

在这个例子中,stringListintListClass 对象相等,因为泛型类型在运行时被擦除为相同的原始类型 List

总结与后续

在本模块中,我们学习了 Java 中的泛型和反射,包括如何使用泛型编写类型安全和通用的代码,以及如何使用反射在运行时动态地操作类和对象。泛型和反射的结合虽然有一些复杂性,但通过理解类型擦除,我们可以更好地在开发中利用这两种技术。

在下一模块中,我们将探讨 Java 序列化和反序列化,学习如何将对象转换为字节流进行存储或传输,以及如何恢复对象的状态。


http://www.mrgr.cn/news/61911.html

相关文章:

  • 无迹卡尔曼滤波器(UKF)
  • 记本地第一次运行seatunnel示例项目
  • ViSual studio如何安装 并使用GeographicLib
  • 「Mac畅玩鸿蒙与硬件5」鸿蒙开发环境配置篇5 - 熟悉 DevEco Studio 界面
  • 探索国际数据空间(IDS)架构(下)
  • 全网最最最详细的haproxy详解!!!
  • 软件工程经验详细总结
  • 进程线程、同步异步、并发并行
  • 小游戏发展迅速,游戏平台如何从技术方向加速业务转化?
  • 如何进行Java的时间序列分析与算法优化,应该从何入手?
  • 大模型:索引构建、预检索与检索阶段、检索后与生成阶段
  • 自动批量生成图片代码
  • Apache Hive 通过Docker快速入门
  • 深入解析Sysmon日志:增强网络安全与威胁应对的关键一环
  • Leetcode—3216. 交换后字典序最小的字符串【简单】
  • 先验概率、似然概率、后验概率
  • Qt5 读写共享内存,已验证,支持汉字的正确写入和读取
  • Java 中 InputStream 的使用:try-with-resources 与传统方式的比较
  • 解密自闭症全托寄宿肇庆:专业照顾与培养一站式服务
  • node学习记录-os
  • 比较24个结构的迭代次数
  • 量化与知识蒸馏的区别
  • 加密软件有什么功能?
  • flume系列之:flume机器做条带划分提高磁盘性能和吞吐量的详细步骤
  • Xss_less靶场攻略(1-18)
  • 电容的基本知识