• 关于反射的一点理解


    最近在看《Spring 3.x企业应用开发实战》这本书,这本书上面写了对于反射的一些理解。虽然之前也看过很多次反射的内容,但是一直感觉自己对反射半懂不懂的。看了这本书上写的,有一种茅塞顿开的感觉,所以在这里记录一下。

    首先我们写一个Car类,它拥有两个构造函数、两个方法和三个属性。

     1 package com.baobaotao.reflect;
     2 
     3 /**
     4  * Created by Jean on 16/4/25.
     5  */
     6 public class Car {
     7     private String brand;
     8     private String color;
     9     private int maxSpeed;
    10 
    11     public Car(){}
    12 
    13     public Car(String brand, String color, int maxSpeed) {
    14         this.brand = brand;
    15         this.color = color;
    16         this.maxSpeed = maxSpeed;
    17     }
    18 
    19     public void introduce() {
    20         System.out.println("brand:" + brand + ";color:" + color
    21         + ";maxSpeed:" + maxSpeed);
    22     }
    23 
    24     public String getBrand() {
    25         return brand;
    26     }
    27 
    28     public void setBrand(String brand) {
    29         this.brand = brand;
    30     }
    31 
    32     public String getColor() {
    33         return color;
    34     }
    35 
    36     public void setColor(String color) {
    37         this.color = color;
    38     }
    39 
    40     public int getMaxSpeed() {
    41         return maxSpeed;
    42     }
    43 
    44     public void setMaxSpeed(int maxSpeed) {
    45         this.maxSpeed = maxSpeed;
    46     }
    47 }

    一般而言,我们创建Car的实例和调用方法的时候,是如下的过程:

    Car car = new Car();
    car.setBrand("红旗CA72",“黑色”,200);

    这就是我们传统的直接创造实例和调用方法的过程。

    直接创造实例的过程如下:

    1.Car car是声明一个引用变量,要求虚拟机分配空间给名字为car的引用变量,就像一个控制Car的遥控器。

    2.new Car()是要求Java虚拟机分配堆空间给新建立的Car对象

    3.中间的“=”号表示着将这个堆里的Car对象,交给引用类型car来控制。

    4.car.setBrand方法,表示通过引用对象car来Car对象来执行setBrand方法。

     

    接下来我们使用反射的方式来调用:

     1 package com.baobaotao.reflect;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.Method;
     5 
     6 /**
     7  * Created by Jean on 16/4/25.
     8  */
     9 public class ReflectTest {
    10     public static Car initByDefaultConst() throws Throwable {
    11         //通过类装载器获取Car类对象
    12         ClassLoader loader = Thread.currentThread().getContextClassLoader();
    13         Class clazz = loader.loadClass("com.baobaotao.reflect.Car");
    14         //获取类的默认构造器对象并通过它实例化Car
    15         Constructor cons = clazz.getDeclaredConstructor((Class[])null);
    16         Car car = (Car)cons.newInstance();
    17         //通过反射的方法设置属性
    18         Method setBrand = clazz.getMethod("setBrand", String.class);
    19         setBrand.invoke(car, "红旗CA72");
    20         Method setColor = clazz.getMethod("setColor", String.class);
    21         setColor.invoke(car, "黑色");
    22         Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
    23         setMaxSpeed.invoke(car, 200);
    24         return car;
    25     }
    26 
    27     public static void main(String[] args) throws Throwable {
    28         Car car = initByDefaultConst();
    29         car.introduce();
    30     }
    31 }

    运行以上程序,在控制台上将打印出以下信息:

    brand:红旗CA72;color:黑色;maxSpeed:200
     
    接下来具体说说反射的方法:
    Java的执行过程,我们简单理解为几步:
    1,Java文件由编译器编译成class文件;
    2,class文件由JVM
    装载(查找和导入Class文件)
    链接(执行校验、准备和解析步骤)
    和初始化(对类的静态变量、静态代码块执行初始化工作)
     
    传统的方法,用的是我们所谓的静态编译,指的是静态编译就是在编译的时候把你所有的内容都编译进class里去,然后最后一起执行。
    而反射,用的是动态的编译,在编译的时候不急着编译进去,等到了最后JVM装载的过程中,再通过一些对class的操作来执行一些操作。
     
    因为Class本身也是一个特殊的类,反射就是利用了这个特点,直接对class本身进行操作:
    1.首先通过ClassLoader获取Car对象的Class
    2.然后获取类的默认构造器对象并通过它实例化Car
    3.再通过反射来设置属性
     
     
     
     
  • 相关阅读:
    ThinkPHP实现定时任务
    VUE 父子组件之间通信传值 props和 $emit,事件触发传值ref,以及兄弟组件之间的通信传值 eventBus
    JS链接转换为二维码
    VUE 动态切换列表active样式
    微信内置浏览器video标签自动全屏的问题
    JS监听video视频播放时间
    JS数据统计表 highcharts.js的运用
    JS 自动返回每个月的天数
    JS 一键复制插件应用 和 原生实现
    JS enter键一键登录
  • 原文地址:https://www.cnblogs.com/jing-daye/p/5431668.html
Copyright © 2020-2023  润新知