Java 基础之反射

反射快速入门

方向探知,在程序运行过程中动态的获取类的相关属性
这种动态获取类的内容以及动态调用对象的方法和获取属性的机制,就叫做JAVA 的反射机制

创建一个普通的类

public class Car {
    public String color="red";
    public Integer price=10000;
    public void run () {
        System.out.println("我是汽车 我会跑!");
    }
}

简单的应用

/**
 * 反射的基本应用
 */
public class TestDemo {

    public static void main(String[] args) throws Exception {
        // 通过普通的方式获取Car 对象
        Car car = new Car();
        System.out.println("通过普通的方式获取Car " + car);
        // 通过 反射的方式获取
        Class<?> name = Class.forName("pojo.Car");
        Object o = name.newInstance();
        System.out.println("通过 反射的方式获取" + o);
        // 通过反射获取属性和方法
        Field color = name.getField("color");
        System.out.println("color = " + color.get(o));
    }
}

反射机制的原理

反射机制允许程序在执行期借助与 Reflection Api 获取任何类的内部信息(比如成员变量,构造方法,成员方法等),并能操作对象的属性及方法,反射在设计模式和框架底层都会使用到。
加载完成类之后 在堆中就产生了一个Class 类型的对象(一个类只有一个Class 对象)这个对象包含了类的完整结构信息 通过这个对象得到累的结构 ,这个对象就像一面镜子 透过镜子看到类的结构 所以形象的称为:反射。
在这里插入图片描述

Java 反射机制可以完成:

1,在运行时判断任意一个对象所属的类
2,在运行时构造任意一个类的对象
3,在运行时构造任意一个类所具有的成员变量和方法
4,在运行时调用任意一个对象的成员变量和方法
5,生成动态代理

反射相关的主要类

1,java.lang.Class 代表一个类 Class 对象表示某个类加载后在堆中的对象
2,java.lang.reflect.Method 代表类的方法
3,java.lang.reflect.Field 代表类的成员变量
4,java.lang.reflect.Constructor 代表类的结构方法。

反射的优缺点

优点:可以动态的创建和使用对象(也是框架底层核心)使用灵活,没有反射机制 框架技术就失去底层支撑
缺点:使用反射基本是解释执行,对执行速度有影响

/**
 * 反射的基本应用
 */
public class TestDemo {

    public static void main(String[] args) throws Exception  {
        fun();
        fun1();
    }
    // 普通的方式获取
    public static void fun() {
        long start = System.currentTimeMillis();
        Car car = new Car();
        for (int i = 0; i < 10000; i++) {
           car.run();
        }
        long end = System.currentTimeMillis();
        System.out.println("普通的方式需要的时间" +(end-start) +"ms");
    }
    public static void fun1() throws Exception {
        long start = System.currentTimeMillis();
        Class<?> aClass = Class.forName("pojo.Car");
        Object instance = aClass.newInstance();
        Method method = aClass.getMethod("run");
        for (int i = 0; i < 10000; i++) {
            method.invoke(instance);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射的方式需要的时间" +(end-start) +"ms");



    }
}

结果
在这里插入图片描述

反射优化

由于有安全检查 所以反射的时候是比较慢 的 我们可以

    public static void fun2() throws Exception {
        long start = System.currentTimeMillis();
        Class<?> aClass = Class.forName("pojo.Car");
        Object instance = aClass.newInstance();
        Method method = aClass.getMethod("run");
        method.setAccessible(true);
        for (int i = 0; i < 10000; i++) {
            method.invoke(instance);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射优化的方式需要的时间" +(end-start) +"ms");
    }

结果
在这里插入图片描述

Class 类介绍

传统的方式去获取对象

在这里插入图片描述
我们可以打断点去测试我们的这个传统的方式是如何获取的对象的
在这里插入图片描述
在这里插入图片描述
newCar() 对象的时候会直接静茹 ClassLoader 的loadClass 方法中

反射的方式获取对象

在这里插入图片描述
进入的是Class 中 但是仍然调用的ClassLoader 类加载 的Class 对象
在这里插入图片描述
Class 类对象不是new 出来的 而是系统创建的,在某个类的Class 类对象,在内存中只有一份 因为类只加载一次

Class 类中的常用方法

public class Demo {
    public static void main(String[] args) throws Exception{
        // 获取Car 类对象
        Class<?> name = Class.forName("pojo.Car");
        // 输出cls
        System.out.println("name = " + name);
        // 获取到java.lang.Class
        System.out.println(name.getClass());
        // 获取到包名
        System.out.println(name.getPackage().getName());
        // 获取到全类名
        System.out.println(name.getName());
        // 通过类对象创建实例对象
        Object o = name.newInstance();
        System.out.println(o
        );
        // 通过反射获取属性
        Field color = name.getField("color");
        System.out.println(color.get(o));
        // 通过反射给属性设置值
        color.set(o,"fff");
        System.out.println(color.get(o));
        // 获取所有属性
        Field[] fields = name.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

    }
}

Class 类对象获取的方式

/**
*
* Class 获取的方式
*
* */
public class Demo1 {
    public static void main(String[] args) throws Exception {
        // Class.forName
        Class<?> name = Class.forName("pojo.Car");
        // 直接类名.class
        Class<Car> aClass = Car.class;
        // 通过new 的方式获取
        Class<? extends Car> aClass1 = new Car().getClass();
        // 通过类加载器的形式获取
        ClassLoader classLoader = Demo1.class.getClassLoader();
        Class<?> aClass2 = classLoader.loadClass("pojo.Car");
        // 基本数据类型Class 类 int long ...
        Class<Integer> aClass3 = int.class;
        // 包装类的class
        Class<Integer> aClass4 = Integer.TYPE;
        System.out.println("aClass3 = " + aClass3);
        System.out.println("aClass4 = " + aClass4);
    }



}

结果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

静态加载和动态加载

反射机制是Java 实现动态语言的关键 也就是通过反射实现类动态加载
1,静态加载 编译时加载相关的类 如果没有则保存 依赖性强
2,动态加载 运行时加载需要的类 如果 运行时不用该类 则不报错 降低了依赖性

类加载时机

1,当创建对象时(new)
2,当子类被加载时
3,调用类中的静态成员时
4,通过反射

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值