Java反射机制

Java反射机制出现的原因:

  情景1:有些时候,我们不会立即得到我们所需要的类,这个类可能在我们编写完代码之后才会出现,但是我们又知道关于这些类的方法等信息。

  情景2:有些时候,我们拥有多个类,这些类都有相同的方法,当我们想去调试这些类的方法的时候,需要重复写多个代码。

    比如我们有Person、Dog、Cat类,这些类都有eat方法,我们需要调用Person.eat()、Dog.eat()、Cat.eat()去测试。

当我们知道了反射以后我们就能在一定程度上解决这些问题。

 

通过反射,我们能够用class文件对象去调用其成员变量,成员方法,构造方法。

首先我们怎么得到class文件对象呢?

  1.调用对象的getClass()方法

  2.数据类型的静态属性class(.class方法)

  3.Class类中的静态方法   

   public static Class forName(String className)

    // 方式1
    Person p = new Person();
    Class c = p.getClass();

    // 方式2
    Class c3 = Person.class;// 方式3
    Class c4 = Class.forName("ForName");

“ForName”中的字符串是你想调用的类的完整路径名。如:java.lang.Thread。

 

得到了class对象之后,我们又怎么调用其成员变量,成员方法,构造方法呢?

  下面的调用都使用该Person类:

public class Person {
    private String name;
    int age;
    public String address;

    public Person() {
    }

    private Person(String name) {
        this.name = name;
    }

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(String name, int age, String address) {
        System.out.println(name + "--" + age + "--" + address);

    }
}

  1. 调用无参的构造方法(Class.forName实现,构造方法用Constructor接收,用getConstructor()方法获取,用newInstance()创建实例):

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
     //得到class对象  
        Class c = Class.forName("a.b.Person");
        //通过class对象过去构造方法对象(con)
        Constructor con = c.getConstructor();
        //创建一个构造方法实例
        Object obj = con.newInstance();
        //显示
        System.out.println(obj);
    }
}

    调用带参的构造方法(Class.forName实现,构造方法用Constructor接收getConstructor()方法获取newInstance()创建实例):

public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("a.b.Person");

        // 获取带参构造方法对象
        // public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor con = c.getConstructor(String.class, int.class,
                String.class);

        // 通过带参构造方法对象创建对象
        // public T newInstance(Object... initargs)
        Object obj = con.newInstance("name", 0, "address");
        
        System.out.println(obj);
    }
}

  2.获取成员变量(成员变量用Field接收, 用getField()获取,set方法赋值)

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获得class文件对象
        Class c = Class.forName("a.b.Person");
        // 得到对象的构造方法
        Constructor con = c.getConstructor();
        // 将构造方法实例化,相当于实例化一个Person类,即此时的obj是一个Person类。
        Object obj = con.newInstance();
        // 获取类中的name成员变量
        Field addressField = c.getField("name");
        // 将obj的name成员变量赋值为Jack
        addressField.set(obj, "Jack"); 
        // 显示
        System.out.println(obj);
    }
}

  3.获取成员方法(成员方法用Method接收, 用getMethod()方法获取,用invoke方法赋值):

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取class文件对象
        Class c = Class.forName("a.b.Person");
        // 获取构造方法并实例化
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        // 得到成员方法
        Method m1 = c.getMethod("eat");
        // 调用obj的ShowPerson方法
        m1.invoke(obj); 
    }
}

  通过上面的例子,我们知道了一种可以不用先创建一个类就可以直接调用其成员变量,成员方法,构造方法的方式(用Class文件对象去调用其成员变量,成员方法,构造方法)。这样我们就可以解决开始时说的情景1的问题。而且我们只需要修改Class.forNAme方法中的字符串,就可以调用不同类的相同方法了,解决了情景2的问题(比如把调用Person的eat方法改为Dog的eat方法,只需将a.b.Person改为a.b.Dog即可)。

   
  
   

posted @ 2015-10-15 16:30  世界打弹珠锦标赛冠军  阅读(128)  评论(0)    收藏  举报