浅谈--Java反射

Java反射是什么?

Java反射是一种运行时能够动态获取类的信息并操作类的能力!(相当于上帝模式,巨屌)

Java反射的核心原理基于类加载机制类的元数据

类加载机制

Java类加载机制主要使用类加载器(ClassLoader)进行相应的类加载。ClassLoader主要使用loadClass()方法进行相应类的加载,遵循双亲委派原则。

如何避免类的重复加载呢?主要依靠的是synchronized和双亲委派机制

1、synchronized保障了类加载时的线程安全。

2、双亲委派机制通过划分加载区间,先委托父类进行加载,父类无法加载再自己加载,保障了类不会重复加载。

如下把loadClass()方法源代码给剖出来。

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        // 用synchronized保障线程安全
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    // 如下体现了双亲委派机制。
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

类的元数据

通过类加载器加载后就会生成一个Class对象。

Class对象存储类的字段、方法、构造器、父类、接口、注解等元数据。

Java反射的常见玩法

动态代理

原生JDK提供了基于Java反射的动态代理机制,使用Proxy来实现。

改变final修饰的常量值

public class ReflectionTest {
    // TODO 改变这个num值!
    private final int value;

    public ReflectionTest(int value){
        this.value = value;
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        ReflectionTest reflectionTest = new ReflectionTest(2);

        System.out.println("没改变前:"+reflectionTest.value);

        // 通过Class对象获取字段
        Field field = reflectionTest.getClass().getDeclaredField("value");

        field.setAccessible(true);

        field.setInt(reflectionTest,10);
        System.out.println("改变后:"+reflectionTest.value);
    }
}

输出:
没改变前:2
改变后:10
posted @ 2025-03-16 14:20  ayu0v0  阅读(15)  评论(0)    收藏  举报