java的反射

1. 反射的应用场景

Java的反射机制在平时的业务开发过程中很少使用到,但是在一些基础框架的搭建上应用非常广泛。Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。java反射的运用场景此文章举例了反射的一个使用场景。《反射机制及其应用场景》此文章中举例说明了更复杂的反射使用场景。

2. 反射可提供的功能

Class类与java.lang.reflect类库一起对反射进行了支持,该类库包含Field、Method和Constructor类,这些类的对象由JVM在启动时创建,用以表示未知类里对应的成员。这样的话就可以使用Contructor创建新的对象,用get()和set()方法获取和修改类中与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getFields()、getMethods()和getConstructors()等许多便利的方法,以返回表示字段、方法、以及构造器对象的数组,这样,对象信息可以在运行时被完全确定下来,而在编译时不需要知道关于类的任何事情。

  反射机制并没有什么神奇之处,当通过反射与一个未知类型的对象打交道时,JVM只是简单地检查这个对象,看它属于哪个特定的类。因此,那个类的.class对于JVM来说必须是可获取的,要么在本地机器上,要么从网络获取。所以对于RTTI,即我们通常使用类的方式,和反射之间的真正区别只在于:

  • RTTI,编译器在编译时打开和检查.class文件
  • 反射,运行时打开和检查.class文件

3. 反射的缺点

  • 性能问题。使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
  • 使用反射会模糊程序内部逻辑。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。

4. 以下是反射使用方法的举例:

import java.util.ArrayList;

public class TestClass {
    public String testVar1;
    private ArrayList arr;

    public TestClass(String testVar1, ArrayList arr){
        this.testVar1 = testVar1;
        this.arr = arr;
    }

    public TestClass(){}

    public void test1(String var1, int var2){
        System.out.println("TestClass.test1(String, int) " + var1 + " " + var2);
    }

    public void test1(String var1){
        System.out.println("TestClass.test1(String)");
    }

    private void test2(String var1){
        System.out.println("TestClass.test2(String) ");
    }

    private void test2(){
        System.out.println("TestClass.test2()");
    }

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


public class Main {


    public static void main(String[] args){
        //得到反射类方法1
        TestClass tc = new TestClass();
        Class c = tc.getClass();

        //得到反射类方法2
        Class c1 = TestClass.class;

        try {
            //得到反射类方法3
            Class<?> clazz = Class.forName("xxx.xxx.xxx.TestClass");  //class的路径要写全
            //得到类名
            System.out.println("得到类名");
            System.out.println(clazz.getName());

            //得到构造器
            Constructor[] constructors = clazz.getConstructors();
            System.out.println("得到构造器名");
            for(Constructor con : constructors) System.out.println(con.getName());

            //得到成员方法
            Method[] methods = clazz.getDeclaredMethods();
            System.out.println("得到所有被声明成员方法");
            for(Method m : methods) System.out.println(m.getName());

            methods = clazz.getMethods();
            System.out.println("得到public的成员方法");
            for(Method m : methods) System.out.println(m.getName());

            Method method = clazz.getMethod("test1", String.class);
            System.out.println("得到特定的成员方法");
            System.out.println(method.getName());
            method = clazz.getDeclaredMethod("test2");
            System.out.println(method.getName());

            //得到public成员变量方法
            Field[] fields = clazz.getFields();
            System.out.println("得到public的成员变量");
            for(Field f : fields) System.out.println(f.getName());

            Field[] fields1 = clazz.getDeclaredFields();
            System.out.println("得到所有成员变量,包括私有成员变量");
            for(Field f : fields1) System.out.println(f.getName());

            System.out.println("使用反射方法获得类实例并访问域成员testVar1");
            Field field = clazz.getField("testVar1");
            Object object = clazz.getConstructor().newInstance();
            field.set(object, "haha");
            TestClass newTc = (TestClass)object;
            System.out.println(newTc.testVar1); //结果为haha

            System.out.println("使用反射方法获得类实例并调用成员方法test1(String, int)");
            object = clazz.getConstructor().newInstance();
            method = clazz.getDeclaredMethod("test1", String.class, int.class);
            Object invoke = method.invoke(object, "hehe", 1);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 

posted @ 2019-05-10 16:34  myLittleGarden  阅读(215)  评论(0编辑  收藏  举报