为什么使用泛型
- 提高代码重用性
- 提高代码可读性和安全性
- 消除强制类型转换
如何理解Java中泛型的伪泛型
在Java中,泛型是一个强大的工具,它允许我们在编译时提供类型信息,从而在运行时避免类型转换错误。然而,Java的泛型被称为“伪泛型”,这是因为它在运行时并不保留类型信息。这种现象是由于Java泛型的实现机制——类型擦除(Type Erasure)所导致的
什么是类型擦除
在Java编译器将泛型代码转换为字节码时,会移除所有的泛型类型信息,只保留原始类型。这意味着泛型类在运行时并不知道它所操作的具体类型,所有的泛型类型参数都被替换为它们的边界类型,如果没有指定边界,则替换为Object
什么是注解
Java 注解,也称为 Java 标注,是 JDK 5.0 引入的一种特殊机制,用于为代码添加元数据。这些元数据不会直接影响代码的逻辑,但可以被编译器和运行时环境使用,实现额外的功能。注解可以应用于类、方法、变量、参数和包等各种元素。
注解的原理
注解的实现原理涉及到 Java 的动态代理。当我们通过反射获取注解时,Java 实际上会创建一个注解的代理对象。例如,当我们调用 @MyAnnotation 的 value() 方法时,实际上是调用代理对象的 invoke 方法来获取属性值。
Java 注解是一种强大的机制,它为我们提供了一种在不改变代码逻辑的情况下,为代码添加信息和指令的方法。通过学习和使用注解,我们可以更好地理解和使用各种框架,并且可以通过自定义注解来实现特定的功能。
什么是反射
Java反射是Java语言中的一个强大特性,它允许程序在运行时访问、检查和修改它自身的结构。反射机制主要提供了以下几个方面的功能:
- 运行时类信息获取:反射可以在程序运行时获取类的信息,如类的方法、字段、构造函数等,甚至可以获取未加载的类的信息。
- 动态对象创建:通过反射,可以动态创建对象,无需在编译时就确定具体的类,增加了程序的灵活性。
- 访问私有成员:反射能够访问和修改类中的私有字段和方法,即使这些成员是私有的。
- 实现动态代理:反射可用于动态代理的实现,即在运行时动态创建实现某个接口的代理类,以实现特定功能,如事务处理。
反射的特点
反射的特点包括其动态性,它允许程序在运行期间动态地创建对象、调用方法和修改属性。然而,反射也存在一些缺点,如性能问题和安全性问题,因为它破坏了封装性,可能会导致性能下降和安全隐患。
动态代理
动态代理是一种在运行时创建代理对象的技术,它允许在不修改原始代码的情况下增强方法的功能。Java中主要有两种实现动态代理的方式:JDK动态代理和CGLib动态代理。
JDK动态代理依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。它只能代理实现了接口的类。
CGLib动态代理通过在运行时生成目标类的子类来实现代理,能够代理未实现接口的类。
JDK Proxy 与 CGLib 的区别
- 代理对象类型:JDK Proxy只能代理实现了接口的类;CGLib可以代理普通类
- 性能:CGLib在运行时生成代理类的子类,性能通常略优于JDK Proxy。
- 使用场景:如果目标对象实现了接口,使用JDK Proxy更简单直接;如果需要代理没有实现接口的类,则必须使用CGLib