【Java基础】JavaCore核心-反射技术

简介: 【Java基础】JavaCore核心-反射技术

18d5f54c4c0c4b94ba5fc11cd11a3108.jpg

1.什么是反射技术

  • Java的反射(reflection)机制是指在程序的运行状态中
  • 可以构造任意一个类的对象
  • 可以了解任意一个对象所属的类
  • 可以了解任意一个类的成员变量和方法
  • 可以调用任意一个对象的属性和方法。
  • 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制
  • 核心:得到编译以后得class文件对象,提供了一个Class类型,就是编译后的class类对象
HelloWorld.java -> javac -> HelloWorld.class
Class clz = HelloWorld.class
  • 分类
  • 类字节码 Class (本身也是一个类,是Java反射的源头)
  • 构造器 Constructor
  • 成员变量 Field
  • 方法 Method

2.反射-获取类对象方式

public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.类名.class 获取
        Class<User> userClass1 = User.class;
        System.out.println(userClass1);
        //2.对象获取
        User user = new User();
        Class<? extends User> userClass2 = user.getClass();
        System.out.println(userClass2);
        //3.全限定名称获取,Class.forName
        Class<?> userClass3 = Class.forName("com.lixiang.reflex.User");
        System.out.println(userClass3);
        //4.通过classLoader类加载器
        ClassLoader classLoader = ReflexTest.class.getClassLoader();
        Class<?> userClass4 = classLoader.loadClass("com.lixiang.reflex.User");
        System.out.println(userClass4);
    }
}
public class User {
    private String name;
    private int age;
}


306e09a2c487490d9f6efafa3aa9f307.jpg

反射API比较多,宏观分类

  • get+要获取的东西,例如:获取属性为getField()、获取方法为getMethod()
  • 只能获取公有的东西
  • 注意:getMethod可以获取到本类及其父类的方法
  • get+Declared+要获取的东西,例如:获取属性为getDeclaredField()、获取方法为geDeclaredtMethod()
  • 可以获取全部的东西
  • 注意:getDeclaredMethod只能获取到本类的方法

3.反射-获取声明构造器

public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //1.类名.class 获取
        Class<User> userClass = User.class;
        Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
        //获取本类的全部构造方法
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName() + " "+ declaredConstructor.getParameterCount());
        }
        System.out.println("--------------------");
        //获取String类型的高燥方法
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor.getName() + " "+ declaredConstructor.getParameterCount());
    }
}

3a01968583e6479a961d81b4a589541e.jpg

4.反射-对象创建实战

  • JDK9后用构造器创建对象,class.getDeclaredConstructor( ).newInstance( )
  • 日常开发定义的POJO类里面,开发规范都推荐显示的写出空构造函数
  • 一是方便通过反射创建对象 ,二是子类继承父类时,默认调用super( ) 保证父类有空构造函数
方法名 说明
T newInstance( ) 根据类的空参的构造器创建对象,类必须提供空参的构造器和public权限
newInstance(Object...initargs) 根据指定的构造方法创建对象
  • 反射创建对象有多种方式,常用步骤如下
  • 根据全类名获取对应的Class对象
  • 调用指定参数结构的构造器,生成Constructor的实例
  • 通过Constructor的实例创建对应类的对象,并初始化类属性
public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.类名.class 获取
        Class<User> userClass = User.class;
        //创建无参User对象
        Constructor<User> userConstructor1 = userClass.getDeclaredConstructor();
        User user = userConstructor1.newInstance();
        System.out.println(user);
        System.out.println("-----------------------");
        //创建一个参数的对象
        Constructor<User> userConstructor2 = userClass.getDeclaredConstructor(String.class);
        User user1 = userConstructor2.newInstance("李祥");
        System.out.println(user1);
    }
}

14853c0b328a40fba16134832f5c2770.jpg

5.反射-方法和属性实战

  • 通过class获取方法
方法 说明
getMethods() 获取当前运行类和 父类中声明的方法,需要是public访问权限的方法
getDeclaredMethods() 获取当前运行时类中声明的全部方法,不包含父类中声明的方法
  • 方法method的方法
方法 说明
getReturnType() 获取全部的返回值
getParameterTypes() 获取全部的参数
getModifiers() 获取修饰符
getExceptionTypes() 获取异常信息
public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取类对象
        Class<User> clazz = User.class;
        //获取当前运行类和 父类中声明的方法,需要是public访问权限的方法
        Method[] methods = clazz.getMethods();
        for(Method method:methods){
            System.out.println("修饰符="+method.getModifiers()+",返回值="+method.getReturnType().getName()+",整体="+method);
        }
        System.out.println("——————————————————");
        //返回当前类中所有的方法,无视修饰符
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method method:declaredMethods){
            System.out.println("修饰符="+method.getModifiers()+",返回值="+method.getReturnType().getName()+",整体="+method);
        }
    }
}

14e36d52c08944aea2c983c390a4aa4c.jpg

  • 通过class对象获取属性
方法名 说明
getFields( ) 获取当前运行类和 父类中声明的属性,需要是public访问权限的属性
getDeclaredFields( ) 获取当前运行时类中声明的全部属性,不包含父类中声明的属性
  • 属性Field的方法
