Java 反射机制

万事万物皆对象

在java中类也是对象,是Class类的实例对象,这个对象称为该类的类类型

例如:现在有个类叫SmartTalk

java
1
2
3
4
5
6
7
8
9
10
11
12
13
class SmartTalk {

public String name;
public int age;

public void sayHello() {
System.out.println("hello");
}

private void sayHello(String hello){
System.out.println(hello);
}
}

如何去获取这个类的类类型呢?有以下三种方式:

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
public class ClassDemo {
public static void main(String[] args) {
//第一种方式,说明每一个类都默认含有一个静态的class对象
Class c1 = SmartTalk.class;
//第二种方式
SmartTalk smartTalk = new SmartTalk();
Class c2 = smartTalk.getClass();
System.out.println(c1 == c2);//true
//第三种方式
Class c3 = null;
try {
c3 = Class.forName("包名+SmartTalk");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c2 == c3);//true
//通过类类型获得实例对象
try {
SmartTalk smartTalk1 = (SmartTalk) c1.newInstance();
smartTalk1.sayHello();//hello
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

获取了类类型有什么用处呢?我们可以获取一个类的所有信息包括类名,属性,方法等,可以通过Field,Method等类来实现。

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
31
32
33
34
35
public class ClassUtil {
/**
* 打印该类的信息,通过反射机制,我们可以获得一个类的信息
*
* @param object 该类对象所属类的信息
*/
public static void printClassInfo(Object object) {
//要获取类的信息,首先获取类的类类型
Class c = object.getClass();
c.getName();//类的全称(包括包名)
System.out.println(c.getName());

Field[] fields = c.getDeclaredFields();//获取所有该类自己声明的属性(实例域)
for (Field filed : fields) {
Class fc = filed.getType();//获取属性类型的类类型
System.out.print(fc.getName()+" ");
System.out.println(filed.getName());
}


Method[] methods = c.getDeclaredMethods();//获取所有的public方法,包括父类继承而来的
c.getDeclaredFields();//获取所有该类自己声明的方法,不管访问去权限,不包含父类的方法
for (Method m : methods) {
Class returnType = m.getReturnType();//得到方法返回值类型的类类型
System.out.print(returnType.getName() + " ");
m.getName();//获取方法名称
System.out.print(m.getName() + "(");
Class[] params = m.getParameterTypes();//获取方法参数列表中的类的类类型
for (Class param : params) {
System.out.print(param.getName() + ",");
}
System.out.println(")");
}
}
}

当然了,我们还可以获得一个属性的或者方法的访问权限,通过getModifiers()方法。还有许多特性可以在官方文档里查阅。下面介绍如何通过反射进行方法调用:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
...

Class c1 = SmartTalk.class;//获得类类型
try {
/**
* 访问共有方法
*/
Method method1 = c1.getMethod("sayHello"/*方法名*/);//获得Method对象,或者使用c1.getDeclaredMethod("sayHello")
method1.invoke(c1.newInstance()/*类对象*/);//方法调用
/**
* 访问非共有方法
*/
Method method2 = c1.getDeclaredMethod("sayHello"/*方法名*/,String.class/*参数类类型*/);//不可使用getMethod(获取不到对象,抛出method not found)
method2.setAccessible(true);//调用私有方法时需要设置为true
method2.invoke(c1.newInstance()/*类对象*/,"hello,SmartTalk"/*参数对象*/);//方法调用
} catch (Exception e) {
e.printStackTrace();
}
}

通过代码里的注释,很清楚的展示出了反射机制方法调用的基本流程,java反射机制可以获取正在运行的java对象,改变其属性和行为,非常的灵活。这是一篇反射机制的学习笔记,如有错误,感谢批评指正。

Lei.Pan wechat
subscribe to my blog by scanning my public wechat account
万一有人想不开呢?