zoukankan      html  css  js  c++  java
  • 反射

    本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解。

    下面开始正文。

    【案例1】通过一个对象获得完整的包名和类名

     1 package Reflect;
     2  
     3 /**
     4  * 通过一个对象获得完整的包名和类名
     5  * */
     6 class Demo{
     7     //other codes...
     8 }
     9  
    10 class hello{
    11     public static void main(String[] args) {
    12         Demo demo=new Demo();
    13         System.out.println(demo.getClass().getName());
    14     }
    15 }
    16 【运行结果】:Reflect.Demo

    添加一句:所有类的对象其实都是Class的实例。

    【案例2】实例化Class类对象

     1 package Reflect;
     2 class Demo{
     3     //other codes...
     4 }
     5  
     6 class hello{
     7     public static void main(String[] args) {
     8         Class<?> demo1=null;
     9         Class<?> demo2=null;
    10         Class<?> demo3=null;
    11         try{
    12             //一般尽量采用这种形式
    13             demo1=Class.forName("Reflect.Demo");
    14         }catch(Exception e){
    15             e.printStackTrace();
    16         }
    17         demo2=new Demo().getClass();
    18         demo3=Demo.class;
    19          
    20         System.out.println("类名称   "+demo1.getName());
    21         System.out.println("类名称   "+demo2.getName());
    22         System.out.println("类名称   "+demo3.getName());
    23          
    24     }
    25 }
    【运行结果】:
    
    类名称   Reflect.Demo
    
    类名称   Reflect.Demo
    
    类名称   Reflect.Demo

    【案例3】通过Class实例化其他类的对象

    通过无参构造实例化对象

     1 package Reflect;
     2  
     3 class Person{
     4      
     5     public String getName() {
     6         return name;
     7     }
     8     public void setName(String name) {
     9         this.name = name;
    10     }
    11     public int getAge() {
    12         return age;
    13     }
    14     public void setAge(int age) {
    15         this.age = age;
    16     }
    17     @Override
    18     public String toString(){
    19         return "["+this.name+"  "+this.age+"]";
    20     }
    21     private String name;
    22     private int age;
    23 }
    24  
    25 class hello{
    26     public static void main(String[] args) {
    27         Class<?> demo=null;
    28         try{
    29             demo=Class.forName("Reflect.Person");
    30         }catch (Exception e) {
    31             e.printStackTrace();
    32         }
    33         Person per=null;
    34         try {
    35             per=(Person)demo.newInstance();
    36         } catch (InstantiationException e) {
    37             // TODO Auto-generated catch block
    38             e.printStackTrace();
    39         } catch (IllegalAccessException e) {
    40             // TODO Auto-generated catch block
    41             e.printStackTrace();
    42         }
    43         per.setName("Rollen");
    44         per.setAge(20);
    45         System.out.println(per);
    46     }
    47 }
    48 【运行结果】:
    49 
    50 [Rollen  20]

     1 但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:
     2 
     3 比如我定义了一个构造函数:
     4 
     5 1
     6 2
     7 3
     8 4
     9 public Person(String name, int age) {
    10         this.age=age;
    11         this.name=name;
    12     }
    13 然后继续运行上面的程序,会出现:
    14 
    15 java.lang.InstantiationException: Reflect.Person
    16 
    17     at java.lang.Class.newInstance0(Class.java:340)
    18 
    19     at java.lang.Class.newInstance(Class.java:308)
    20 
    21     at Reflect.hello.main(hello.java:39)
    22 
    23 Exception in thread "main" java.lang.NullPointerException
    24 
    25     at Reflect.hello.main(hello.java:47)
    26 
    27 所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数

    类的生命周期

    在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开JVM。在程序执行中JVM通过装载,链接,初始化这3个步骤完成。

    类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。但是同一个类只会被类装载器装载以前

    链接就是把二进制数据组装为可以运行的状态。

     

    链接分为校验,准备,解析这3个阶段

    校验一般用来确认此二进制文件是否适合当前的JVM(版本),

    准备就是为静态成员分配内存空间,。并设置默认值

    解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)

    完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。

    当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

    将反射用于工厂模式

  • 相关阅读:
    23种设计模式(12):策略模式
    23种设计模式(11):责任链模式
    23种设计模式(10):命令模式
    23种设计模式(9):访问者模式
    23种设计模式(8):观察者模式
    23种设计模式(7):中介者模式
    23种设计模式(6):模版方法模式
    创建型模式总结
    23种设计模式(5):原型模式
    leetcode6
  • 原文地址:https://www.cnblogs.com/LJN520/p/5549907.html
Copyright © 2011-2022 走看看