Java反射

Java反射

在学习这种语言基础时,一定要要动手去写一些demo,不要只停留在看的层面

所以我写这篇博客的主要目的就是想要更直观的去了解Java反射,比较适合新手小白入门

正射

反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释。

正射就是在编写代码时当需要使用到某一个类的时候,我们要先了解这个类是做什么的,然后实例化这个类,接着用实例化好的对象进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Person {
public String name;
private int age;

public Person(){

}

public Person(String name,int age){
this.name=name;
this.age=age;
}

public void action(String act){
System.out.println(act);
}

public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

public static void main(String[] args) throws Exception{
Person person = new Person("abc",22);
System.out.println("Name: " + person.name);
System.out.println(person);
}
}

反射

而反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。

总结为四个步骤

1.操作Class

2.从原型class里面实例化对象

3.获取类里面属性

4.调用类里面方法

操作Class

加载类,返回Class类型的对象

讲反射的第一个就先了解一下getClass

image

这个是Object里面的一个final方法,会返回一个大Class类型

可以看一下大Class类里面有什么东西

forname

1
2
3
4
5
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

返回的也是一个泛型的Class,就是你把它的名字传进去,就会返回对应的原型类

1
Class c = Class.forName("Person");

实例化对象

newInstance

1
2
3
4
5
6
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}

一个无参的方法

getConstructor

1
2
3
4
5
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.PUBLIC);
}

可以接收参数

1
Constructor personConstructor = c.getConstructor(String.class, int.class);

然后我们再实例化

1
2
3
4
5
6
7

public static void main(String[] args) throws Exception{
Class c = Class.forName("Person");
Constructor personConstructor = c.getConstructor(String.class, int.class);
Person p = (Person) personConstructor.newInstance("abc", 22);
System.out.println(p);
}

获取类里面属性

getFields

它的参数类型是一个数组,我们来打印看一下返回什么

1
2
3
4
Field[] personfields = c.getFields();
for (Field f:personfields){
System.out.println(f);
}

返回了

public java.lang.String Person.name

也就是string类型的name,但是要知道我们一开始写的demo里面还有一个age,age并没有打印出来,即这个只可以返回public类型的参数

getDeclaredFields

那么我们就用这个看能否把private的age返回,直接进行修改

public java.lang.String Person.name private int Person.age

ok,成功返回了私有属性的参数

也就是说Declared会把所有的变量都打印出来

getField

我们用这个进行属性值的更改

1
2
Field namefield = c.getField("name");
namefield.set(p,"aaaaaaaaaa");

image

同理,这个也只是可以修改公有属性的值

getDeclaredField

如果我们直接把它改成这个运行会报access的问题

于是我们需要加上一行赋予权限

namefield.setAccessible(true);

image

调用类里面的方法

getMethods

1
2
3
4
Method[] personmethods = c.getMethods();
for (Method f:personmethods){
System.out.println(f);
}

image

大部分都是继承的方法,但是也可以看到有我定义的action方法

getMethod

接收一个函数名和一个类的泛型

用这个来调用我们的方法

跟getField类似,但这里不适用set而是用invoke

1
2
Method actionmethod = c.getMethod("action", String.class);
actionmethod.invoke(p,"sdfghhj");

getDeclaredMethod

与getDeclaredField一样

总结

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。


Java反射
http://example.com/post/java-reflection-z1evhqq.html
作者
Dre4m
发布于
2025年8月4日
许可协议