首页 > 编程语言 >JAVA反射

JAVA反射

时间:2024-07-25 15:53:59浏览次数:17  
标签:反射 JAVA String System Class 获取 class out

JAVA反射

一、什么是反射

反射就是把java类中的各种成分映射成一个个的Java对象
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

反射的本质是得到class对象后,反向获取对象的各种信息
当我们通过 new User()创建对象的时候,jvm会加载我们的user.class,jvm会到磁盘中找到user.class加载到jvm内存中,一个类只会产生一个class对象

类的加载过程

二、反射的应用

2.1 Class类

每个类在Java中都对应着一个Class对象,这个对象保存了该类的结构信息,如类名、字段、方法等。简言之,Class类是一个反射工具,能提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。

Class的一些常用方法

//获取成员变量
getFields()//获取所有公开(public)的成员变量,包括继承变量

getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量

getField(变量名)//获取指定公共属性的Field对象

 getDeclaredField(变量名)//获取指定包括私有,不包括继承的Field对象

//获取成员方法
getMethods()//获取所有可见的方法,包括继承的方法

getMethod(方法名,参数类型列表)//获取指定方法的Method对象
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)//获取指定包括私有,不包括继承的Method对象

//获取构造方法
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)//获取指定包括私有,不包括继承的Constructor对象
//其他方法
getInterfaces()//返回一个包含class对象的数组,存放该类或者接口实现的接口

newInstance()//使用无参构造创建一个类的实例

getName()//返回该类的完整名

User类

package com.ruoyi.system.domain;

public class User {

    private String name;

    public Integer id;

    protected String sex;

}

2.2 获取类的成员变量

package com.ruoyi.system.domain;

import java.lang.reflect.Field;

public class JavaReflect {

    public static void main(String[] args) throws NoSuchFieldException {

        Class<User> userClass = User.class;
        //获取所有公开的成员变量,包括继承变量
        Field userFields[] = userClass.getFields();
        System.out.println("通过getFields获取User所有公开的成员变量,包括继承变量");
        for(Field f: userFields){
            System.out.println("属性类型" + f.getType() + "属性名称:" +f.getName());
        }
        Field userDeclaredFields[] = userClass.getDeclaredFields();
        System.out.println("通过getDeclaredFields获取User获取本类定义的成员变量,包括私有,但不包括继承的变量");
        for(Field f: userDeclaredFields){
            System.out.println("属性类型" + f.getType() + "属性名称:" +f.getName());
        }
        Field userFieldsByName = userClass.getField("id");
        System.out.println("通过getField(变量名)获取User的指定公共属性的Field对象");
        System.out.println("属性类型" + userFieldsByName.getType() + "属性名称:" +userFieldsByName.getName());
    }
}

运行结果

通过getFields获取User所有公开的成员变量,包括继承变量
属性类型class java.lang.Integer属性名称:id
通过getDeclaredFields获取User获取本类定义的成员变量,包括私有,但不包括继承的变量
属性类型class java.lang.String属性名称:name
属性类型class java.lang.Integer属性名称:id
属性类型class java.lang.String属性名称:sex
通过getField(变量名)获取User的指定公共属性的Field对象
属性类型class java.lang.Integer属性名称:id

2.3 获取成员方法


    public static void main(String[] args) throws NoSuchMethodException {
        Class<User> userClass = User.class;
        System.out.println("通过getMethods()获取所有公开方法");
        Method[] methods = userClass.getMethods();
        for(Method m : methods){
            System.out.print("方法名称 :" + m.getName() +" ");
            Class[] plts = m.getParameterTypes();
            System.out.println("参数列表为");
            for(Class p : plts){
                System.out.print(p.getTypeName() + "  ");
            }
        }
        System.out.println();
        System.out.println("getDeclaredMethods()获取所有方法(包括私有,不包括继承)");
        Method[] methods2 = userClass.getDeclaredMethods();
        for(Method m : methods2){
            System.out.print("方法名称 :" + m.getName() +" ");
            Class[] plts = m.getParameterTypes();
            System.out.println("参数列表为");
            for(Class p : plts){
                System.out.print(p.getTypeName() + "  ");
            }
        }
        System.out.println();
        System.out.println("getMethod(\"getId\",Integer.class)获取setId");
        Method methods3 = userClass.getMethod("setId",Integer.class);
        System.out.print("方法名称 :" + methods3.getName());
        Class[] plts = methods3.getParameterTypes();
        System.out.print("参数列表为");
        for(Class p : plts){
            System.out.print(p.getTypeName() + "  ");
        }
        System.out.println();
        System.out.println("getDeclaredMethod(\"getId\",Integer.class)获取setName");
        Method methods4 = userClass.getDeclaredMethod("setName",String.class);
        System.out.print("方法名称 :" + methods4.getName());
        Class[] plts2 = methods4.getParameterTypes();
        System.out.print("参数列表为");
        for(Class p : plts2){
            System.out.print(p.getTypeName() + "  ");
        }


    }


