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)

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值