一、反射
1、反射简介
Java语言反射提供了一种动态链接程序组建的多功能方法,允许程序创建和控制任何类的对象(根据安全性限制),是不是很厉害,我们无需提前硬编码目标类。这些特性是的反射特别适用于创建以非常普通的方式与对象协作的库。
例如,反射经常在持续存储对象为数据库、XML或者其他外部格式的框架中使用。
Java Reflection非常有用,它使类和数据结构能按照名称动态检索相关信息,并允许在运行着的程序中操作这些信息。JAVA这一特性非常强大,这也是其他一些常用语言所不具备的(如C、C++、Pascal等)
但反射有两个缺点:
第一就是性能问题,用于字段肯方法接入时反射要远慢于直接代码。性能问题的程序主要取决于程序中是如何使用它的。如果它作为程序运行中很少涉及的部分,将不是个问题。即使测试环境下计时图显示的反射操作也只是耗时几微秒。反射的性能主要应用在核心逻辑中才至关重要。
很多应用中最严重的一个缺点是使用反射会模糊程序内部实际要发生的事情,程序人员希望在程序中看到代码实现程序的逻辑,但反射绕过了源代码的技术会带来维护问题,反射代码比相应的直接代码更复杂,就像性能比较的代码实例中看到的一样,解决这些问题的最佳方法是保守的使用反射,——仅在它可以真正增加灵活性的地方——记录在目标类中的使用。
Reflection是Java程序开发语言的特征之一,Reflection允许运行中的Java程序对自身进行检查,说直白点就是自省、自审。并能直接操作程序的内部属性。如:使用Reflection可以获得Java类中各成员的名称并显示出来。
JAVA的这一能力在实际应用中也许用的不是很多,但在其他语言中根本不存在这一特性,记住反射是Java独有的。
JavaBean是Reflection的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过Reflection动态的载入并获取Java组件类的属性。
2、一个简单的例子
来看下Reflection是如何工作的
输入结果为:
这样就列出了java.util.Stack类中的各方法名以及他们的限制符和返回类型。
java.lang.reflect.Method是用来描述某个类中单个方法的一个类。
3、使用Reflection
用于Reflection的类,如Method,可以在java,lang.relfect包中找到。使用这些类时必须遵循三个步骤:
第一:获得你想操作的类的java.lang.Class对象,在运行中的Java程序中,用java.lang.Class类来描述类和接口。
1:Class c = Class.forName("java.lang.String");
得到String类的类对象。
2:Class c = int.class;
或者
3:Class c = Integer.TYPE
他们获得基本类型的类信息,其中后一种方法中访问的是基本类型的封装类中定义好的TYPE字段。
第二:调用如GetDeclaredMethods的方法,获取类中定义在所有方法的列表。
获取到之后,
第三:使用Reflection API来操作这些信息。
Method m[]= c.getDeclaredMethods();
System.out.println(m[i].toString());
打印出String中定义的第一个方法的原型。
模拟instanceof操作符
得到类的信息后,通过Class对象解决一些基本的问题
public class ReflectionDemo {
public static void main(String[] args) {
try {
Class c = Class.forName(args[0]);
Method m[]= c.getDeclaredMethods();
for(int i = 0; i<m.length;i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.out.println(e);
}
Class cls = Class.forName("A");
boolean b1 = cls.isInstance(new Integer(37));
System.out.println(b1);
boolean b2 = cls.isInstance(new A());
System.out.println(b2);
}
}
这个例子创建了一个A类的Class对象,然后检查一些对象是否是A的实例。Integer不是,NEW A是。
4、找出类的方法
找出一个类中定义了些什么方法是非常有价值的。
下面我们来通过Reflection实现一下:
package com.cn;
import java.lang.reflect.Method;
public class method1{
private int f1(Object p, int x) throws NullPointerException{
if(p==null)
{
throw new NullPointerException();
}
return x;
}
public static void main(String[] args) {
try {
Class cls = Class.forName("method1");
Method mList[] = cls.getDeclaredMethods();
for(int i =0 ;i<mList.length;i++)
{
Method m = mList[i];
System.out.println("name="+m.getName());
System.out.println("decl Class = "+m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for(int j = 0;j<pvec.length; j++)
{
System.out.println("param#"+j+""+pvec[j]);
System.out.println("return type = "+m.getReturnType());
Class evec[] = m.getExceptionTypes();
for(int n =0 ;n<evec.length; n++)
{
System.out.println("exc #"+j+""+evec[n]);
System.out.println("return type ="+m.getReturnType());
System.out.println("-----------------");
}
}
}
} catch (Throwable e) {
System.out.println(e);
}
}
}
jdk1.8不支持反射?java.lang.ClassNotFoundException
5、获取构造器信息
6、获取类的字段
7、根据方法名称来执行方法
8、创建新的对象
9、改变字段的值
Reflection改变字段的值:
10、 使用数组
二、反射精讲