Java反射详解

1. 反射

  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制。
  • 成员变量:Field[] fields
  • 构造方法:Constructor[] cons
  • 成员方法:Method[] methods

2. 为什么用反射?

  • 1.可以在程序运行过程中操作这些对象。例如idea提示
  • 2.可以解耦,提高成宿可扩展性。

3. 获取class对象的方式

  • 1.Class.forName(“全类名”) 将字节码文件加载进内存获取。
    • 多用于配置文件,将类名定义在配置文件中,读取配置文件,加载类
  • 2.类.Class 通过类名的属性class获取类对象。
    • 多用于参数的传递
  • 3.对象.getClass:getClass()方法在Object类中定义。
    • 多用于对象获取字节码对象

4. 实现验证

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 反射
 * 反射:将类的各个组成部分封装为其他对象,这就是反射机制。
 * 成员变量:Field[] fields
 * 构造方法:Constructor[] cons
 * 成员方法:Method[] methods
 * <p>
 * 为什么用反射?
 * 1.可以在程序运行过程中操作这些对象。例如idea提示
 * 2.可以解耦,提高成宿可扩展性。
 * <p>
 * 获取class对象的方式
 * 1.Class.forName("全类名") 将字节码文件加载进内存获取。
 * * 多用于配置文件,将类名定义在配置文件中,读取配置文件,加载类
 * 2.类.Class 通过类名的属性class获取类对象。
 * * 多用于参数的传递
 * 3.对象.getClass:getClass()方法在Object类中定义。
 * * 多用于对象获取字节码对象
 *
 * @author zrj
 * @version V1.0
 * @since 2020/11/28
 **/
public class ReflexTest {

    /**
     * 获取类对象3中方式
     *
     * @throws ClassNotFoundException
     */
    @Test
    public void reflex() throws ClassNotFoundException {
        System.out.println( "------------获取类对象3中方式------------" );

        // 1.Class.forName("全类名") 将字节码文件加载进内存获取。
        Class<?> clazz = Class.forName( "com.zrj.junit.Person" );
        System.out.println( clazz );

        //2.类.Class 通过类名的属性class获取类对象。
        Class<Person> personClass = Person.class;
        System.out.println( personClass );

        // 3.对象.getClass:getClass()方法在Object类中定义。
        Person person = new Person();
        Class<? extends Person> aClass = person.getClass();
        System.out.println( aClass );

        /**
         * 结论:
         * 同一个字节码文件(.Class)在一次程序运行中,只会加载一次
         * 不论通过哪种方式获取。
         */
        System.out.println( clazz == personClass );
        System.out.println( clazz == aClass );
    }

    /**
     * 获取成员变量
     * 1.Field[] Class.getFields() 获取所以public修饰成员变量
     * 2.Field[] Class.getFields(String) 获取 指定的 public修饰成员变量
     * Field:获取成员变量无非就两个操作:
     * 设置值:set(Object obj,Object value)
     * 获取值:set(Object obj)
     */
    @Test
    public void reflexFieldTest() throws Exception {

        System.out.println( "------------获取成员变量------------" );

        // 获取Class对象
        Class<Person> personClass = Person.class;
        System.out.println( "获取类对象:" + personClass );

        Field[] fields = personClass.getFields();
        System.out.println( "获取public修饰成员变量:" + fields );
        Arrays.stream( fields ).forEach( System.out::println );

        System.out.println( "----------------------------------" );
        Field a = personClass.getField( "a" );
        System.out.println( "获取指定的 public修饰 成员变量" + a );

        // 获取成员变量a的值,默认null
        Person person = new Person();
        Object obj = a.get( person );
        System.out.println( "设置值前,获取a属性值:" + obj );
        // 设置a值,设置对象与获取对象必须是同一个对象,否则无法获取
        a.set( person, "张三" );
        System.out.println( "设置值后,获取a属性值:" + a.get( person ) );

        System.out.println( "----------------------------------" );
        Field[] declaredFields = personClass.getDeclaredFields();
        System.out.println( "获取所以成员变量不考虑修饰符:" + declaredFields );
        Arrays.stream( declaredFields ).forEach( System.out::println );

        // 不能直接访问私有变量 java.lang.IllegalAccessException
        Field ds = personClass.getDeclaredField( "d" );
        // 需要忽略访问权限修饰符的安全检查,暴力反射
        ds.setAccessible( true );
        Object obj2 = ds.get( person );
        System.out.println( "获取私有变量:" + obj2 );

    }

    /**
     * 获取构造方法
     * Constructor:创建对象
     */
    @Test
    public void reflexConstructorTest() throws Exception {
        System.out.println( "------------获取构造方法------------" );
        // 获取Class对象
        Class<Person> personClass = Person.class;
        System.out.println( "获取类对象:" + personClass );

        Constructor<Person> constructor = personClass.getConstructor( String.class, int.class, String.class, String.class, String.class, String.class );
        System.out.println( "获取构造方法:" + constructor );
        // 可以传无参构造
        Person person = constructor.newInstance( "张三", 18, "a", "b", "c", "d" );
        System.out.println( person );

        // 无惨构造对象
        Person person1 = personClass.newInstance();
        System.out.println( person1 );

        // 设置私有方法访问权限,同理属性,暴力反射
        constructor.setAccessible( true );

    }
    
    /**
     * 获取成员方法
     * Method:方法对象
     * 执行方法对象
     */
    @Test
    public void reflexMethodTest() throws Exception {
        System.out.println( "------------获取成员方法------------" );
        // 获取Class对象
        Class<Person> personClass = Person.class;
        System.out.println( "获取类对象:" + personClass );

        // 获取指定名称方法,无参方法
        Method eat = personClass.getMethod( "eat" );
        Person person = new Person();
        eat.invoke( person );

        // 获取指定名称方法,有参方法
        Method eat1 = personClass.getMethod( "eat", String.class );
        eat1.invoke( person, "rain" );

        /**
         * 获取所以public修饰方法
         * 所有类默认继承Object,所有getMethods会把Object的方法一起获取
         *
         */
        System.out.println( "----------------------------------------" );
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            // 暴力反射,获取私有成员方法
            method.setAccessible( true );
            System.out.println( "获取方法对象:" + method );
            String name = method.getName();
            System.out.println( "获取方法名称:" + name );
        }

        Field[] declaredFields = personClass.getDeclaredFields();

    }
    
    /**
     * 获取类名
     */
    @Test
    public void reflexClassNameTest() throws Exception {
        System.out.println( "------------获取类名------------" );
        // 获取Class对象
        Class<Person> personClass = Person.class;
        System.out.println( "获取类对象:" + personClass );

        String name = personClass.getName();
        System.out.println( "获取类名:" + name );
    }
    
}

import lombok.*;

/**
 * @author zrj
 * @version V1.0
 * @since 2020/11/29
 **/
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    private String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private String d;

    public void eat() {
        System.out.println( "eat方法执行了..." );
    }

    public void eat(String foot) {
        System.out.println( "eat方法执行了...foot:" + foot );
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值