java反射

目录

Class类

获取Class实例

动态加载

Class的一些成员方法

1.反射实例

[2. 反射成员方法](#2. 反射成员方法)

[3. 反射成员变量](#3. 反射成员变量)

4.反射类结构

[动态代理(Dynamic Proxy)](#动态代理(Dynamic Proxy))


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

Class类

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

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

获取Class实例

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

java 复制代码
Class cls = String.class;
  1. 通过该实例变量提供的getClass()方法获取
java 复制代码
String s = "Hello";
Class cls = s.getClass();

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

java 复制代码
Class cls = Class.forName("java.lang.String");

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

动态加载

"一次编写,到处运行"

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

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

java 复制代码
// 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.反射实例

java 复制代码
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. 反射成员方法

java 复制代码
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. 反射成员变量

java 复制代码
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()

java 复制代码
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的实例

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

java 复制代码
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");

简单实现动态代理

java 复制代码
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);
}

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

java 复制代码
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完成的。

相关推荐
奔跑吧邓邓子2 分钟前
【Java实战㉞】从0到1:Spring Boot Web开发与接口设计实战
java·spring boot·实战·web开发·接口设计
专注API从业者11 分钟前
Python/Java 代码示例:手把手教程调用 1688 API 获取商品详情实时数据
java·linux·数据库·python
奔跑吧邓邓子32 分钟前
【Java实战㉝】Spring Boot实战:从入门到自动配置的进阶之路
java·spring boot·实战·自动配置
ONLYOFFICE33 分钟前
【技术教程】如何将ONLYOFFICE文档集成到使用Spring Boot框架编写的Java Web应用程序中
java·spring boot·编辑器
叫我阿柒啊41 分钟前
Java全栈开发工程师的实战面试经历:从基础到微服务
java·微服务·typescript·vue·springboot·前端开发·后端开发
耶啵奶膘1 小时前
uni-app头像叠加显示
开发语言·javascript·uni-app
看海天一色听风起雨落1 小时前
Python学习之装饰器
开发语言·python·学习
cyforkk1 小时前
Spring 异常处理器:从混乱到有序,优雅处理所有异常
java·后端·spring·mvc
Want5951 小时前
C/C++圣诞树①
c语言·开发语言·c++
生擒小朵拉1 小时前
STM32添加库函数
java·javascript·stm32