反射概念
java文件在编译后会变成.class文件,本身是.java,在镜中是.class,他们其实是一样的。我们看到镜子的反射是.class,就能通过反编译,了解到.java文件的本来面目。Java反射允许程序在运行时来进行自我检查并且对内部的成员进行操作。
它允许一个Java类获取它所有的成员变量和方法并且显示出来。反射主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
在Java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。这也是Java被视为动态语言的一个关键性质。
反射用途
我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等。但是需要注意的是反射使用不当会造成很高的资源消耗!
三种获取Class对象方法
public static void main(String[] args) {
//第一种方式获取Class对象
User user = new USer();//这一new 产生一个User对象,一个Class对象。
Class userClass = user.getClass();//获取Class对象
System.out.println(userClass.getName());
//第二种方式获取Class对象
Class userClass2 = User.class;
System.out.println(userClass == userClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
//第三种方式获取Class对象
try {
Class userClass3 = Class.forName("fanshe.User");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(userClass3 == userClass2);//判断三种方式是否获取的是同一个Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
一些class方法
/*
*得到某个对象的属性
*/
public Object getProperty(Object owner, String fieldName) throws Exception {
//得到该对象的Class
Class ownerClass = owner.getClass();
//通过Class得到类声明的属性
Field field = ownerClass.getField(fieldName);
//通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
Object property = field.get(owner);
return property;
}
/*
*得到某个类的静态属性
*/
public Object getStaticProperty(String className, String fieldName)throws Exception {
//得到这个类的Class
Class ownerClass = Class.forName(className);
//和上面一样,通过Class得到类声明的属性
Field field = ownerClass.getField(fieldName);
//这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取
Object property = field.get(ownerClass);
return property;
}
/*
*执行某对象的方法
*/
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
//得到这个对象的Class
Class ownerClass = owner.getClass();
//配置参数的Class数组,作为寻找Method的条件
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++){
argsClass[i] = args[i].getClass();
}
//通过methodName和参数的argsClass(方法中的参数类型集合)数组得到要执行的Method
Method method = ownerClass.getMethod(methodName,argsClass);
//执行这个方法。owner对象中带有参数args的method方法。返回值是Object,也既是该方法的返回值
return method.invoke(owner, args);
}
/*
*执行某个类的静态方法
*/
public Object invokeStaticMethod(String className, String methodName, Object[] args) throws Exception {
//得到这个对象的Class
Class ownerClass = Class.forName(className);
//配置参数的Class数组,作为寻找Method的条件
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
//通过methodName和参数的argsClass(方法中的参数类型集合)数组得到要执行的Method
Method method = ownerClass.getMethod(methodName,argsClass);
//这是静态方法,不需要借助实例运行。执行参数数组args的invoke()方法。
return method.invoke(null, args);
}
/*
*新建实例
*/
public Object newInstance(String className, Object[] args) throws Exception {
//得到要构造的实例的Class
Class newoneClass = Class.forName(className);
//得到参数的Class数组
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
//得到构造子
Constructor cons = newoneClass.getConstructor(argsClass);
//执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用
return cons.newInstance(args);
}
/*
*判断是否为某个类的实例
*/
public boolean isInstance(Object obj, Class cls) {
return cls.isInstance(obj);
}
/*
*得到数组中的某个元素
*/
public Object getByArray(Object array, int index) {
return Array.get(array,index);
}