当前位置: 首页> 游戏> 游戏 > 重庆市建设工程信息网招标代理入渝备案取消_亚马逊跨境电商入门完整教程_如何推广软件_今日新闻摘抄十条

重庆市建设工程信息网招标代理入渝备案取消_亚马逊跨境电商入门完整教程_如何推广软件_今日新闻摘抄十条

时间:2025/7/12 6:28:15来源:https://blog.csdn.net/2501_90745824/article/details/146377238 浏览次数:0次
重庆市建设工程信息网招标代理入渝备案取消_亚马逊跨境电商入门完整教程_如何推广软件_今日新闻摘抄十条

反射

反射机制可以读取注解。

反射的概念

在 Java 中,通常情况下,我们在编译时就知道要使用的类和方法。但反射机制打破了这种常规,它允许程序在运行时动态地分析类、调用方法、操作字段等。也就是说,在运行时,程序可以根据需要来决定要使用哪个类、调用哪个方法、访问哪个字段,而不是在编译时就确定下来。

反射的核心类

Java 反射机制主要涉及以下几个核心类:

1、Class

Class类是反射机制的基础,它代表一个类或接口。在 Java 中,每个类都有一个对应的Class对象,通过Class对象可以获取类的各种信息,如类名、父类、接口、方法、字段等**(可以理解为Class对象拥有对应类的所有信息)**。获取Class对象的常见方式有以下几种:

  • Class.forName("全限定类名"):通过类的全限定名获取 Class 对象。
  • 类名.class:直接通过类名获取 Class 对象。
  • 对象.getClass():通过对象的 getClass() 方法获取 Class 对象。
// 示例代码
try {// 方式一:使用 Class.forNameClass<?> clazz1 = Class.forName("java.util.ArrayList");// 方式二:使用 类名.classClass<?> clazz2 = java.util.ArrayList.class;// 方式三:使用 对象.getClass()java.util.ArrayList list = new java.util.ArrayList();Class<?> clazz3 = list.getClass();
} catch (ClassNotFoundException e) {e.printStackTrace();
}

