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完成的。

相关推荐
Forward♞1 小时前
Qt——实现”Hello World“、认识对象树与Qt坐标系
开发语言·qt
草莓熊Lotso1 小时前
《吃透 C++ 类和对象(中):拷贝构造函数与赋值运算符重载深度解析》
开发语言·c++·经验分享·笔记·其他
楚Y6同学1 小时前
QT之键盘控制虚拟遥控系统开发总结
开发语言·c++·qt·串口通信
zyd09151 小时前
代码随想录Day50:图论(图论理论、深度搜索理论、所有可达路径、广度搜索理论)
java·数据结构·算法·leetcode·图论
都叫我大帅哥2 小时前
Flink Slot 终极指南:从入门到避坑,幽默解析分布式计算的“工位经济学
java·大数据·flink
小凡敲代码2 小时前
2025年最新Java后端场景面试题(大厂真题+解析)
java·程序员·java面试·java面试题·后端开发·java场景题·2025求职面试
一百天成为python专家2 小时前
OpenCV图像平滑处理方法详解
开发语言·人工智能·python·opencv·机器学习·支持向量机·计算机视觉
软测进阶2 小时前
【Python】Python 函数基本介绍(详细版)
开发语言·python
摇滚侠2 小时前
面试实战 问题三十二 Java中创建对象的几种方式
java·面试·职场和发展
BestAns2 小时前
Java中如何判断两个值是否相等?一篇文章讲透比较机制
java