反射浅解析

java反射机制的详解

反射是什么?

1
1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

注意,我们书写的java代码后缀都是.java,当代码被编译的时候.java文件会编译成.class文件,加载到JVM当中,此时反射机制会将其反编译,以来获取其中的信息。

1
2)通过反射的机制,可以访问java对象的属性,方法和构造方法等

反射的获取:

获取class对象的三种方法:

我们先写一个类对象:

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
package org.example.fanshe;

public class girlfrind {
public String name = "wangyuting";
public String gender = "女";
public int age = 18;
public int hight = 165;

public girlfrind(int age, String gender, int hight, String name) {
this.age = age;
this.gender = gender;
this.hight = hight;
this.name = name;
}

public girlfrind() {
System.out.println("无参构造");
}


private girlfrind(int age){
this.age = age;
}


protected girlfrind(int hight, String name) {
this.hight = hight;
this.name = name;
}

public String getName() {
return this.name;
}

private String getGender(){
return this.gender;
}

@Override
public String toString() {
System.out.println("我是to_string方法");
return "girlfrind{" +
"age=" + age +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", hight=" + hight +
'}';
}
}

第一种获取方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.example.fanshe;
import java.io.*;

public class fanshe {
public static void main(String[] args) {
//通过new一个对象来获取Class文件,来调用反射的机制
//不常用,都new一个类对象了,我们可以直接来操作了,就没必要使用反射机制了
girlfrind girl = new girlfrind();
Class girlClass = girl.getClass();
System.out.println(girlClass);
}
}

//运行结果
无参构造 //new时调用了无参构造
class org.example.fanshe.girlfrind

第二种获取方法:

1
2
3
4
5
6
7
8
9
10
package org.example.fanshe;
import java.io.*;

public class fanshe {
public static void main(String[] args) {
Class gir = girlfrind.class;
System.out.println(gir);
}
}
//这种需要频繁的导包,也不是很常用

第三种获取方法:

1
2
3
4
5
6
7
8
9
10
11
package org.example.fanshe;

import java.io.*;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException {
Class girl = Class.forName("org.example.fanshe.girlfrind"); //注意参数一定为该类的全限定类名
System.out.println(girl);
}
}
//这种是最常用的

获取构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.example.fanshe;

import java.io.*;
import java.lang.reflect.Constructor;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//Constructor[] constructor = girl.getDeclaredConstructors()获取其中的所有构造方法,无论共有,私有,还是保护的,存储在数组中

Constructor[] constructor = girl.getDeclaredConstructors();
for(Constructor c : constructor) {
System.out.println(c);
}
}
}

//运行结果
protected org.example.fanshe.girlfrind(int,java.lang.String)
private org.example.fanshe.girlfrind(int)
public org.example.fanshe.girlfrind()
public org.example.fanshe.girlfrind(int,java.lang.String,int,java.lang.String)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package org.example.fanshe;

import java.io.*;
import java.lang.reflect.Constructor;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//Constructor[] constructor = girl.getConstructors() 仅仅获取其中的共有方法

Constructor[] constructor = girl.getConstructors();
for(Constructor c : constructor) {
System.out.println(c);
}
}
}

//运行结果
public org.example.fanshe.girlfrind()
public org.example.fanshe.girlfrind(int,java.lang.String,int,java.lang.String)
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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//获取无参构造
Constructor constructor1 = girl.getConstructor(null);

//获取全参数构造,其中的参数类型要对应
Constructor constructor2 = girl.getConstructor(int.class,String.class,int.class,String.class);

//获取私有int构造
Constructor constructor3 = girl.getDeclaredConstructor(int.class);

System.out.println(constructor1);
System.out.println(constructor2);

}
}

//运行结果
public org.example.fanshe.girlfrind()
public org.example.fanshe.girlfrind(int,java.lang.String,int,java.lang.String)
private org.example.fanshe.girlfrind(int)

利用构造方法创建对象:

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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class girl = Class.forName("org.example.fanshe.girlfrind");
Constructor constructor1 = girl.getConstructor(null);
Constructor constructor2 = girl.getConstructor(int.class,String.class,int.class,String.class);
Constructor constructor3 = girl.getDeclaredConstructor(int.class);

//利用公有方法构造对象girl1
Object girl1 = constructor2.newInstance(18,"女",165,"sunrt");
System.out.println(girl1);

//利用私有方法构造对象girl2
constructor3.setAccessible(true); //忽略构造器的访问修饰符,解除私有限定
Object girl2 = constructor3.newInstance(18);
System.out.println(girl2);


//运行结果
girlfrind{age=18, name='sunrt', gender='女', hight=165}
girlfrind{age=18, name='wangyuting', gender='女', hight=165}

获取成员变量:

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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//获取公有的所有成员属性
Field[] fields = girl.getFields();
for (Field field : fields) {
System.out.println(field);
}

}
}

//运行结果
public java.lang.String org.example.fanshe.girlfrind.name
public java.lang.String org.example.fanshe.girlfrind.gender
public int org.example.fanshe.girlfrind.age
public int org.example.fanshe.girlfrind.hight

public int org.example.fanshe.girlfrind.age
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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//获取公有,私有,保护所有属性的的所有成员属性
Field[] fields = girl.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}


//可以获得所有的单个公私有保护成员方法
Field fields = girl.getDeclaredField("age");
fields.setAccessible(true); //忽略构造器的访问修饰符,解除私有限定
System.out.println(fields);


