java反射的操作:
Class 类:代表一个类。
通过 getClasses()将类的成员变量包装成Class类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
通过getFields()将类的成员变量包装成Field类。
Method 类:代表类的方法。
通过getMethods()将类的方法包装成 Method类。
Constructor 类:代表类的构造方法。
通过getConstructors()将类的成员变量包装成 Constructor类。
获得Class的方法:
1)运用 对象.getClass()(注意:每个class 都有此函数)
String str = "abc";Class c1 = str.getClass();
2)运用 类名.class
Button b = new Button();
Class c1 = b.getClass();
3)运用 Class.forName()(最常被使用,通常情况下是之前在不知道类的情况使用)
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c5 = Class.forName (".class");
1. 得到某个对象的属性
public Object getProperty(Object owner, String fieldName) throws Exception {
Class ownerClass = owner.getClass();
Field field = ownerClass.getField(fieldName);
Object property = field.get(owner);
return property;
}
Class ownerClass = owner.getClass():得到该对象的Class。
Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。
Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
2. 得到某个类的静态属性
public Object getStaticProperty(String className, String fieldName)
throws Exception {
Class ownerClass = Class.forName(className);
Field field = ownerClass.getField(fieldName);
Object property = field.get(ownerClass);
return property;
}
Class ownerClass = Class.forName(className) :首先得到这个类的Class。
Field field = ownerClass.getField(fieldName):和上面一样,通过Class得到类声明的属性。
Object property = field.get(ownerClass) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。
3. 执行某对象的方法
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
Class ownerClass = owner.getClass();
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Method method = ownerClass.getMethod(methodName, argsClass);
return method.invoke(owner, args);
}
Class owner_class = owner.getClass() :第一步,还是必须得到这个对象的Class。
Class[] argsClass = new Class[args.length];第二步,配置参数的Class数组,作为寻找Method的条件。
Method method = ownerClass.getMethod(methodName, argsClass):通过Method名和参数的Class数组得到要执行的Method。
method.invoke(owner, args):执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既
是该方法的返回值。
4. 新建实例
public Object newInstance(String className, Object[] args) throws Exception {
Class newoneClass = Class.forName(className);
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);
}
这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。
Class newoneClass = Class.forName(className):第一步,得到要构造的实例的Class。
第二步,得到参数的Class数组。
Constructor cons = newoneClass.getConstructor(argsClass):得到构造子。
cons.newInstance(args):新建实例。
5. 判断是否为某个类的实例
public boolean isInstance(Object obj, Class cls) {
return cls.isInstance(obj);
}
6. 得到数组中的某个元素
public Object getByArray(Object array, int index) {
return Array.get(array,index);
注意:
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
7 . 执行某个类的main方法
Class clazz = Class.forName(arg[0]);
Method mMain = clazz.getMethod("main", String[].class);
mMain.invoke(null,new Object[]{new String[]{"aaa","bbb"}});
mMain.invoke(null,(Object)new String[]{"aaa","bbb"});
总结:
Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。
但反射有两个缺点。第一个是性能问题。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。