Java反射

来源:互联网 发布:定额软件app 编辑:程序博客网 时间:2024/06/08 17:49

基本概念

在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。在Java中,反射允许在编译期间不知道接口的名称,字段、方法的情况下,在运行时检查类、接口、字段和方法。它还允许实例化新对象、修改成员变量和调用方法。

使用

要在Java中使用反射,就必须使用到Class类。在面向对象的世界里,万事万物皆对象。所以类也是对象,类是java.lang.Class的实例化对象。也就是在Java中任何一个类都是都是Class类的实例化对象。在进行反射操作前必须先取得该类的类类型(即该类对应的Class类的实例化对象),有三种方法可以完成此项操作:
假定需要进行反射操作的类如下:

class A{    private String name;    public int age;    public String getName(){        return this.name;    }    public A(){}    public A(String name, int age){        this.name = name;        this.age = age;    }    public void print(int a, int b){        System.out.println(a + b);    }    public void print(String a, String b){        System.out.println(a + b);    }}
  1. 通过任何一个类中都有隐含的静态成员变量class取得
Class c1 = A.class;
  1. 若已知某个类的实例化对象,通过getClass方法取得
A a = new A();Class c2 = a.getClass();
  1. 通过Class类提供的forName(包名.类名称)方法取得(此方法可用于类的动态加载,详情见后)
Class c3 = Class.forName("A");

注:Classc1c2c3

测试代码

package practicve.reflect;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{    private String name;    public String getName(){        return this.name;    }    public void print(int a, int b){        System.out.println(a + b);    }    public void print(String a, String b){        System.out.println(a + b);    }}public class Refelct {    public static void main(String [] args) throws ClassNotFoundException {        //  方式一:通过类中的隐含静态变量class获取A类的类类型(Class类对象)        Class c1 = A.class;        // 方式二:通过A的对象a调用getClass方法获取A的类类型(Class类对象)        A a = new A();        Class c2 = a.getClass();        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)        Class c3 = Class.forName("A");        // 一个类只可能是Class类的一个实例对象(c1、c2、c3相等)        System.out.println(c1 == c2 && c2 == c3);    }}

运行结果

这里写图片描述

获取Class的实例对象后,便可完成该类的反射操作。下面主要介绍三种反射操作:
1. 构造函数的反射操作
2. 成员变量的反射操作
3. 方法的反射操作

  1. 构造方法的反射操作
class A{    private String name;    public int age;    public String getName(){        return this.name;    }    public A(){}    public A(String name, int age){        this.name = name;        this.age = age;    }    public void print(int a, int b){        System.out.println(a + b);    }    public void print(String a, String b){        System.out.println(a + b);    }    public String toString(){        return "name:" + this.name + "  age:" + this.age;    }}public class Refelct {    public static void main(String [] args) throws Exception {        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)        Class c = Class.forName("practicve.reflect.A");        // 获取含参构造方法        Constructor cs = c.getConstructor(String.class, int.class);        // 调用构造方法实例化A类对象        Object obj = cs.newInstance("zhangsan", 20);    System.out.println(obj.toString());    }}

程序运行结果

这里写图片描述

  1. 成员变量的反射操作
package practicve.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{    private String name;    public int age;    public String getName(){        return this.name;    }    public A(){}    public A(String name, int age){        this.name = name;        this.age = age;    }    public void print(int a, int b){        System.out.println(a + b);    }    public void print(String a, String b){        System.out.println(a + b);    }    public String toString(){        return "name:" + this.name + "  age:" + this.age;    }}public class Refelct {    public static void main(String [] args) throws Exception {        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)        Class c = Class.forName("practicve.reflect.A");        // 获取A类中的成员变量        Field name = c.getDeclaredField("name");        Field age = c.getDeclaredField("age");        // 允许改变private变量        name.setAccessible(true);        A a = new A();        // 变量反射操作        name.set(a, "zhangsan");        age.set(a, 20);    System.out.println(a.toString());    }}

程序运行结果

这里写图片描述

  1. 方法的反射操作
package practicve.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * Created by lin_y on 2017/6/17. */class A{    private String name;    public int age;    public String getName(){        return this.name;    }    public A(){}    public A(String name, int age){        this.name = name;        this.age = age;    }    public void print(int a, int b){        System.out.println(a + b);    }    public void print(String a, String b){        System.out.println(a + b);    }    public String toString(){        return "name:" + this.name + "  age:" + this.age;    }}public class Refelct {    public static void main(String [] args) throws Exception {        // 方式三:使用Class类的静态方法forName获取A的类类型(Class类对象)        Class c = Class.forName("practicve.reflect.A");        // 获取A类中的方法       Method m1 = c.getDeclaredMethod("print", String.class, String.class);       Method m2 = c.getDeclaredMethod("print", int.class, int.class);       A a = new A();       // 方法的调用        m1.invoke(a, "12", "34");        m2.invoke(a, 12, 34);    }}

程序运行结果
这里写图片描述

注:

附:动态加载

基本概念:使用 new 创建对象是静态加载类,在编译时刻就需要加载所有的可能使用到的类。而动态加载类,是在运行时刻加载所需的类。

比如说,要写一个Office软件,里面包含多种功能,便可以使用动态加载类来实现线,具体实现见如下例子:

OfficeAble接口

package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public interface OfficeAble {    public void print();}

Office主类

package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Office {    public static void main(String [] args) throws Exception {        OfficeAble office = (OfficeAble) Class.forName(args[0]).newInstance();        office.print();    }}

Word功能

package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Word implements OfficeAble {    @Override    public void print() {        System.out.println("Word start ...");    }}

Excel功能

package practicve.reflect;/** * Created by lin_y on 2017/6/17. */public class Excel implements OfficeAble{    @Override    public void print() {        System.out.println("Excel start ...");    }}

程序运行时args[0]参数为practicve.reflect.Word,程序运行结果为:
这里写图片描述

注:1.使;2.使线

原创粉丝点击