zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
  • 相关阅读:
    WPA/WPA2无法暴力破解
    被书本知识所边缘化的软件工程师
    栈和队列
    Oracle update 之部分更新
    SAAS之初体验
    Entity Framework
    ResourceWriter和ResxResourceWriter的區別
    C#中將顏色轉換成網頁16進制顏色代碼
    Javascript功能代码收集(不断更新中...)
    .net1.1转换成更高版本的问题总结
  • 原文地址:https://www.cnblogs.com/sunada2005/p/10845223.html
Copyright © 2011-2022 走看看