JAVA反射机制定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1、Class对象
1.1通过全限定名加载一个类,格式如下:
Class<?> clazz = Class.forName("com.test.reflect.ReflectTestClass");
1.2 取得父类
clazz.getSuperclass();
1.2 取得实现的接口:
clazz.getInterfaces();
2、实例化
通过Class.forName我们只是把一个类加载到了JVM中,并没有实例化这个类,要获得这个类的一个实例可以这个做:
clazz.newInstance()
此方法需要被实例的类有一个无参数的构造方法,否则会报错
3、方法
3.1 获得类中声明的方法,有两种方法可以获得一个类声明的方法,第一种是通过Class类的getDeclaredMethods,例如,我们定义一个类,代码如下:
package com.test.reflect;
public class ReflectTestClass {
public void publicMetod() {
}
void defaultMethod() {
}
protected void protectedMethod() {
}
private void testdMethod() {
}
}
然后通过getDeclaredMethods方法取得这个类声明的方法,打印结果如下:
publicMetod
defaultMethod
protectedMethod
testdMethod
我们看到,getDeclaredMethods可一取得你声明的所有方法,包括private权限的,但是没有获得从父类继续来的方法,还有一种方式是getMethods方法,使用这个方法得到的结果如下:
publicMetod
wait
wait
wait
hashCode
getClass
equals
toString
notify
notifyAll
我们看到,这次我们得到了从父类继承的方法,但是这个方法之能获得public权限的方法
3.2 获得方法声明的参数个数、类型、返回值以及执行方法
修改ReflectTestClass类,代码如下
package com.test.reflect;
public class ReflectTestClass {
public void test(String name , int age){
System.out.println("test被执行");
}
}
修改Test类,测试下怎么获得方法参数个数,类型返回值已经执行方法
package com.test;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.test.reflect.ReflectTestClass");
//要想执行一个方法,必须实例化这个方法
Object o = clazz.newInstance();
//获取类中声明的方法
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods){
String methodName = method.getName();
System.out.println("方法名字\t" + methodName);
//获取方法参数
Class<?>[] types = method.getParameterTypes();
System.out.println(methodName + "方法参数个数为" + types.length);
for(int i = 0 ; i < types.length ; i++){
System.out.println(methodName + "方法第" + (i + 1) + "个参数类型为:" + types[i].getName());
}
//返回值
System.out.println("methodName返回值是" + method.getReturnType().getName());
//执行方法,该方法返回值是Object,代表实际方法执行时的返回值,因为test方法返回值为void,所以在这里就没有对返回值进行处理
method.invoke(o, "str",10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
打印结果如下:
方法名字 test
test方法参数个数为2
test方法第1个参数类型为:java.lang.String
test方法第2个参数类型为:int
methodName返回值是void
test被执行
4、获取声明的字段
修改ReflectTestClass,加上几个字段,代码如下:
package com.test.reflect;
public class ReflectTestClass {
private int i = 10;
public String str = "str";
protected boolean b = true;
double d = 2.0;
public void publicMetod() {
}
void defaultMethod() {
}
protected void protectedMethod() {
}
private void testdMethod() {
}
}
然后我们定义一个测试类来测试下获取怎么获取字段,代码如下:
package com.test;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.test.reflect.ReflectTestClass");
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
System.out.println(field.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
执行测试类,结果如下:
i
str
b
d
结果显示,我们声明的字段全部都获得到了,Class也有一个getFields方法,如果换成使用这个方法,那么打印的结果就是下面这个:
str
可以看到,这个方法之能获得public|权限的字段,一般一个java类中很少会有字段声明为public方法,所以我觉得这个方法没什么太大的意义
5、获取构造函数
修改ReflectTestClass类,加上些构造函数:
package com.test.reflect;
public class ReflectTestClass {
private int i = 10;
public String str = "str";
protected boolean b = true;
double d = 2.0;
private ReflectTestClass(){
}
public ReflectTestClass(int i){
this.i = i;
}
public void publicMetod() {
}
void defaultMethod() {
}
protected void protectedMethod() {
}
private void testdMethod() {
}
}
然后修改Test类,测试获取构造方法
package com.test;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.test.reflect.ReflectTestClass");
Constructor<?>[] constructors = clazz.getConstructors();
for(Constructor constructor : constructors){
System.out.println("构造方法\t" + constructor.getName());
Class<?>[] types = constructor.getParameterTypes();
System.out.println("构造方法参数个数\t" + types.length);
for(Class type : types){
System.out.println("构造方法参数类型 \t" + type.getName());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
打印结果如下:
构造方法 com.test.reflect.ReflectTestClass
构造方法参数个数 1
构造方法参数类型 int
可以看到,我们只获得了public的构造方法,并且可以获得构造函数参数的个数和类型
简要的介绍点基础知识,java反射机制的内容很多,具体内容可以查看JDK的帮组文档。