对反射的理解和简单运用

在初步学习框架的时候,了解到反射技术被常用于框架的底层设计,对此技术比较感兴趣,故写下此文.

反射技术能够做什么?

通常,想要实例化一个对象,必须通过new关键词创建对象并且创建出的对象不能调用其私有属性和私有方法,尤其是当该类将自己的构造方法私有,那new关键字就无法创建该类对象了,但是我就是想拿到它的私有属性,用它的私有方法,还想实例化该类对象就算他的构造器私有了,咋办呢?反射就可以解决这个问题.

反射的原理理解

反射将一个类的划分颠覆了我对类的认识,也让我对JAVA的面向对象思想理解的更深了一些.

我们之前理解的类就是有三大部分组成:构造方法,成员方法和成员变量.而以此为模板就可以new出该类对象 如 Car car = new Car(); 这里的car就是Car这个类的一个实例化对象.

而反射先找到该类字节码对象,再将类划分为构造方法对象,成员方法对象,成员变量对象(可能还有其他)。在拿到该类的字节码文件之后,通过反射,你可以拿到任何一个你想要的对象,整个类就像摆在你餐桌上的一道菜,你可以对它为所欲为。

原理实现以及代码展示

package service;

import org.junit.Test;

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

public class Demo {

    //需求一:创建构造方法私有的Car对象
    @Test
    public void test01() throws Exception {
        /*如果我们想使用下面的Car类,通常思路是new对象*/
        //Car car = new Car("奔驰");  这里是无法直接new的

        //首先先解决实例化对象的问题
    /*
        三部曲:1、得到该类的字节码对象;2、通过字节码对象调用该类的成员对象;3、实现需求
     */
        //一、得到该类的字节码对象
        //方式1:类.class
        Class<Car> carClass01 = Car.class;
        //方式二: 对象.getClass()  这里仅写了私有的空参数构造,所以不能直接创建对象,不推荐,不做示范

        // 方式三(推荐): Class.forName(类的全路径)
        Class<?> carClass02 = Class.forName("service.Car");
        //二、通过字节码对象调用该类的成员对象

        Constructor<?> declaredConstructor = carClass02.getDeclaredConstructor();
        //非常关键的步骤,设置权限为Accessible,默认是false,
        //不修改的话会报java.lang.IllegalAccessException异常,无法使用私有成员
        declaredConstructor.setAccessible(true);
        Car car = (Car) declaredConstructor.newInstance();
        car.setCarName("奔驰");
        //打印仅是为确认创建了我们想要的对象
        System.out.println(car);
    }

    //需求二:调用Car的run方法(私有方法)
    //注意,因为调用的是私有方法,所以调用getDeclaredMethod()而不是getMethod(),后者只能调用非私有方法。
    @Test
    public void test02() throws Exception {
        Class<?> carClass02 = Class.forName("service.Car");
        Constructor<?> declaredConstructor = carClass02.getDeclaredConstructor();
        //非常关键的步骤,设置权限为Accessible,默认是false,
        //不修改的话会报java.lang.IllegalAccessException异常,无法使用私有成员
        declaredConstructor.setAccessible(true);
        Car car = (Car) declaredConstructor.newInstance();
        Method run = carClass02.getDeclaredMethod("run", String.class);
        run.setAccessible(true);
        run.invoke(car, "宾利");
    }

    //需求三:调用Car的私有属性
    @Test
    public void test03() throws Exception {
        Class<?> carClass02 = Class.forName("service.Car");
        Constructor<?> declaredConstructor = carClass02.getDeclaredConstructor();
        //非常关键的步骤,设置权限为Accessible,默认是false,
        //不修改的话会报java.lang.IllegalAccessException异常,无法使用私有成员
        declaredConstructor.setAccessible(true);
        Car car = (Car) declaredConstructor.newInstance();
        Field carName = carClass02.getDeclaredField("carName");
        carName.setAccessible(true);
        carName.set(car, "柯尼塞格");
        System.out.println(car);
    }

}

class Car {
    //将两个成员属性私有
    private String carName;
    private double price;

    //私有化有参构造,这个时候直接new对象已经不行了
    private Car() {

    }

    //一个私有方法
    private void run(String car) {
        System.out.println(car + "汽车行驶");
    }

    //setter 和 getter方法 和toString方法
    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "carName='" + carName + '\'' +
                ", price=" + price +
                '}';
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值