方法 说明
getModifiers() 整数形式返回此Field的修饰符,整数对应在 java.lang.reflect.Modifier里面
getType() 返回 Field的属性类型
getName() 返回 Field的名称
public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取类对象
        Class<User> clazz = User.class;
        //都是private,则获取不了; 属性改为public才行
        Field[] fields = clazz.getFields();
        for(Field field:fields){
            System.out.println("属性名="+field.getName()+",属性类型="+field.getType().getName()+",属性修饰符="+field.getModifiers());
        }
        System.out.println("——————————————————");
        // 获取当前运行时类中声明的全部属性,不包含父类中声明的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field field:declaredFields){
            System.out.println("属性名="+field.getName()+",属性类型="+field.getType().getName()+",属性修饰符="+field.getModifiers());
        }
    }
}

5e25e7522b03408d91377cfbb1d4aed0.jpg

6.反射-属性值操作实战

  • 对反射进行相关操作,但如果构造器、方法、属性 没权限怎么操作?
  • 可以通过 setAccessible(true) ,修改访问权限,Method和Field、Constructor对象都有setAccessible()方法
  • ff0535191c8d49c8ada6c42587874d0d.jpg
public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取类对象
        Class<User> clazz = User.class;
        //获取public空构造函数,并创建对象(把构造函数private私有化)
        Constructor<User> declaredConstructor = clazz.getDeclaredConstructor();
        //修改访问权限,true表示暴力反射,攻破权限
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance();
        user.setAge(11);
        user.setName("李祥");
        System.out.println(user);
    }
}

37437d2f68134200b350c4f34bf2ac45.jpg

  • Field相关方法
方法 说明
get(Object obj) 获取取指定对象obj上此Field的属性内容
set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

4f9a293a13c247d991aa97e5890d4b7e.jpg

public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class clazz = User.class;
        //创建运行时类的对象
        //获取类对象
        //获取public空构造函数,并创建对象
        Constructor<User> declaredConstructor = clazz.getDeclaredConstructor();
        //修改访问权限,true表示保留反射
        declaredConstructor.setAccessible(true);
        //创建对象
        User user = declaredConstructor.newInstance();
        System.out.println(user.toString());
        //获取运行时类中指定变量名的属性
        Field name = clazz.getDeclaredField("name");
        //保证当前属性是可访问的
        name.setAccessible(true);
        //设置指定对象的的属性值
        name.set(user,"李祥");
        //打印对象的name属性值
        System.out.println(name.get(user));
        System.out.println(user.toString());
    }
}

8a27132e39704919bf64d3d52d57b57a.jpg

7.反射-invoke运行类方法

  • 运行类的指定方法步骤
  • 获取class对象,创建对象
  • 获取方法,invoke调用

什么是invoke调用 Object invoke(Object obj, Object … args)

  • invoke的中文意思是【调用、召唤】
  • 用来调用某个类中的方法的,但是它不是通过当前类直接去调用而是通过反射的机制去调用
  • 参数说明:obj是调用类的实例对象, args:调用方的方法参数,是可变长度的
  • Object 对应原方法的返回值,若原方法无返回值,此时返回null
  • 如果原方法为静态方法,此时形参 obj可为null
  • 如果原方法形参列表为空,则args为null
  • 如果原方法声明为private,则需要在调用此invoke()方法前,调用对象的
  • setAccessible(true)方法
  • 编码实战
  • User类中加入这三个方法

188d947d7ba2482c9dbc036b610df161.jpg

public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //获取类对象
        Class<User> clazz = User.class;
        //获取public空构造函数,并创建对象
        Constructor<User> declaredConstructor = clazz.getDeclaredConstructor();
        //确保有访问权限,true表示暴力反射
        declaredConstructor.setAccessible(true);
        User user = declaredConstructor.newInstance();
        user.setName("李祥");
        System.out.println("—————————调用普通方法———————————");
        //获取指定的某个方法, 参数1,指明获取的方法的名称  参数2,指明获取的方法的形参列表
        Method say = clazz.getDeclaredMethod("say", String.class);
        //保证当前方法是可访问的
        say.setAccessible(true);
        //invoke调用,参数1 方法的调用者  参数2 给方法形参赋值的实参,
        // 返回值 是 对应类中调用的方法的返回值。
        Object returnValue = say.invoke(user, "李祥");
        System.out.println(returnValue);
        System.out.println("—————————调用静态方法———————————");
        //获取指定的某个方法, 参数1,指明获取的方法的名称  参数2,指明获取的方法的形参列表
        Method sleepMethod = clazz.getDeclaredMethod("sleep",String.class);
        //保证可以访问
        sleepMethod.setAccessible(true);
        //调用静态方法,不需要获取类对象。
        Object returnValue2 = sleepMethod.invoke(null,"李祥");
        //如果调用的运行时类中的方法没有返回值,则此invoke()返回null
        System.out.println(returnValue2);
    }
}

181fe3ad8ac44973994ddc411c2d8351.jpg


相关文章
|
20天前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
46 11
|
29天前
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
63 7
|
11天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
10天前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
30天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
2月前
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
|
2月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
2月前
|
JSON 前端开发 JavaScript
java-ajax技术详解!!!
本文介绍了Ajax技术及其工作原理,包括其核心XMLHttpRequest对象的属性和方法。Ajax通过异步通信技术,实现在不重新加载整个页面的情况下更新部分网页内容。文章还详细描述了使用原生JavaScript实现Ajax的基本步骤,以及利用jQuery简化Ajax操作的方法。最后,介绍了JSON作为轻量级数据交换格式在Ajax应用中的使用,包括Java中JSON与对象的相互转换。
59 1
|
2月前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
40 7
|
2月前
|
Java
Java的反射
Java的反射。
39 2