反射浅析

来源:互联网 发布:win7电脑连接网络 编辑:程序博客网 时间:2024/06/14 00:13
java里万物皆对象,(静态)成员变量、普通数据类型、方法、构造函数都是对象,甚至是void关键字也是对象,它们都是java.lang.Class类的实例对象,比如Class c1 = int.class;
Class c2 = Double.class;   Class c3 = void.class;

有三中表示方式:
1.Class c1 = 类名.class;
2.通过类的对象:Class c2 = 类的一个对象.getClass();
3.Class c3 = null; c3 = Class.forName("类的全称");

java.land.Constructor
java.land.Field
java.land.Method 封装了这些对象的信息

要得到类的信息,先得到该类的类类型(class type)

方法的反射
方法的名称和方法的参数列表才能唯一决定某个方法。

方法反射的操作:先得到方法对象method,再用method.invoke(对象,参数列表)操作方法。


下面用一个例子展示利用反射得到类的变量、构造方法和方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {

public static void main(String[] args) {
ReflectTest.printClassMessage(new Integer("123"));
}

/**
* 该方法简单打印一个类自己声明定义的变量、构造方法、方法
* @param obj
*/
public static void printClassMessage(Object obj) {
getFieldMessage(obj);
getConMessage(obj);
getMethodMessage(obj);
}


public static void getFieldMessage(Object obj) {
Class c1 = obj.getClass();//得到传入对象的类类型
//Field[] fs = c1.getFields();//得到该类的public变量
Field[] fs =  c1.getDeclaredFields();//得到该类自己声明的所有变量
for (Field field : fs) {
Class fieldType = field.getType();//得到该类的变量类型的类类型
String TypeName = fieldType.getName();//得到该类变量的类型名称
String fieldName = field.getName();//得到该类的变量名称
System.out.println(TypeName + " " + fieldName);
}
}

public static void getConMessage(Object obj) {
Class c2 = obj.getClass();
//Constructor[] cs = c2.getConstructors();//得到该类的public构造方法
Constructor[] cs = c2.getDeclaredConstructors();//得到该类所有自己声明的构造方法
for (Constructor constructor : cs) {
System.out.print(constructor.getName() + "(");
//得到该构造方法参数列表的类类型
Class[] paramType = constructor.getParameterTypes();
//得到该构造方法参数列表的类型的名称
for (Class class1 : paramType) {
String paramTypeName = class1.getSimpleName();
System.out.print(paramTypeName + " ");
}
System.out.println(")");
}
}

public static void getMethodMessage(Object obj) {
Class c3 = obj.getClass();
//Method[] ms = c3.getMethods();//得到该类的public方法和从父类继承的方法
Method[] ms = c3.getDeclaredMethods();//得到该类自己声明的方法,无论访问权限
for (Method method : ms) {
//得到返回类型的类类型
Class returnType = method.getReturnType();
//得到返回类型的名称
String returnTypeName = returnType.getSimpleName();
System.out.print(returnTypeName + " " + method.getName() + "(");
//得到该方法参数列表的类型的类类型
Class[] paramTypes = method.getParameterTypes();
for (Class class1 : paramTypes) {
//得到该方法的参数列表的类型名称,参数名简称(不包含包名类名)
String paramTypeName = class1.getSimpleName();
System.out.print(paramTypeName);
}
System.out.println(")");
}
}
}


接下来的例子展示方法反射的基本操作

import java.lang.reflect.Method;

public class ReflectOfMethod {

public static void main(String[] args) {
//得到Methods类的类类型
//Class method = Methods.class;
Methods ms = new Methods();
Class method = ms.getClass();
//通过类类型得到方法对象
try {
/**
* 方法为无参数时,只写方法名或者写new Class[]{}
* Method m = method.getMethod("print");
* getMethod()方法可得到该类public的方法
* getDeclaredMethod()方法可得到该类自己声明的方法
*/
Method m1 = method.getMethod("print", new Class[]{});
/**
* 方法的反射操作
* 方法的反射操作invoke会抛出异常,如NoSuchMethodException
* 或者Object o = m.invoke(ms);
* 当方法无返回值时返回null,否则返回该方法的返回值
*/
Object o1 = m1.invoke(ms, new Class[]{});
//Method m = method.getMethod("print", int.class,int.class);
Method m2 = method.getMethod("print", new Class[]{int.class,int.class});
//与ms.print(10, 20)效果一样
Object o2 = m2.invoke(ms, 10, 20);
Method m3 = method.getMethod("print", new Class[]{String.class,String.class});
Object o3 = m3.invoke(ms, "HELLO", "world");
} catch (Exception e) {
e.printStackTrace();
}
}
}

class Methods {
public void print() {
System.out.println("Reflect of methods");

public void print(int a, int b) {
System.out.println(a + b);

public void print(String a, String b) {
System.out.println(a.toLowerCase() + "," + b.toUpperCase());

}


下面的例子展示动态加载类

当我们有一些功能类还没实现时,动态加载类可以帮助我们先把实现好的功能类加载,否则的话,程序无法通过编译,而且在升级版本时可以直接添加新类,不用重构代码

public class Office {
public static void main(String[] args) {
try {
//动态加载类,在运行时加载
Class c = Class.forName(args[0]);
//通过类类型创建该类对象
OfficeAble oa = (OfficeAble)c.newInstance();
oa.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}

接口

public interface OfficeAble {
public void start();
}

Word类

public class Word implements OfficeAble{
public void start() {
System.out.println("Word has started!");
};
}

Excel类

public class Excel implements OfficeAble{
public void start() {
System.out.println("Excel has started!");
};
}


感谢慕课网的学习视频和论坛一些牛人的经验总结!

0 0
原创粉丝点击