谈谈对反射的理解

1. 定义

在程序运行过程中,可以获取某一个类的成员变量和方法或是构造新的对象,或是可以获取其父类信息,我们称之为反射。

2. jvm如何加载类

  • 将java文件编译为class文件
  • 根据路径查找到class文件,将class文件使用类加载器(其中用到了反射)加载到内存中
  • 验证class文件的准确性
  • 为静态变量分配内存空间
  • 将内存中的符号引用变为直接引用
  • 初始化静态变量和静态代码块

3. 反射的使用

3.1 获取class对象的3种方式

  • Class.forName
  • 类名.class
  • 对象.getClass()

注意:基础数据类型用包装类型.type

package com.liu.reflect;

public class People {
    public String sex;

    private String height;
}

package com.liu.reflect;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends People{
    String name;
    int age;
    
    private User(String password){
        this.password = password;
    }

    public static void main(String[] args) {
        try {
            //1.Class.forName
            Class<?> aClass1 = Class.forName("com.liu.reflect.User");
            //2.类名.class
            Class<User> aClass2 = User.class;
            //3.对象.getClass()
            User user = new User();
            Class<? extends User> aClass3 = user.getClass();

            System.out.println(aClass1);
            System.out.println(aClass2);
            System.out.println(aClass3);

            //基础数据类型用包装类型.type
            System.out.println(Integer.class);
            System.out.println(Integer.TYPE);


        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3.2 class对象常用方法

getFields()和getMethods()方法获得权限为public成员变量和成员方法时,还包括从父类继承得到的成员变量和成员方法;
getDeclaredFields()和getDeclaredMethods()方法只是获得在本类中定义的所有成员变量和成员方法。
getConstructors():返回当前类的所有public构造
getDeclaredConstructors():返回当前类的所有构造,包含私有

注意:没有任何修饰符时,默认为default修饰

            //反射获取类的属性
            System.out.println(Arrays.toString(aClass1.getFields()));
            System.out.println(Arrays.toString(aClass1.getDeclaredFields()));

            //反射获取类的方法
            System.out.println(Arrays.toString(aClass1.getMethods()));
            System.out.println(Arrays.toString(aClass1.getDeclaredMethods()));

            //反射获取构造
            //当前类的所有public构造
            System.out.println(Arrays.toString(aClass1.getConstructors()));
            //当前类的所有构造,包括私有的
            System.out.println(Arrays.toString(aClass1.getDeclaredConstructors()));

3.4 暴力破解private

核心都是获取到这个私有的变量或方法,为其添加setAccessible(true)

            //私有属性
            try {
                User user1 = new User("123");
                System.out.println("原密码:"+user1.getPassword());
                Field password1 = aClass1.getDeclaredField("password");
                password1.setAccessible(true);
                password1.set(user1,"222");
                System.out.println("新密码:"+user1.getPassword());

            } catch (Exception  e) {
                throw new RuntimeException(e);
            }
            //私有方法

            User user1 = new User();
            user1.setPassword("111");
            System.out.println(user1.password);

            Method getPasswordAndName = aClass1.getDeclaredMethod("getPasswordAndName",String.class);
            getPasswordAndName.setAccessible(true);
            getPasswordAndName.invoke(user1, "222");

            System.out.println(user1.password);

3.3 运行结果

class com.liu.reflect.User
class com.liu.reflect.User
class com.liu.reflect.User
class java.lang.Integer
int
[public java.lang.String com.liu.reflect.User.name, public int com.liu.reflect.User.age, public java.lang.String com.liu.reflect.People.sex]
[public java.lang.String com.liu.reflect.User.name, public int com.liu.reflect.User.age, private java.lang.String com.liu.reflect.User.password]
[public static void com.liu.reflect.User.main(java.lang.String[]), public boolean com.liu.reflect.User.equals(java.lang.Object), public java.lang.String com.liu.reflect.User.toString(), public int com.liu.reflect.User.hashCode(), public java.lang.String com.liu.reflect.User.getName(), public void com.liu.reflect.User.setName(java.lang.String), public java.lang.String com.liu.reflect.User.getPassword(), public int com.liu.reflect.User.getAge(), public void com.liu.reflect.User.setAge(int), public void com.liu.reflect.User.setPassword(java.lang.String), public java.lang.String com.liu.reflect.People.getHeight(), public java.lang.String com.liu.reflect.People.getSex(), public void com.liu.reflect.People.setSex(java.lang.String), public void com.liu.reflect.People.setHeight(java.lang.String), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
[public static void com.liu.reflect.User.main(java.lang.String[]), public boolean com.liu.reflect.User.equals(java.lang.Object), public java.lang.String com.liu.reflect.User.toString(), public int com.liu.reflect.User.hashCode(), public java.lang.String com.liu.reflect.User.getName(), public void com.liu.reflect.User.setName(java.lang.String), public java.lang.String com.liu.reflect.User.getPassword(), public int com.liu.reflect.User.getAge(), protected boolean com.liu.reflect.User.canEqual(java.lang.Object), public void com.liu.reflect.User.setAge(int), public void com.liu.reflect.User.setPassword(java.lang.String)]
[public com.liu.reflect.User(), public com.liu.reflect.User(java.lang.String,int,java.lang.String)]
[public com.liu.reflect.User(), public com.liu.reflect.User(java.lang.String,int,java.lang.String), private com.liu.reflect.User(java.lang.String)]
原密码:123
新密码:222
111
222

3.4 反射的应用

类加载器:使用反射获取要加载的类
springAOP:使用反射实现动态代理
spring框架:使用反射获取注解标识的方法或属性
数据库连接:使用反射获取驱动

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值