通过getMethods()获取所有公开方法
方法名称 :getId 参数列表为
方法名称 :setId 参数列表为
java.lang.Integer 方法名称 :wait 参数列表为
方法名称 :wait 参数列表为
long int 方法名称 :wait 参数列表为
long 方法名称 :equals 参数列表为
java.lang.Object 方法名称 :toString 参数列表为
方法名称 :hashCode 参数列表为
方法名称 :getClass 参数列表为
方法名称 :notify 参数列表为
方法名称 :notifyAll 参数列表为
getDeclaredMethods()获取所有方法(包括私有,不包括继承)
方法名称 :getName 参数列表为
方法名称 :getId 参数列表为
方法名称 :setName 参数列表为
java.lang.String 方法名称 :setSex 参数列表为
java.lang.String 方法名称 :setId 参数列表为
java.lang.Integer 方法名称 :getSex 参数列表为
getMethod(“getId”,Integer.class)获取setId
方法名称 :setId参数列表为java.lang.Integer
getDeclaredMethod(“getId”,Integer.class)获取setName
方法名称 :setName参数列表为java.lang.String

2.4 获取构造函数

public static void main(String[] args) throws NoSuchMethodException {
        Class<User> userClass = User.class;
        System.out.println("getConstructor()获取所有公开构造方法");
        Constructor[] con1 = userClass.getConstructors();
        for(Constructor c : con1){
            System.out.print("构造方法名称 :" + c.getName() +" ");
            Class[] plts = c.getParameterTypes();
            System.out.print("参数列表为:");
            for(Class p : plts){
                System.out.print(p.getTypeName() + "  ");
            }
            System.out.println();
        }
        System.out.println("getDeclaredConstructors()获取所有构造方法");
        Constructor[] con2 = userClass.getDeclaredConstructors();
        for(Constructor c : con2){
            System.out.print("构造方法名称 :" + c.getName() +" ");
            Class[] plts = c.getParameterTypes();
            System.out.print("参数列表为:");
            for(Class p : plts){
                System.out.print(p.getTypeName() + "  ");
            }
            System.out.println();
        }
        System.out.println("getDeclaredConstructor()获取构造方法");
        //Constructor con3 = userClass.getConstructor(Integer.class,String.class,String.class);
        Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class,String.class);
        System.out.print("构造方法名称 :" + con3.getName() +" ");
        Class[] plts = con3.getParameterTypes();
        System.out.print("参数列表为:");
        for(Class p : plts){
            System.out.print(p.getTypeName() + "  ");
        }
        System.out.println();

    }

getConstructor()获取所有公开构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String
getDeclaredConstructors()获取所有构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String java.lang.String
getDeclaredConstructor()获取构造方法
构造方法名称 :com.ruoyi.system.domain.User 参数列表为:java.lang.Integer java.lang.String java.lang.String

2.5 通过反射创建对象

  public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
        Object obj = con3.newInstance(11,"测试");
        System.out.println(obj);
    }

User{, id='11’name=‘测试’, sex=‘null’}

2.6 通过反射修改属性(常用)

   public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<User> userClass = User.class;
        Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
        Object obj = con3.newInstance(11,"测试");
        //name是私有属性
        Field f = userClass.getDeclaredField("name");
        f.setAccessible(true);
        f.set(obj,"关羽");
        System.out.println(obj);
    }

User{, id='11’name=‘关羽’, sex=‘null’}

2.7 通过反射调用方法(常用)

  public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<User> userClass = User.class;
        Constructor con3 = userClass.getDeclaredConstructor(Integer.class,String.class);
        Object obj = con3.newInstance(11,"张飞");
        Method m1 = userClass.getDeclaredMethod("setName", String.class);
        m1.setAccessible(true);
        m1.invoke(obj,"刘备");
        System.out.println(obj);
    }

