反射

144 阅读2分钟

Class类

-- 类是对象,类是java.lang.Class类的实例对象。

Foo foo1 = new Foo();

任何一个类都是Class的实例对象,这个实例对象有三种表示方式:

  1. 第一种表示方式,在知道类名时使用 Class c1 = Foo.class;

    • 实际在告诉我们任何一个类都有一个隐含的静态成员变量class
  2. 第二种表示方式,已知该类的对象通过getClass方法 Class c2 = foo1.getClass;

  3. 第三种表达方式,通过Class.forName方法,Class c3 = Class.forName("com.imooc.reflect.Foo"); com.imooc.reflect.Foo是类的全称。

注:

  • c1 == c2 == c3,因为一个类的类类型只有一个。并且需要获取类的信息(类成员变量/方法/构造方法/包名/注解等),必须先获取类的类类型(Class)。
  • 可以通过类的类类型创建该类的对象实例, 即通过c1 或 c2 或 c3 创建Foo的实例 Foo foo = (Foo)c1.newInstance();

-- 编译时刻加载类是静态加载类,运行时刻加载类是动态加载类。

new创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类,一个类或者一个方法不存在,整个程序就通过不了编译。解决该问题可以使用动态加载类。

//动态加载类,在运行时刻加载
Class c = Class.forName(args[0]);
//通过类类型,创建该类对象
OfficeAble oa = (officeAble)c.newInstance();   //officeAble为类的共同接口(统一标准,多态),里面有start方法
oa.start();  //运行时刻传入的哪个类,就调用哪个类的start()实现

-- 方法反射的操作

method.invoke(对象,参数列表)

  • 示例

要获取如下print(int, int)方法:

class A{
  public void print(int a,int b){
          System.out.println(a+b);
      }
}
  1. 要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
A a1 = new A();
Class c = a1.getClass();
  1. 获取方法名称(print)和参数列表(int,int)
    getMethod获取的是public的方法。getDelcaredMethod自己声明的方法。
Method m =  c.getMethod("print", new Class[]{int.class,int.class});

Method m = c.getMethod("print", int.class,int.class);
  1. a1.print(10, 20);方法的反射操作是用Method对象来进行方法调用,和a1.print调用的效果完全相同
Object o = m.invoke(a1,new Object[]{10,20});

  Object o = m.invoke(a1,10,20);
  • 方法如果没有返回值返回null,有返回值返回具体的返回值。

注:反射的操作(Class的操作,Method的操作等)都是绕过编译的。 java集合的泛型是为了防止输入类型错误,但只在编译阶段有效。

参考

反射——Java高级开发必须懂的