//也能用getField获取成员变量,但是得共有

}
}


//为了效果,我们在girlfrind类中添加了一个私有成员变量
//结果
public java.lang.String org.example.fanshe.girlfrind.name
public java.lang.String org.example.fanshe.girlfrind.gender
public int org.example.fanshe.girlfrind.age
public int org.example.fanshe.girlfrind.hight
private java.lang.String org.example.fanshe.girlfrind.chengji

public int org.example.fanshe.girlfrind.age

设置成员变量:

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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//获得int构造方法
Constructor girl_baby = girl.getDeclaredConstructor(int.class);
girl_baby.setAccessible(true);

//获得对象,利用构造方法设置年龄
Object girl_now = girl_baby.newInstance(20);
System.out.println(girl_now);

//获得属性
Field girl_baby_age = girl.getDeclaredField("age");
girl_baby_age.setAccessible(true);
//设置改变属性
girl_baby_age.set(girl_now,19);
System.out.println(girl_now);

}
}
//结果
girlfrind{age=20, name='wangyuting', gender='女', hight=165}
girlfrind{age=19, name='wangyuting', gender='女', hight=165}

获取成员方法:

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
66
67
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class girl = Class.forName("org.example.fanshe.girlfrind");


//获取公有的,包括继承的
Method[] methods = girl.getMethods();
for (Method method : methods) {
System.out.println(method);
}

System.out.println("\n");

//获得共有的,私有的,受保护的,但是不包括继承
Method[] method = girl.getDeclaredMethods();
for (Method meth : method) {
System.out.println(meth);
}

System.out.println("\n");

//获取单个的共有的,私有的,受保护的方法,getGender为函数名字,null为参数,这里无参
Method method123 = girl.getDeclaredMethod("getGender",null);
System.out.println(method123);

System.out.println("\n");
//也能有getMethod获取单个的函数,但是得共有
Method method1234 = girl.getMethod("toString",null);
System.out.println(method1234);



}
}

//运行结果
public java.lang.String org.example.fanshe.girlfrind.toString()
public java.lang.String org.example.fanshe.girlfrind.getName()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()


public java.lang.String org.example.fanshe.girlfrind.toString()
public java.lang.String org.example.fanshe.girlfrind.getName()
private java.lang.String org.example.fanshe.girlfrind.getGender()


private java.lang.String org.example.fanshe.girlfrind.getGender()


public java.lang.String org.example.fanshe.girlfrind.toString()

调用成员方法:

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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

//用反射声明类对象
Object girl_myfriend = girl.getConstructor(int.class,String.class,int.class,String.class).newInstance(18,"女",167,"sunruiting");

//获取toString方法,传递无参数
//getMethod只能获取公有的函数
Method method_to_string = girl.getMethod("toString",null);

//执行方法,获取返回值
Object obj = method_to_string.invoke(girl_myfriend,null);
System.out.println(obj);


System.out.println("\n");


//获取私有方法
Method method_pr = girl.getDeclaredMethod("getGender",null);
method_pr.setAccessible(true); // 设置私有可执行
Object obj2 = method_pr.invoke(girl_myfriend,null);
System.out.println(obj2);



}
}

//运行结果
我是to_string方法
girlfrind{age=18, name='sunruiting', gender='女', hight=167}




为了演示调用main方法的实列,我们在girlfrind对象里面加入了如下的main方法:

1
2
3
4
public static void main(String[] args) {
System.out.println("我是main方法");
System.out.println(Arrays.toString(args));
}

调用main方法

我们记住如下的话:

在 Java 中,通过反射调用 main 方法 不需要实例化类对象,因为 main 方法是一个 static 静态方法。静态方法属于类本身,不依赖于具体实例即可直接调用。

java声明数组的方法:

**数据类型[] 数组名 = {值1, 值2, 值3, …};**例如:String[] str = {"sunrt","wangyuting","yejiahui"};

也可以new String[]{"yeyey", "sisisiis"};

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
package org.example.fanshe;

import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class fanshe {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class girl = Class.forName("org.example.fanshe.girlfrind");

Method meth_main = girl.getMethod("main",String[].class);

//静态方法不用实例化对象,所以直接写null
//new String[]{"yeyey", "sisisiis"}声明数组
//(Object) new String[]{"yeyey", "sisisiis"}防止invoke函数解析错误,误以为是invoke(null,"yeyey", "sisisiis")

Object obj = meth_main.invoke(null,(Object) new String[]{"yeyey", "sisisiis"});


}
}
//运行结果
我是main方法
[yeyey, sisisiis]

反射如何使用

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
package org.example.fansheliyong;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class fansheshiyong {

public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

Class xClass = Class.forName(getValue("className"));
Object obj = xClass.getConstructor().newInstance();

Method method = xClass.getMethod(getValue("methodName"),null);
method.invoke(obj,null);


}

public static String getValue(String key) throws IOException {
//Properties 类是一个专门用于管理键值对配置信息的工具类
Properties pro = new Properties();

//FileReader 是一个用于从文件中读取字符流的类。它属于 java.io 包,是专门为读取文本文件(基于字符的文件,如 .txt 文件)设计的。
FileReader reader = new FileReader("D:\\fanshe.txt");
//加载到pro类中
pro.load(reader);

//System.out.println(pro);

reader.close();

return pro.getProperty(key);

}

}
//运行结果
test

D:\\fanshe.txt
className=org.example.fansheliyong.fan
methodName=test