java反射

发布于:2025-07-16 ⋅ 阅读:(14) ⋅ 点赞:(0)

目录

Class类

获取Class实例

动态加载

Class的一些成员方法

1.反射实例

2. 反射成员方法

3. 反射成员变量

4.反射类结构

动态代理(Dynamic Proxy)


反射Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息,解决在运行期,对某个实例一无所知的情况下,如何调用其方法

Class类

只能由JVM创建的类,当JVM去加载某个class时,会new 一个Class实例 记录 该class的所有信息

我们可以通过这个Class实例获取到该实例对应的class的所有信息,即为 反射

获取Class实例

1.通过 某class 的静态变量 获取 Class实例

Class cls = String.class;

2. 通过该实例变量提供的getClass()方法获取

String s = "Hello";
Class cls = s.getClass();

3.完整类名,可通过静态方法Class.forName()获取

Class cls = Class.forName("java.lang.String");

Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例

动态加载

"一次编写,到处运行"

动态加载是指JVM在程序运行期间根据需要加载、链接和初始化类的机制,减少了程序的初始加载时间,只有真正使用到的类才会被加载

Commons Logging总是优先使用Log4j,只有当Log4j不存在时,才使用JDK的logging。利用JVM动态加载特性,大致的实现代码如下:

// Commons Logging优先使用Log4j:
LogFactory factory = null;
if (isClassPresent("org.apache.logging.log4j.Logger")) {
    factory = createLog4j();
} else {
    factory = createJdkLog();
}

boolean isClassPresent(String name) {
    try {
        Class.forName(name);
        return true;
    } catch (Exception e) {
        return false;
    }
}

Class的一些成员方法

1.反射实例

import java.lang.reflect.Constructor;

public class ReflectionNewInstance {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Class.forName("java.util.Date");
        
        // 方式1:调用无参构造(已过时)
        Object obj1 = cls.newInstance();
        System.out.println(obj1); // 当前日期

        // 方式2:通过Constructor对象(推荐)
        Constructor<?> constructor = cls.getConstructor();
        Object obj2 = constructor.newInstance();
        System.out.println(obj2); // 当前日期

        // 方式3:调用有参构造
        Constructor<?> strConstructor = String.class.getConstructor(String.class);
        String str = (String) strConstructor.newInstance("Hello");
        System.out.println(str); // Hello
    }
}

newInstance()已过时,推荐使用Constructor.newInstance() 

2. 反射成员方法

import java.lang.reflect.Method;

public class InvokeMethodExample {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Class.forName("java.lang.String");
        Object str = cls.getConstructor(String.class).newInstance("Hello");

        // 获取并调用方法
        Method method = cls.getMethod("toUpperCase");
        String result = (String) method.invoke(str);
        System.out.println(result); // HELLO

        // 调用私有方法(需设置accessible)
        Method privateMethod = cls.getDeclaredMethod("indexOf", String.class, int.class);
        privateMethod.setAccessible(true);
        int index = (int) privateMethod.invoke(str, "l", 0);
        System.out.println(index); // 2
    }
}

getMethod获取公共方法,getDeclaredMethod可获取私有方法(需setAccessible(true)

调用 静态方法,invoke方法传入的第一个参数永远为null

3. 反射成员变量

import java.lang.reflect.Field;

class Person {
    private String name = "Alice";
}

public class FieldExample {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Class.forName("Person");
        Object obj = cls.newInstance();

        // 获取并修改私有字段
        Field field = cls.getDeclaredField("name");
        field.setAccessible(true);
        System.out.println(field.get(obj)); // Alice
        field.set(obj, "Bob");
        System.out.println(field.get(obj)); // Bob
    }
}

4.反射类结构

getInterfaces()只返回当前类直接实现的接口类型

两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom()

class ClassStructure {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> cls = Class.forName("java.util.ArrayList");

        // 获取类名和修饰符
        System.out.println("Class: " + cls.getName());
        System.out.println("Modifiers: " + Modifier.toString(cls.getModifiers()));

        // 获取父类和接口
        System.out.println("Superclass: " + cls.getSuperclass().getName());
        for (Class<?> iface : cls.getInterfaces()) {
            System.out.println("Implements: " + iface.getName());
        }

        ArrayList arrayList = new ArrayList<>();
        System.out.println(arrayList instanceof List);
        System.out.println(arrayList.getClass().isAssignableFrom(List.class));
        System.out.println(List.class.isAssignableFrom(arrayList.getClass()));
    }
}

动态代理(Dynamic Proxy)

动态代理:绕过interface的实现类,可以在运行期动态创建某个interface的实例

静态代码 就是 编写接口的实现类,然后自动向上转型赋值

public interface Hello {
    void morning(String name);
}

public class HelloWorld implements Hello {
    public void morning(String name) {
        System.out.println("Good morning, " + name);
    }
}

Hello hello = new HelloWorld();
hello.morning("Bob");

简单实现动态代理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method);
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]);
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(), // 传入ClassLoader
            new Class[] { Hello.class }, // 传入要实现的接口
            handler); // 传入处理调用方法的InvocationHandler
        hello.morning("Bob");
    }
}

interface Hello {
    void morning(String name);
}

 上面的动态代理改写为静态实现类大概长这样:

public class HelloDynamicProxy implements Hello {
    InvocationHandler handler;
    public HelloDynamicProxy(InvocationHandler handler) {
        this.handler = handler;
    }
    public void morning(String name) {
        handler.invoke(
           this,
           Hello.class.getMethod("morning", String.class),
           new Object[] { name }
        );
    }
}

动态代理是通过Proxy创建代理对象,然后将接口方法“代理”给InvocationHandler完成的。


网站公告

今日签到

点亮在社区的每一天
去签到