Java 中反射的学习
反射是 Java 提供的一种机制,通过 java.lang.reflect
包中的接口和类,可以在运行时动态地获取类的结构信息(如构造器、成员变量、成员方法等),并对其进行操作。
什么是反射?
定义
反射是指将加载到内存中的字节码,通过代码编程的方式解析出类的各个组成部分(构造器、成员变量、成员方法)。
作用
反射的主要作用包括:
- 动态加载类和操作类的成员。
- 实现框架的通用性(如 Spring、Hibernate 等)。
- 在运行时动态生成代理类。
如何获取 Class 对象?
在 Java 中,可以通过以下三种方式获取 Class
对象:
1. 通过类的 class
属性
每个类都有一个静态的 class
属性,可以直接通过 类名.class
获取对应的 Class
对象。
1
| Class<?> clazz = String.class;
|
2. 通过对象的 getClass()
方法
每个 Java 对象都有一个 getClass()
方法,可以通过该方法获取对象所属类的 Class
对象。
1 2
| String str = "Hello"; Class<?> clazz = str.getClass();
|
3. 通过 Class.forName()
方法
使用类的全限定名(包名+类名)作为参数,调用 Class.forName()
方法获取 Class
对象。
1 2 3 4 5
| try { Class<?> clazz = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
|
注意:使用 Class.forName()
方法时,如果类不存在或类加载失败,会抛出 ClassNotFoundException
。
解析类的组成部分
通过反射,可以解析类的以下组成部分:
构造器:Constructor
获取构造器
getConstructors()
:获取类中所有的 公有构造器。
getDeclaredConstructors()
:获取类中所有的构造器(包括私有构造器)。
1 2 3 4 5 6 7
| Class<?> clazz = String.class;
Constructor<?>[] publicConstructors = clazz.getConstructors();
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
|
调用构造器
通过 Constructor
对象的 newInstance()
方法,可以调用构造器创建对象。
1 2 3 4 5 6 7 8 9 10
| try { Constructor<String> constructor = String.class.getConstructor(String.class);
String str = constructor.newInstance("Hello"); System.out.println(str); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }
|
设置私有构造器可访问
对于私有构造器,可以通过 setAccessible(true)
方法设置其可访问性。
1 2 3 4 5 6 7 8 9 10 11 12 13
| try { Constructor<String> privateConstructor = String.class.getDeclaredConstructor(byte[].class);
privateConstructor.setAccessible(true);
String str = privateConstructor.newInstance("Hello".getBytes()); System.out.println(str); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }
|
成员变量:Field
通过反射,可以获取类的成员变量(包括公有和私有)。
获取成员变量
getFields()
:获取类中所有的 公有成员变量。
getDeclaredFields()
:获取类中所有的成员变量(包括私有成员变量)。
1 2 3 4 5 6 7
| Class<?> clazz = String.class;
Field[] publicFields = clazz.getFields();
Field[] allFields = clazz.getDeclaredFields();
|
操作成员变量
通过 Field
对象,可以读取或修改成员变量的值。
1 2 3 4 5 6 7 8 9 10 11 12
| try { Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
String str = "Hello"; char[] value = (char[]) valueField.get(str); System.out.println(Arrays.toString(value)); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }
|
成员方法:Method
通过反射,可以获取类的成员方法(包括公有和私有)。
获取成员方法
getMethods()
:获取类中所有的 公有方法。
getDeclaredMethods()
:获取类中所有的方法(包括私有方法)。
1 2 3 4 5 6 7
| Class<?> clazz = String.class;
Method[] publicMethods = clazz.getMethods();
Method[] allMethods = clazz.getDeclaredMethods();
|
调用成员方法
通过 Method
对象的 invoke()
方法,可以调用类的方法。
1 2 3 4 5 6 7 8 9
| try { Method charAtMethod = String.class.getMethod("charAt", int.class);
String str = "Hello"; char ch = (char) charAtMethod.invoke(str, 1); System.out.println(ch); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }
|