理解java反射首先要知道程序运行时jvm做了什么。我们写完一个java 文件,经过编译生成.class文件,当程序运行时,jvm首先将.class文件载入到内存,返回一个该类的类对象。
然后我们就可以用Class的api了。
我们可以这样得到jvm产生的类对象:
1、Class clazz = Class.forName("此处写类的全限定名");
2、Class clazz = obj.class;
3、Class clazz = obj.getClass();
当得到这个类对象后,我们就可以用java.lang.reflect包下的api来对这个类对象进行操作了,而在反射这个包下,有许多用来描述一个类对象中的形形色色的东西的类,比如Field类描述一个类中的属性,Method类用来描述一个类中的方法等等。可以这样理解,我们可以将这个类对象大卸八块,每一块都可以用reflect包下的api类来描述,这样我们就可以反过来对类进行操作了,反射大概就是这个意思了。
看例子:
/**
* 需求:获取类的属性信息
* 实现方式:借助Field类存储相关信息并使用
* 要点: 私有属性的访问方式
*/
public class Example04 {
public static void main(String[] args) throws Exception {
Class clazz = BaseClass.class;
Field[] allField = clazz.getDeclaredFields();
for(Field f : allField){
System.out.println(Modifier.toString(f.getModifiers()));
}
BaseClass base = new BaseClass(1,"xx",30,3);
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);
System.out.println(f.get(base));
f.set(base, "helloKitty");
System.out.println(f.get(base));
}
}
/**
* 需求:获取类内的方法信息
* 实现方式:使用Method对象进行封装
* 要点:重点看如何使用Method调用指定对象的方法
*/
public class Example05 {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("Reflect.BaseClass");
Method[] all = clazz.getDeclaredMethods();
for(Method m : all){
System.out.print(m.getReturnType().getSimpleName());
System.out.print(" "+m.getName()+"(");
Class[] allPara = m.getParameterTypes();
for(Class c : allPara){
System.out.print(c.getSimpleName()+" ");
}
System.out.println(")");
}
BaseClass b = new BaseClass();
Method fun1 = clazz.getDeclaredMethod("fun1", new Class[]{});
fun1.invoke(b, new Object[]{});
Method fun2 = clazz.getDeclaredMethod("fun2", int.class,String.class);
Object result = fun2.invoke(b, 3000,"abx");
System.out.println(result);
}
}
/**
* 需求:获取类内的方法信息
* 实现方式:使用Method对象进行封装
* 要点:重点看如何使用Method调用指定对象的方法
*/
public class Example05 {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("Reflect.BaseClass");
Method[] all = clazz.getDeclaredMethods();
for(Method m : all){
System.out.print(m.getReturnType().getSimpleName());
System.out.print(" "+m.getName()+"(");
Class[] allPara = m.getParameterTypes();
for(Class c : allPara){
System.out.print(c.getSimpleName()+" ");
}
System.out.println(")");
}
BaseClass b = new BaseClass();
Method fun1 = clazz.getDeclaredMethod("fun1", new Class[]{});
fun1.invoke(b, new Object[]{});
Method fun2 = clazz.getDeclaredMethod("fun2", int.class,String.class);
Object result = fun2.invoke(b, 3000,"abx");
System.out.println(result);
}
}
public class Example06 {
public static void main(String[] args) throws Exception{
Class clazz = Class.forName("Reflect.BaseClass");
Constructor[] allcon = clazz.getConstructors();
//后去指定的构造器
Constructor c = clazz.getConstructor(int.class,String.class,double.class,double.class);
BaseClass obj = (BaseClass)c.newInstance(new Integer(100),
"xiaoming",
new Double(100.0),
new Double(3.0));
obj.printInfo();
}
}
下面是一个拷贝属性的方法:
public class BeanUtil {
public static void copyProperties(Object source,Object target) throws Exception{
Class sourceClass = source.getClass();
Class targetClass = target.getClass();
Field[] sourceFields = sourceClass.getDeclaredFields();
for(Field f : sourceFields){
String sourceFieldName = f.getName();
Field targetField = null;
try {
targetField = targetClass.getDeclaredField(sourceFieldName);
} catch (SecurityException e) {
break;
} catch (NoSuchFieldException e) {
continue;
}
if(f.getType() == targetField.getType()){
String getMethodName = "get" + sourceFieldName.substring(0,1).toUpperCase()
+ sourceFieldName.substring(1);
String setMethodName = "set" + sourceFieldName.substring(0,1).toUpperCase()
+ sourceFieldName.substring(1);
// 构造get、set方法的对象,并调用
Method getMethod = sourceClass.getDeclaredMethod(getMethodName, new Class[]{});
Method setMethod = targetClass.getDeclaredMethod(setMethodName, f.getType());
Object result = getMethod.invoke(source, new Object[]{});
setMethod.invoke(target, result);
}
}
}
}