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(); }
|