抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

什么是java反射机制

Java 反射机制(Reflection)是一种在程序运行时动态地检查和操作类、方法、字段、构造函数等结构的技术。通过反射,程序可以在不知道对象具体类型的情况下,动态获取类的信息并操作对象。Java提供了一系列反射方法来操作(如获取、创建、修改、调用)Class对象、构造函数、方法、字段等。。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息

执行流程:Animal.java文件一一>Animal.class文件一一>类加载器加载到JVM中,JVM加载到内存中–>Animal.class就会有个对象表示

常用对象的反射

类反射

Class类的实例表示正在运行的Java应用程序中的类和接口

获取class对象:

第一种 使用class.forName ()静态方法:知道类的全路径名

第二种 使用 类名.class方法:适合在编译前知道操作的CLass:

第三种 使用 类对象.getClass()

第四种 ClassLoader的loaderclass(ClassName):动态加载类,ClassName指定要加载的类名。

1
2
3
4
5
6
7
8
9
10
11
12
// 1. 使用 Class.forName() 动态加载类
Class<?> clazz = Class.forName("com.example.MyClass");

// 2. 使用 类名.class
Class<?> clazz = MyClass.class;

// 3. 使用 对象.getClass()
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();

//4.ClassLoader
Class cl = ClassLoader.getSystemClassLoader().loadClass("com.example.MyClass");

通过类获取类实例

  • class.newInstrance():执行无参构造获取类实例,该方法要求class类有无参构造方法。
1
2
3
4
//1.获取类
Class cl = Class.forName("com.example.MyClass");
//执行类的无参构造方法来获取类实例(必须要求该类含有无参构造方法)
Object o = cl.newInstance();

构造方法反射

类的单个构造方法的信息以及对它的动态访问权限

获取构造方法

  • class.getConstructor(...ParameterTypes):获取class类中的public权限的构造方法,ParameterTypes指定所获取的构造方法中的参数的类型,没有则表示无参。
  • class.getConstructors():获取class类中的所有public权限的构造方法。
  • class.getDeclaredConstructor(...ParameterTypes) :获取class类中的任意构造方法。
  • class.getDeclaredConstructors():获取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
//1. 获取无参构造方法
Constructor constructor = cl.getConstructor();
System.out.println(constructor);
/*
输出:
public com.example.uu.Test()
*/

//2. 获取带一个参数且为string类型的构造方法
Constructor constructor = cl.getConstructor(String.class);
System.out.println(constructor);
/*
输出:
public com.example.uu.Test(java.lang.String)
*/

//3. 获取该类的所有构造方法
Constructor[] constructors = cl.getConstructors();
for (Constructor con:constructors) {
System.out.println(con);
System.out.println(con.getName() + "||" + con.getModifiers() + "||"
+ Arrays.toString(con.getParameters()) + "||"
+ Arrays.toString(con.getParameterTypes()));
}
/*
输出
public com.example.uu.Test(java.lang.String)
com.example.uu.Test||1||[java.lang.String arg0]||[class java.lang.String]
public com.example.uu.Test()
com.example.uu.Test||1||[]||[]
*/

通过构造方法获取类实例

  • constructor.newInstance(...args):通过constructor构造方法构造类实例对象,根据获取到的constructor构造方法来决定是否需要传入参数args
  • constructor.setAccessible(bool):设置constructor构造函数的访问权限,若bool为true则表示取消构造函数的访问权限控制,这意味着private声明的构造函数也可以进行访问。
1
2
3
4
5
6
7
8
9
//1.无参构造
Class cl = Class.forName("com.example.uu.Test");//获取类
Constructor constructor = cl.getConstructor();//通过类获取无参构造方法
Object o = constructor.newInstance();//执行构造方法获得类实例

