反射
2017-04-13 本文已影响27人
风吹稻子
1.什么是反射?
“听其声,问其人”,就是根据声音,我们可以知道这个人。而反射就是“根据当前类,获取这个类的属性和方法以及构造器”。
比如我们知道一个类名Person,但不知道Person类的方法,属性以及构造器。如果我们想知道Person类到底有什么方法、属性、构造器?怎么办呢?那就使用反射。
2.为什么要用反射?
1. 判断运行时对象所属的类
2. 判断运行时对象所具有的成员变量和方法
3. 甚至可以调用到private的方法
4. 生成动态代理
3.什么是动态代理?
4.使用反射的步骤
- 首先获取一个类的Class对象
- 用这个对象来调用相应的方法获取属性、构造器和方法。
注意:三个重要的反射类,Filed、Constructor、Method
5.获取Class对象的方式
- “.class”方法:在知道类型的情况下使用,比如boolean.class
- "Object.getClass()":在知道对象的情况下使用,比如:new Date().getClass
- "Class.forName()":在知道类的全名下使用,比如“java.lang.String”.但是这种方法不能用在基本类型上,但可以用在基本类型的数组上。而且此类在使用的基础上,会抛出异常。
代码示例:
package reflection;
import java.util.Date;
public class TestReflection {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("第一种方法:Object.getClass()");
Class c1 = new Date().getClass();
System.out.println(c1.getName());// 输出对象名称
System.out.println("第二种方法:.class语法");
Class c2 = boolean.class;
System.out.println(c2.getName());
System.out.println("第三种方法:Class.forName()");
Class c3 = Class.forName("java.lang.String");
System.out.println(c3.getName());
System.out.println("第四种方法:包装类的Type域");
Class c4 = Double.TYPE;
System.out.println(c4.getName());
}
}
结果:
第一种方法:Object.getClass()
java.util.Date
第二种方法:.class语法
boolean
第三种方法:Class.forName()
java.lang.String
第四种方法:包装类的Type域
double
说明:
TYPE:每个基本数据类型和void都有包装类,利用TYPE就可以获取Class对象
getName():查看各种类型对象的名称,可以根据这些名称判断原来对象的类型
6.奇怪的数组类型
// 奇怪的数组类型
String array = new int[4].getClass().getName();
String array2 = new int[4][4].getClass().getName();
System.out.println("一维基本类型数组" + array);
System.out.println("二维基本类型数组" + array2);
System.out.println("使用getCanonicalName()方法可以直接获取数组");
String arrayCopy = new int[4].getClass().getCanonicalName();
String arrayCopy2 = new int[4][4].getClass().getCanonicalName();
System.out.println("一维基本类型数组" + arrayCopy);
System.out.println("二维基本类型数组" + arrayCopy2);
测试结果:
一维基本类型数组[I
二维基本类型数组[[I
使用getCanonicalName()方法可以直接获取数组:
一维基本类型数组int[]
二维基本类型数组int[][]
说明:
1.一维数组和二维数组对象类型是“[”组成
2.可以直接使用getCanonicalName()方法获取直观的数组类型
获取类的一些基本信息
package reflection;
import java.lang.reflect.Modifier;
public class TestReflection {
private String name;
private boolean b;
private int[] age;
//方法
public int info(int a) {
return a;
}
public static void main(String[] args) throws ClassNotFoundException {
// 获取类名
Class c1 = TestReflection.class;
Class c2 = Class.forName("reflection.TestReflection");
System.out.println("类名" + c1);
// 获取指定的包名
String package1 = c1.getPackage().getName();
System.out.println("包名:" + package1);
// 获取类的修饰符,注意修饰符返回的是数字0,1,2
int mod = c1.getModifiers();
String modifier = Modifier.toString(mod);
System.out.println("修饰符:" + modifier);
// 获取父类
Class superClazz = c1.getSuperclass();
String superClazzName = superClazz.getName();
System.out.println("父类:" + superClazzName);
// 获取实现的接口
Class[] interfaces = c1.getInterfaces();
for (Class i : interfaces) {
System.out.println("接口名" + i.getName());
}
}
}
测试结果:
类名class reflection.TestReflection
包名:reflection
修饰符:public
父类:java.lang.Object
获取成员变量
// 获取指定类的成员变量
Field[] fields = c1.getDeclaredFields();
for(Field f : fields){
//获取每一个变量的修饰符
int modf = f.getModifiers();
String modifiers = Modifier.toString(modf);
//获取类型
Class type = f.getType();
String typeName = type.getName();
//获取变量名
String name = f.getName();
System.out.println("变量名:"+name+" 类型:"+typeName+" 修饰符:"+modifiers);
测试结果:
变量名:name 类型:java.lang.String 修饰符:private
变量名:b 类型:boolean 修饰符:private
变量名:age 类型:[I 修饰符:private
获取构造方法
//获取构造方法
Constructor[] constructor = c1.getDeclaredConstructors();
for(Constructor construct : constructor){
//这里只获取了名字,修饰符,参数与上大致相同
String conName = construct.getName();
System.out.println("构造方法的名字:"+conName);
}
测试结果:
构造方法的名字:reflection.TestReflection
获取成员方法
// 获取成员方法
Method[] methods = c1.getDeclaredMethods();
for (Method m : methods) {
// 获取方法的修饰符
int modm = m.getModifiers();
String modName = Modifier.toString(modm);
// 获取返回值类型
Class returnType = m.getReturnType();
String returName = returnType.getName();
if (returnType.isArray()) {
//returName = returnType.getClass().getCanonicalName();
returName = returnType.getComponentType().getName();
}
// 获取方法名
String methodName = m.getName();
System.out.println("方法名:" + methodName + " 方法修饰符:" + modName + " 方法的返回类型" + returName);
// 获取参数相关信息
Class[] parameter = m.getParameterTypes();
for (Class p : parameter) {
// 获取参数的类型
String paramType = p.getTypeName();
// 获取参数名
String paramName = p.getName();
System.out.println(methodName + "方法的参数名:" + paramName + " 参数的类型:" + paramType);
}
System.out.println("-------------------------");
}
测试结果:
方法名:main 方法修饰符:public static 方法的返回类型void
main方法的参数名:[Ljava.lang.String; 参数的类型:java.lang.String[]
-------------------------
方法名:info 方法修饰符:public 方法的返回类型int
info方法的参数名:int 参数的类型:int
info方法的参数名:boolean 参数的类型:boolean
-------------------------