User{, id='11’name=‘刘备’, sex=‘null’}

三、常见面试题

3.1怎么给类中私有属性赋值

(1)属性对象.setAccessible(true);
在程序还没调用属性对象.setAccessible(false);之前,在同一程序内还可以调用私有属性,通过属性值.set(对象, 值)来给对象赋值(例如2.6)
(2)方法.setAccessible(true),使用m1.invoke(obj,属性名);(例如2.7)

标签:反射,JAVA,String,System,Class,获取,class,out
From: https://blog.csdn.net/qq_15740137/article/details/140684979

相关文章

  • java跨平台原理
    跨平台是指程序可以在多种平台(MicrosoftWindows、AppleMacintosh和Linux等)上运行,即编写一次,随处运行(WriteOnce,RunAnywhere)。Java语言通过为每个计算机系统提供一个叫做Java虚拟机的环境来实现跨平台。Java虚拟机是可运行Java字节码的虚拟计算机系统。可以将Java虚拟机看成......
  • JavaSE笔记
    目录一、JAVA基础编程二、第一阶段--JAVA基本语法2.1关键字与保留字2.2标识符2.3变量2.4运算符2.5从键盘获取输入Scanner类2.6流程控制结构2.7循环结构番外篇--软件开发流程番外篇--IDEA使用经验IDEA项目结构2.8一维数组数组的特点2.8.1声明与初始化2.8.1.1静态初始化2.......
  • JavaWeb第一天
    目录HTML+CSS+JS学习VUE框架学习Ajax--异步JavaScript和XMLVue项目结构MavenMaven坐标依赖管理传递依赖&排除依赖依赖范围生命周期Web入门springboot快速入门HTTP协议HTTP请求数据格式HTTP响应数据格式Tomcat请求响应1、请求请求参数设置2、响应3、案例4、分层解耦三层架构分层解......
  • JavaWeb第二天
    目录tlias案例实践登录校验1,Cookie技术——存储在客户端2,Session技术——存储在服务端3,令牌Token技术JWT(JSONWebToken)令牌4,过滤器Filter定义过滤器Filter拦截路径过滤器链5、拦截器interceptor6、全局异常处理器7、Spring事务管理事务进阶——事务属性AOP——面向切面编......
  • java处理超大文件面试题
    java海量大文件数据处理方式 1.给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?方案1:可以估计每个文件安的大小为50G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。s遍历文......
  • 基于JSP、java、Tomcat三者的项目实战--校园交易网(1)-项目搭建(前期准备工作)
    这是项目的初始页面接下来我先写下我的初始项目搭建技术支持:JAVA、JSP服务器:TOMCAT7.0.86编程软件:IntelliJIDEA2021.1.3x64首先我们打开页面,准备搭建项目的初始准备1.NewProject2.随后点击Next,勾选Createprojectfromtemplate,再点击Next3.给自己的项目命名......
  • 【YashanDB数据库】yasdb jdbc驱动集成druid连接池,业务(java)日志中有token IDENTIFIE
    问题现象客户的java日志中有如下异常信息:问题的风险及影响对正常的业务流程无影响,但是影响druid的mergesql功能(此功能会将sql语句中的字面量替换为绑定变量,然后将替换以后的sql视为同一个,然后用做执行性能统计)问题影响的版本与yashandb版本无关问题发生原因druid源码中在......
  • Java基础语法
    Java基础语法目录Java基础语法1.关键字和保留字关键字(Keywords)保留字(ReservedWords)2.标识符2.1.命名规则1.标识符的组成2.标识符的首字符3.标识符的命名限制4.命名风格5.其他建议6.示例2.2.驼峰命名法大驼峰命名法(UpperCamelCase)小驼峰命名法(lowerCamelCase)注意事项2.3.变......
  • Java8 函数式编程和Lambda
    lambda初识lambda表达式一个简单的方法,比较两个Integer:publicvoidTest1(){ Comparator<Integer>com=newComparator<Integer>(){ @Override publicintcompare(Integero1,Integero2){ returnInteger.compare(o1,o2); } }; TreeSet<Integer>......
  • JavaWeb Servlet
    Servlet入门Servlet是Java提供的一门动态web资源开发技术。简而言之,不同用户访问同样的资源会看到不一样的效果。Servlet是JavaEE规范之一,其实是一个接口。1快速入门1.1创建web项目,导入Servlet依赖坐标<dependency><groupId>javax.servlet</groupId>......