2、Constructor:代表类的构造函数,通过 Class 对象的 getConstructor()getDeclaredConstructor() 方法可以获取构造函数对象,然后使用 newInstance() 方法创建类的实例。

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class ConstructorExample {public static void main(String[] args) {try {Class<?> clazz = String.class;// 获取带有一个 String 参数的构造函数Constructor<?> constructor = clazz.getConstructor(String.class);// 创建对象Object obj = constructor.newInstance("Hello");System.out.println(obj);} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}}
}

3、Method:代表类的方法,通过 Class 对象的 getMethod()getDeclaredMethod() 方法可以获取方法对象,然后使用 invoke() 方法调用该方法。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class MethodExample {public static void main(String[] args) {try {Class<?> clazz = String.class;// 获取 substring 方法Method method = clazz.getMethod("substring", int.class, int.class);String str = "HelloWorld";// 调用方法Object result = method.invoke(str, 0, 5);System.out.println(result);} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}}
}

4、Field:代表类的字段,通过 Class 对象的 getField()getDeclaredField() 方法可以获取字段对象,然后使用 get()set() 方法访问和修改字段的值。

import java.lang.reflect.Field;class MyClass {public int myField = 10;
}public class FieldExample {public static void main(String[] args) {try {MyClass obj = new MyClass();Class<?> clazz = obj.getClass();// 获取字段Field field = clazz.getField("myField");// 获取字段的值int value = (int) field.get(obj);System.out.println("Original value: " + value);// 修改字段的值field.set(obj, 20);int newValue = (int) field.get(obj);System.out.println("New value: " + newValue);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}}
}

反射的使用场景

  1. 框架开发:许多 Java 框架(如 Spring、Hibernate 等)都广泛使用反射机制。例如,Spring 框架通过反射实现依赖注入,在运行时动态地创建对象并注入依赖;Hibernate 框架通过反射来映射数据库表和 Java 类。
  2. 插件化开发:在插件化开发中,可以使用反射机制动态加载和使用插件类,实现程序的扩展性。
  3. 单元测试:在单元测试中,可以使用反射机制访问和调用类的私有方法和字段,方便进行测试。

反射的优缺点

优点

  • 灵活性高:反射机制允许程序在运行时动态地处理类和对象,提高了程序的灵活性和可扩展性。
  • 可扩展性强:可以在不修改现有代码的情况下,通过反射机制动态地加载和使用新的类和方法。

缺点

  • 性能开销大:反射涉及到动态解析类和方法,相比直接调用,会带来一定的性能开销。
  • 安全性问题:反射机制可以访问和修改类的私有成员,可能会破坏类的封装性,带来安全隐患。
  • 代码可读性和维护性差:反射代码通常比较复杂,可读性和维护性较差。

得到Class类的几种方式

1. 使用 Class.forName() 方法

  • 原理Class.forName() 是一个静态方法,它接收一个字符串参数,该参数为类的全限定名(包含包名)。此方法会尝试加载指定名称的类,并返回对应的 Class 对象。如果指定的类不存在或者在加载过程中出现问题,会抛出 ClassNotFoundException 异常。
  • 适用场景:常用于动态加载类,例如在配置文件中指定类名,程序在运行时根据配置文件中的类名动态加载相应的类。
  • 示例代码
public class ForNameExample {public static void main(String[] args) {try {// 通过全限定名获取 Class 对象Class<?> clazz = Class.forName("java.util.ArrayList");System.out.println(clazz.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

2. 使用 类名.class 语法

  • 原理:在 Java 中,每个类都有一个隐含的静态成员变量 class,通过 类名.class 可以直接获取该类对应的 Class 对象。这种方式是在编译时就确定了要获取的 Class 对象,不需要进行类的加载操作。
  • 适用场景:当在代码中明确知道要操作的类时,使用这种方式非常简洁和方便。
  • 示例代码
public class ClassLiteralExample {public static void main(String[] args) {// 直接通过类名获取 Class 对象Class<?> clazz = java.util.ArrayList.class;System.out.println(clazz.getName());}
}

3. 使用对象的 getClass() 方法

  • 原理Object 类是所有类的父类,Object 类中定义了 getClass() 方法,该方法返回调用该方法的对象所属类的 Class 对象。因此,任何 Java 对象都可以调用 getClass() 方法来获取其所属类的 Class 对象。
  • 适用场景:当已经有一个对象实例,需要获取该对象所属类的信息时,使用这种方式很合适。
  • 示例代码
import java.util.ArrayList;public class GetClassExample {public static void main(String[] args) {// 创建对象ArrayList<String> list = new ArrayList<>();// 通过对象的 getClass() 方法获取 Class 对象Class<?> clazz = list.getClass();System.out.println(clazz.getName());}
}

4. 使用基本数据类型的 TYPE 字段

  • 原理:对于基本数据类型(如 intchar 等),Java 为它们提供了对应的包装类,并且每个包装类都有一个静态常量 TYPE,该常量是一个 Class 对象,代表对应的基本数据类型。
  • 适用场景:在处理基本数据类型和包装类的反射操作时会用到。
  • 示例代码
public class PrimitiveTypeExample {public static void main(String[] args) {// 获取 int 基本数据类型的 Class 对象Class<?> intClass = int.class;System.out.println(intClass.getName());// 通过包装类的 TYPE 字段获取 int 基本数据类型的 Class 对象Class<?> intClass2 = Integer.TYPE;System.out.println(intClass2.getName());}
}

哪些类型可以有Class对象

1. 类(class

普通的 Java 类,无论是自定义类还是 Java 标准库中的类,都有对应的 Class 对象。

// 自定义类
class MyClass {}public class ClassForClassExample {public static void main(String[] args) {// 获取自定义类的 Class 对象Class<?> myClassClass = MyClass.class;System.out.println(myClassClass.getName());// 获取 Java 标准库中类的 Class 对象Class<?> stringClass = String.class;System.out.println(stringClass.getName());}
}

2. 接口(interface

Java 中的接口同样拥有对应的 Class 对象。

// 定义一个接口
interface MyInterface {}public class ClassForInterfaceExample {public static void main(String[] args) {// 获取接口的 Class 对象Class<?> myInterfaceClass = MyInterface.class;System.out.println(myInterfaceClass.getName());// 获取 Java 标准库中接口的 Class 对象Class<?> listInterfaceClass = java.util.List.class;System.out.println(listInterfaceClass.getName());}
}

3. 数组(array

无论数组的元素类型是基本数据类型还是引用类型,数组都有对应的 Class 对象。数组的 Class 对象的名称包含元素类型和维度信息。

public class ClassForArrayExample {public static void main(String[] args) {// 基本数据类型数组int[] intArray = new int[5];Class<?> intArrayClass = intArray.getClass();System.out.println(intArrayClass.getName());// 引用类型数组String[] stringArray = new String[5];Class<?> stringArrayClass = stringArray.getClass();System.out.println(stringArrayClass.getName());}
}

4. 基本数据类型(primitive type

Java 的 8 种基本数据类型(byteshortintlongfloatdoublecharboolean)都有对应的 Class 对象。可以通过 .class 语法或者包装类的 TYPE 字段来获取。

public class ClassForPrimitiveExample {public static void main(String[] args) {// 通过 .class 语法获取基本数据类型的 Class 对象Class<?> intClass = int.class;System.out.println(intClass.getName());// 通过包装类的 TYPE 字段获取基本数据类型的 Class 对象Class<?> doubleClass = Double.TYPE;System.out.println(doubleClass.getName());}
}

5. 枚举(enum

枚举类型是一种特殊的类,也有对应的 Class 对象。

// 定义一个枚举
enum MyEnum {VALUE1, VALUE2
}public class ClassForEnumExample {public static void main(String[] args) {// 获取枚举的 Class 对象Class<?> myEnumClass = MyEnum.class;System.out.println(myEnumClass.getName());}
}

6. 注解(annotation

注解是 Java 5 引入的一种元数据机制,注解类型也有对应的 Class 对象。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {}public class ClassForAnnotationExample {public static void main(String[] args) {// 获取注解的 Class 对象Class<?> myAnnotationClass = MyAnnotation.class;System.out.println(myAnnotationClass.getName());}
}

7. void 类型

void 类型也有对应的 Class 对象,可通过 void.class 来获取。

public class ClassForVoidExample {public static void main(String[] args) {// 获取 void 类型的 Class 对象Class<?> voidClass = void.class;System.out.println(voidClass.getName());}
}
关键字:重庆市建设工程信息网招标代理入渝备案取消_亚马逊跨境电商入门完整教程_如何推广软件_今日新闻摘抄十条

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: