java反射基础(一)

Java反射

1、什么是Java反射

参考:https://xz.aliyun.com/t/9117

Java提供了一套反射API,该API由Class类与java.lang.reflect类库组成。

该类库包含了Field、Method、Constructor等类。

对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。

2、为什么要用到反射

参考:https://xz.aliyun.com/t/9117

其实从官方定义中就能找到其存在的价值,在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可)

3、反射机制应用

开发应用场景:

Spring框架的IOC基于反射创建对象和设置依赖属性。

SpringMVC的请求调用对应方法,也是通过反射。

JDBC的Class#forName(String className)方法,也是使用反射。

安全应用场景:

构造利用链,触发命令执行

反序列化中的利用链构造

动态获取或执行任意类中的属性或方法

动态代理的底层原理是反射技术

rmi反序列化也涉及到反射操作

#Java-反射-Class对象类获取普通用户我们可以采用以下方法创建实例:

1
Person test = new Person();

而我们在创建class类的实例对象却不能使用上述方法,运行会抛出错误

1
Class test = new Class();

跟进Class类的源码进行查看,发现其构造器是私有的,所以只有JVM能够创建Class对象。

因为Class类是private私有属性,我们也无法通过创建对象的方式来获取class对象,那么我们怎样才能够获取到class对象呢?一般我们获取class对象就有以下几种方法,我们来逐一看看。

1
2
3
4
5
6
7
8
9
10
//1、根据类名:类名.class
Class userClass =User.class;
//2、根据对象:对象.getClass()
User user =new User();
Class aClass = user.getClass();
//3、根据全限定类名:Class.forName("全路径类名")
Class aClass1 =Class.forName("com.example.reflectdemo.User");
//4、通过类加载器获得Class对象://ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader clsload=ClassLoader.getSystemClassLoader();
Class aClass2 = clsload.loadClass("com.example.reflectdemo.User");

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ReflectTemo {  
public static void main(String[] args) throws ClassNotFoundException {
//1、类的.class属性
Class c1 = ReflectTemo.class;
System.out.println(c1.getName());

//2、实例化对象的getClass()方法
ReflectTemo demo = new ReflectTemo();
Class c2 = demo.getClass();
System.out.println(c2.getName());

//3、Class.forName(String className): 动态加载类
Class c3 = Class.forName("org.example.ReflectTemo");
System.out.println(c3.getName());
//4、通过类加载器获得Class对象://ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader c4=ClassLoader.getSystemClassLoader();
Class aClass2 = c4.loadClass("org.example.ReflectTemo");
System.out.println(aClass2.getName());
}
}

#Java-反射-Field成员变量类获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Class aClass = Class.forName("com.example.reflectdemo.User");
//获取公共成员变量对象
// Field[] fields=aClass.getFields();
// for(Field f:fields){
// System.out.println(f);
// }
//获取所有成员变量对象
// Field[] fields=aClass.getDeclaredFields();
// for(Field f:fields){
// System.out.println(f);
// }
//获取公共,私有单个成员变量对象
// Field field=aClass.getField("age");
// Field field=aClass.getDeclaredField("gender");
// System.out.println(field);
//城边变量值获取和赋值
// User u = new User();
// Field field=aClass.getField("age");
// field.set(u,30);
// Object a=field.get(u);
// System.out.println(a);

实现代码

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
public class ReflectTemo {
public String name;
public String profession;
protected int age;
private String number;
char sex;
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class aClass = Class.forName("org.example.ReflectTemo");
// 获取公共成员变量对象
Field[] fields = aClass.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("-------分割线---------");
// 获取所有成员变量对象
Field[] fields1 = aClass.getDeclaredFields();
for (Field f : fields1) {
System.out.println(f);
}
System.out.println("-------分割线---------");
// 获取公共,私有单个成员变量对象
Field field = aClass.getField("name");
Field field1 = aClass.getDeclaredField("number");
System.out.println(field.getName());
System.out.println(field1.getName());
System.out.println("-------分割线---------");
// 获取指定成员变量
Field field2 = aClass.getDeclaredField("age");
System.out.println(field2);
}
}