//2.有参构造
Class cl= Class.forName("com.example.uu.Test");//获取类
Constructor constructor = cl.getConstructor(String.class);///获取带一个参数且参数类型为String类型的构造方法
Object obj = constructor.newInstance("aaaaaaaaaaaaaaaa");//执行构造方法获得类实例

字段反射

Field提供有关类或接口的单个字段信息以及动态访问权限

获取字段

  • class.getField(FieldName) :获取class类中的带public声明的FieldName变量。
  • class.getFields():获取class类中的带public声明变量。
  • class.getDeclaredField(FieldName):获取class类中的FieldName变量。
  • class.getDeclaredFields():获取class类中的所有变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//1. 获取该类的publicStr字段
Field field = cl.getField("publicStr");//只能获取public声明的变量,获取privateStr失败
System.out.println(field);
/*
输出:
public java.lang.String com.example.uu.Test.publicStr
*/
//2.获取该类中所有字段
Field[] declaredFields = cl.getDeclaredFields();
for(Field dec : declaredFields){
System.out.println(dec);
}
/*
public java.lang.String com.example.uu.Test.publicStr
private java.lang.String com.example.uu.Test.privateStr
com.test.wtf.Dog com.example.uu.Test.dog
*/

操作字段

  • field.getXxx(obj):获取obj对象的field字段的属性值。Xxx代指8个基本数据类型,如果该属性类型是引用类型则直接使用Field.get(obj)
  • field.setXxx(obj, value):将obj对象的Field字段赋值为valueXxx代指8个基本数据类型,如果该字段类型是引用类型则直接使用Field.set(obj, value)
  • field.setAccessible(bool):设置field字段的访问权限,若bool为true则表示取消字段的访问权限控制,这意味着private声明的字段也可以进行访问。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//1.获取类
Class cl= Class.forName("com.example.uu.Test");
//2.获取构造函数
Constructor constructor = cl.getConstructor(String.class);
//3.创建类对象
Object newtest = constructor.newInstance("ousasf");
//4.获取privateStr字段
Field privateStr = cl.getDeclaredField("privateStr");
//5.因为该字段是Private权限,所以需要取消属性的访问权限控制
privateStr.setAccessible(true);
System.out.println(privateStr.get(newtest));
//6.修改privateStr字段的值
privateStr.set(newtest,"ahlsdfjpasp");
System.out.println(privateStr.get(newtest));
/*
输出:
abc
ahlsdfjpasp
*/

方法反射

Method提供关于类或接口上单独某个方法的信息

获取方法

  • class.getMethod(MethodName,...ParameterTypes):获取class类中的public权限的方法,MethodName指定所要获取的方法的方法名,ParameterTypes指定所获取的方法中的参数的类型,没有则表示无参。
  • class.getMethods():获取class类中所有public权限的方法。
  • class.getDeclaredMethod(MethodName,...ParameterTypes):获取class类中任意方法。
  • class.getDeclaredMethods():获取class类的所有方法。
1
2
3
//获取带一个参数的且为int类型的getPublicStr方法
Method method = cl.getMethod("getPublicStr",int.class);
System.out.println(method);

执行方法

  • method.invoke(obj,...args):调用obj对象的method方法,args指定传入的参数,没有则表示无参。
  • method.setAccessible(bool):设置method方法的访问权限,若bool为true则表示取消方法的访问权限控制,这意味着private声明的方法也可以被调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.获取类
Class cl= Class.forName("com.example.uu.Test");
//2.获取带一个参数且为String类型的构造方法
Constructor constructor = cl.getConstructor(String.class);
//3.通过构造方法,构造类对象
Object newtest = constructor.newInstance("abcdedfg");
//4.获取getPublicStr()方法
Method method = cl.getDeclaredMethod("getPublicStr");
System.out.println(method);
//5.取消访问控制
//method.setAccessible(true);
//6.调用该方法
System.out.println(method.invoke(newtest));
/*
输出:
public java.lang.String com.example.uu.Test.getPublicStr()
abcdedfg
*/

评论