使用 Class 和反射创建类的对象

  |  

摘要: 本文主要是关于如何用 Class 和反射创建类的对象,并调用方法。

【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


使用 Class 和反射创建类的对象

在 Class 类中有一个 newInstance 方法,可以用来创建 Class 对象所表示的类的一个实例。

Class.forName 方法只需要有类名就能得到该类对应的 Class 对象,而 newInstance 可以创建该类的对象。

于是我们可以从程序外部传入类名,这样程序就可以创建任意类的对象了。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

class Person {
private String name;

public Person() {
this("匿名");
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public void run(int meters) {
System.out.printf("%s 跑了 %d 米 %n", name, meters);
}

public String toString() {
return "姓名: " + name;
}

private void helper() {
System.out.println("私有的辅助方法");
}
}

public class ObjectFactory {
public static void main(String[] args) {
if(args.length < 1) {
System.exit(1);
}
try {
Class<?> clz = Class.forName(args[0]);
// 得到无参的公有构造方法
Constructor noArgCons = clz.getConstructor();
Object obj = noArgCons.newInstance();
System.out.println(clz);
System.out.println(obj);

if(args.length > 1) {
Class paramClz = args[1].getClass();
// 得到一个参数的公有构造方法
Constructor oneArgsCons = clz.getConstructor(paramClz);
obj = oneArgsCons.newInstance(args[1]);
System.out.println(obj);
}
} catch (ClassNotFoundException
| NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException
e ){
System.out.println(e.toString());
}
}
}

可以用 ObjectFactory 类创建任意类的对象,只要该类有无参的构造方法和带一个字符串参数的构造方法即可。

运行示例1:

1
java ObjectFactory Person 张三

运行结果:

1
2
3
class Person
姓名: 匿名
姓名: 张三

运行示例2:

1
java ObjectFactory java.lang.String 张三

运行结果:

1
2
3
class java.lang.String

张三

使用反射调用对象的方法

使用 Constructor 类可以实例化对象。

有了对象,就能够调用对象的方法,Method 类中定义了一个 invoke 方法,用来调用 Method 对象所表示的方法。I

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
31
32
33
34
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class MethodTest {
public static void main(String[] args) {
try {
Class<?> clz = Class.forName("Person");
// 得到一个参数的公有构造方法
Constructor oneArgsCons = clz.getConstructor(String.class);
Object obj = oneArgsCons.newInstance("张三");

// 得到 run 方法对应的 Method 对象
Method mth = clz.getMethod("run", int.class);
// 调用 run 方法
mth.invoke(obj, 800);

// 得到 helper 方法对应的 Method 对象
mth = clz.getDeclaredMethod("helper");
// helper 方法是私有方法,正常不可调用
// 通过调用 Method 对象的 setAccessible(true)
// 将 helper 方法设置为可访问的
mth.setAccessible(true);
mth.invoke(obj);
} catch ( ClassNotFoundException
| NoSuchMethodException
| InstantiationException
| IllegalAccessException
| InvocationTargetException
e ){
System.out.println(e.toString());
}
}
}

结果如下:

1
2
张三 跑了 800 米
私有的辅助方法

使用反射修改对象的字段

与使用 Method 类可以调用类中方法类似,使用 Field 类就可以访问类中的字段。

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
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;

public class FieldTest {
public static void main(String[] args) {
try {
Class<?> clz = Class.forName("Person");
// 得到一个参数的公有构造方法
Constructor oneArgsCons = clz.getConstructor(String.class);
Object obj = oneArgsCons.newInstance("张三");

// 得到字段 name
Field f = clz.getDeclaredField("name");
// name 是私有的
f.setAccessible(true);
f.set(obj, "李四");
System.out.println(obj);
f.setAccessible(false);
} catch ( ClassNotFoundException
| NoSuchMethodException
| NoSuchFieldException
| InstantiationException
| IllegalAccessException
| InvocationTargetException
e ){
System.out.println(e.toString());
}
}
}

运行结果:

1
姓名: 李四

Share