Java-反射-Method成员方法类获取

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
//Class aClass = Class.forName("com.example.reflectdemo.User");
//返回所有公共成员方法对象的数组,包括继承的
// Method[] methods = aClass.getMethods();
// for (Method me:methods){
// System.out.println(me);
// }
//返回所有成员方法对象的数组,不包括继承的
// Method[] methods = aClass.getDeclaredMethods();
// for (Method me:methods){
// System.out.println(me);
// }
//返回单个公共成员方法对象
// Method methods = aClass.getMethod("getName");
// System.out.println(methods);
// Method methods = aClass.getMethod("setName", String.class);
// System.out.println(methods);
//返回单个成员方法对象
// Method methods = aClass.getDeclaredMethod("UserInfo", String.class, int.class, String.class);
// System.out.println(methods);
//运行方法invoke
// Method methods = aClass.getDeclaredMethod("UserInfo", String.class, int.class, String.class);
// User u = new User();
// //私有需要开启临时
// methods.setAccessible(true);
// methods.invoke(u,"calmsec",18,"man");
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
public class ReflectTemo {
public void study(String s) {
System.out.println("学习中..." + s);
}

protected void run() {
System.out.println("跑步中...");
}

void eat() {
System.out.println("吃饭中...");
}

private String sleep(int age) {
System.out.println("睡眠中..." + age);
return "sleep";
}

public static void main(String[] args) {
try {
Class c = Class.forName("org.example.ReflectTemo"); // 创建Class对象
Method[] methods1 = c.getDeclaredMethods(); // 获取所有该类中的所有方法
Method[] methods2 = c.getMethods(); // 获取所有的public方法,包括类自身声明的public方法,父类中的public方法、实现的接口方法

for (Method m:methods1) {
System.out.println(m);
}

System.out.println("-------分割线---------");

for (Method m:methods2) {
System.out.println(m);
}

System.out.println("-------分割线---------");

Method methods3 = c.getMethod("study", String.class); // 获取公有方法
System.out.println(methods3);
System.out.println("-------分割线---------");

Method method4 = c.getDeclaredMethod("sleep", int.class); // 获取私有方法
System.out.println(method4);

} catch (Exception e) {
e.printStackTrace();
}
}
}

#Java-反射-Constructor构造方法类获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Class aClass = Class.forName("com.example.reflectdemo.User");
//返回所有公共构造方法对象的数组
// Constructor[] constructors = aClass.getConstructors();
// for(Constructor con:constructors){
// System.out.println(con);
// }
//返回所有构造方法对象的数组
// Constructor[] constructors = aClass.getDeclaredConstructors();
// for(Constructor con:constructors){
// System.out.println(con);
// }
//返回单个公共构造方法对象
// Constructor con1=aClass.getConstructor();
// Constructor con1=aClass.getConstructor(String.class);
// System.out.println(con1);
//返回单个构造方法对象
// Constructor con2=aClass.getDeclaredConstructor(int.class);
//Constructor con2=aClass.getDeclaredConstructor(String.class,int.class, String.class);
// System.out .println(con2);
// Constructor con2=aClass.getDeclaredConstructor(int.class);
// con2.setAccessible(true);
// User uu=(User) con2.newInstance("calmsec",30,"man");
// System.out.println(uu);
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
public class ReflectTemo {
public ReflectTemo() {
System.out.println("无参构造函数");
}
public ReflectTemo(String name) {
System.out.println("有参构造函数" + name);
}
private ReflectTemo(boolean n) {
System.out.println("私有构造函数");
}
public static void main(String[] args) {
try {
Class c1 = Class.forName("org.example.ReflectTemo");
Constructor[] constructors1 = c1.getDeclaredConstructors();
Constructor[] constructors2 = c1.getConstructors();
for (Constructor c : constructors1) {
System.out.println(c);
}
System.out.println("-------分割线---------");
for (Constructor c : constructors2) {
System.out.println(c);
}
System.out.println("-------分割线---------");
Constructor constructors3 = c1.getConstructor(String.class);
System.out.println(constructors3);
System.out.println("-------分割线---------");
Constructor constructors4 = c1.getDeclaredConstructor(boolean.class);
System.out.println(constructors4);
} catch (Exception e) {
e.printStackTrace();
}
}
}