关于反射:Java的精华反射机制

1.Java反射机制的概念

Java反射机制次要就是在程序运行的时候,动静的加载一些类和这些类的详细信息,而后操作这些类或对象的属性和办法。它的实质就是JVM通过类加载器失去一个class对象后,对其进行反编译,这样就能失去对象中的各种信息。

2.反射机制的优缺点

长处

  • 运行期类型的判断,动静加载类,进步代码灵便度。

毛病

  • 性能瓶颈:反射相当于一系列解释操作,告诉 JVM 要做的事件,性能比间接的 java 代码要慢很多。
  • 平安问题:让咱们能够动静操作扭转类的属性同时也减少了类的安全隐患。

3.Java反射机制的原理

下图就是类的失常加载过程,以及它们的反射原理和class对象:

4.反射具体应用

  • 创立Class类的实例有四种办法:

    //提供的简略的Person类
    public class Person{
    
      private String name;
      private int id;
      private static int UID;
      
       private String show(String nation){
          System.out.println("我的国籍是:" + nation);
          return nation;
      }
    
    } 
    
    
           //形式一:调用运行时类的属性:.class
          Class clazz1 = Person.class;
          
          //形式二:通过运行时类的对象,调用getClass()
          Person p1 = new Person();
          Class clazz2 = p1.getClass();//通过对象取得class
    
          //形式三:调用Class的静态方法:forName(String classPath)
          Class clazz3 = Class.forName("com.demo.java.Person");
          
          System.out.println(clazz1 == clazz2);//true
          System.out.println(clazz1 == clazz3);//true
    
          //形式四:应用类的加载器:ClassLoader  (理解)
          ClassLoader classLoader = ReflectionTest.class.getClassLoader();
          Class clazz4 = classLoader.loadClass("com.demo.java.Person");
  • 通过反射创立对应的运行时类的对象

    //个别应用newInstance()创立空参的
     Class c = Class.forName("com.demo.java.Person");
     Person p = (Person)c.newInstance();
    
    //调用指定参数构造的结构器,生成Constructor的实例
    Constructor con = clazz.getConstructor(String.class,Integer.class);
    //通过Constructor的实例创立对应类的对象,并初始化类属性
     Person p2 = (Person) con.newInstance("Peter",20);
  • 通过反射操作运行时类中的指定的属性

    Class clazz = Person.class;
    
          //创立运行时类的对象
          Person p = (Person) clazz.newInstance();
    
          //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
          Field name = clazz.getDeclaredField("name");
    
          //2.保障以后属性是可拜访的
          name.setAccessible(true);
          //3.获取、设置指定对象的此属性值
          name.set(p,"Tom");
    
          System.out.println(name.get(p));
          System.out.println("**************调用动态属性**************");
    
          Field uid = clazz.getDeclaredField("UID");
    
          uid.setAccessible(true);
    
          uid.set(null,1234);//动态属性赋值
          System.out.println(uid.get(p));
  • 通过反射操作运行时类中的指定的办法

    @Test
      public void testMethod() throws Exception {
    
          Class clazz = Person.class;
    
          //创立运行时类的对象
          Person p = (Person) clazz.newInstance();
    
          /*
          1.获取指定的某个办法
          getDeclaredMethod():参数1 :指明获取的办法的名称  参数2:指明获取的办法的形参列表
           */
          Method show = clazz.getDeclaredMethod("show", String.class);
          //2.保障以后办法是可拜访的
          show.setAccessible(true);
    
          /*
          3. 调用办法的invoke():参数1:办法的调用者  参数2:给办法形参赋值的实参
          invoke()的返回值即为对应类中调用的办法的返回值。
           */
          Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
          System.out.println(returnValue);
    
          System.out.println("*************如何调用静态方法*****************");
    
          // private static void showDesc()
    
          Method showDesc = clazz.getDeclaredMethod("showDesc");
          showDesc.setAccessible(true);
          //如果调用的运行时类中的办法没有返回值,则此invoke()返回null
    //        Object returnVal = showDesc.invoke(null);
          Object returnVal = showDesc.invoke(Person.class);
          System.out.println(returnVal);//null
    
      }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理