前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Java-SE-第三十七章》之反射

《Java-SE-第三十七章》之反射

作者头像
用户10517932
发布2023-10-07 14:54:03
1410
发布2023-10-07 14:54:03
举报
文章被收录于专栏:929KC929KC

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢

反射

定义

Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然都可以拿到,我们就可以修改类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

基本使用

获取类

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的。因为对象都是通过类创建而来的,拿到了Class对象,并对其解析就可以获取类的成员属性,成员方法,构造器。Class对象存在的位置具体如下图。

在这里插入图片描述
在这里插入图片描述

获取类有三种方法

  1. 使用 Class.forName(“类的全路径名”); 静态方法。
  2. 使用类名.class
  3. 使用对象.getClass();

使用演示

首先创建一个User类,便于后期使用

代码语言:javascript
复制
@Data
@AllArgsConstructor
@NoArgsConstructor

public class User {
    private String username;
    private String password;
    public int age ;


    public  String pr(String username){
      return username;
    }
}

开始使用上述三种方法获取User的类对象

代码语言:javascript
复制
public class ClassDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> user = Class.forName("org.example.Functional.model.User");
        Class<User> userClass = User.class;
        User user2 = new User("user2", "11");
        Class<? extends User> aClass = user2.getClass();
        System.out.println(user);
        System.out.println(userClass);
        System.out.println(aClass);
    }
}
获取构造器

获取构造器的方法如下

方法

说明

Constructor<?>[] getConstructors()

返回所有构造器对象的数组(只能拿public的)

Constructor<?>[] getDeclaredConstructors()

返回所有构造器对象的数组,存在就能拿到

Constructor getConstructor(Class<?>… parameterTypes)

返回单个构造器对象(只能拿public的)

Constructor getDeclaredConstructor(Class<?>… parameterTypes)

返回单个构造器对象,存在就能拿到

使用演示

代码语言:javascript
复制
import java.lang.reflect.Constructor;

public class ConstructorsDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的无参构造
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        //设置禁止访问权限
        declaredConstructor.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor.getName()+"->"+declaredConstructor.getParameterCount());
        //获取有参构造
        Constructor<User> declaredConstructor1 = userClass.getConstructor(String.class, String.class);
        //设置禁止访问权限
        declaredConstructor1.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor1.getName()+"->"+declaredConstructor1.getParameterCount());

        Constructor<?>[] constructors = userClass.getConstructors();
        Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
        System.out.println(constructors[1]);
        System.out.println(constructors[0]);
        System.out.println(declaredConstructors[1]);
        System.out.println(declaredConstructors[0]);
    }
}

运行结果:

在这里插入图片描述
在这里插入图片描述

获取构造器的作用依旧是为了初始化对象返回

Constructor类中用于创建对象的方法

方法

说明

T newInstance(Object… initargs)

根据指定的构造器创建对象

public void setAccessible(boolean flag)

设置为true,表示取消访问检查,进行暴力反射

使用演示

将User的有参构造设置为私有,并且不设置访问检查

代码语言:javascript
复制
public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

在这里插入图片描述
在这里插入图片描述

取消访问检查后

代码语言:javascript
复制
public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        //设置禁止访问权限
         declaredConstructor1.setAccessible(true);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

在这里插入图片描述
在这里插入图片描述

如果是非public的构造器,需要打开权限,然后才能创建对象。反射是Java的后门破坏的封装性,私有的也可以构造方法也可以执行了。

获取成员变量

Class类中用于获取成员变量的方法

方法

说明

Field[] getFields()

返回所有成员变量对象的数组(只能拿public的)

Field[] getDeclaredFields()

返回所有成员变量对象的数组,存在就能拿到

Field getField(String name)

返回单个成员变量对象(只能拿public的)

Field getDeclaredField(String name)

返回单个成员变量对象,存在就能拿到

使用演示

代码语言:javascript
复制
public class AttributeDemo {
    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Field[] fields = userClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName()+"-->"+field.getType());
        }
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName()+"-->"+declaredField.getType());
        }
        //定位某个变量
        Field age = userClass.getField("age");
        Field username = userClass.getDeclaredField("username");
        Field password = userClass.getDeclaredField("password");
        User user = new User();
        //设置私有变量的访问
        username.setAccessible(true);
        password.setAccessible(true);
        //赋值
        username.set(user,"sdf");
        password.set(user,"ss12");
        age.set(user,90);
        System.out.println(user);
        //取值
        String o = (String)username.get(user);
        System.out.println(o);
    }
}

运行结果:

在这里插入图片描述
在这里插入图片描述

私有的成员变量依旧需要开启访问权限

获取成员方法

Class类中用于获取成员变量的方法、

方法

说明

Method[] getMethods()

返回所有成员方法对象的数组(只能拿public的

Method[] getDeclaredMethods()

返回所有成员方法对象的数组,存在就能拿到

Method getMethod(String name, Class<?>… parameterTypes)

返回单个成员方法对象(只能拿public的)

Method getDeclaredMethod(String name, Class<?>… parameterTypes)

返回单个成员方法对象,存在就能拿到

使用演示

代码语言:javascript
复制
public class MethodDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的成员方法
        Method[] methods = userClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + " "+method.getParameterCount()
            +method.getReturnType());
        }
        //获取某个对象方法
        Method pr = userClass.getDeclaredMethod("pr",String.class);
        System.out.println(pr.getName() + " "+pr.getParameterCount()+" "
                +pr.getReturnType());
        User user = new User();
        pr.setAccessible(true);
        //调用方法,用user对象
        Object invoke = pr.invoke(user,"java");
        System.out.println(invoke);
    }
}
使用场景
  1. 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统****应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。
  2. 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 反射
    • 定义
      • 基本使用
        • 获取类
        • 获取构造器
        • 获取成员变量
        • 获取成员方法
        • 使用场景
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档