Java反射的使用

先创建一个实体类ReflectTest02

反射是在面试中经常被问到的一个知识点,经常被问到的比如:反射的基本概念,反射一些api,Java中哪些地方使用到了反射或者反射的应用场景等等。

 

我们在ReflectTest02中设置一些封装的属性、方法,以及一些公共的属性和方法,以便于我们待会测试。

package com.main.Package1;

public class ReflectTest02 {

    private int id ;
    private String name ;
    private int age ;

    public String addr;

    private ReflectTest02() {
    }

    public ReflectTest02(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    private void my(String name , String code){
        System.out.println("我是私有方法```" + name + " , 代号" + code);
    }

    @Override
    public String toString() {
        return "ReflectTest02{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

另写一个类测试反射。

package com.main;

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

/**
 * 反射demo
 *  1、反射机制的作用
 *     通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件)
 *     通过反射机制可以操作代码片段(.class文件)
 *  2、反射机制的相关类在哪个包下?
 *      java.lang.reflect.*
 *  3、反射机制相关的重要的类有哪些?
 *      java.lang.Class     代表整个字节码,代表一个类型,代表一个类
 *      java.lang.reflect.Method        代表字节码中的方法字节码,代表类中的方法
 *      java.lang.reflect.Constructor       代表字节码中的构造方法字节码,代表类中的构造方法
 *      java.lang.reflect.Field     代表字节码中的属性字节码,代表类中的成员变量(静态变量+实例变量)
 *
 */
public class ReflectionTest {

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

        // 4、获取Class的三种方式, 三种方式的返回值都是Class类型
        // 4.1 Class.forName("完整类名带包名")
        Class clazz = Class.forName("com.main.Package1.ReflectTest02");
        // 通过newInstance()这个方法调用无参构造方法,来完成对象的创建
        // 调用newInstance()这个方法调用的是无参构造,所以必须保证无参构造是存在的
        Object obj = clazz.newInstance();
        System.out.println(obj); // 结果:com.main.Package1.ReflectTest02@1b6d3586

        // 返回完整类名带包名
        String name = clazz.getName();
        System.out.println(name); // 结果:com.main.Package1.ReflectTest02

        // 返回类名
        String simpleName = clazz.getSimpleName();
        System.out.println(simpleName); // 结果:ReflectTest02

        // 返回类中public修饰的属性
        Field[] fields = clazz.getFields();
        for (Field f : fields) {
            System.out.println(f); // 结果:public java.lang.String com.main.Package1.ReflectTest02.addr
        }

        // 返回类中所有属性  包括私有
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println(f);
            //结果:
//            private int com.main.Package1.ReflectTest02.id
//            private java.lang.String com.main.Package1.ReflectTest02.name
//            private int com.main.Package1.ReflectTest02.age
//            public java.lang.String com.main.Package1.ReflectTest02.addr
        }

        // 根据属性名name获取指定的属性
        Field id = clazz.getDeclaredField("id");
        // 注意:set() 不能访问私有属性   需要打破封装才可以  setAccessible() 默认为false  修改为true即可
        id.setAccessible(true);
        // 给对象属性赋值
        id.set(obj , 1);
        System.out.println(id.get(obj)); // 结果:1
        System.out.println(id); // 结果:private int com.main.Package1.ReflectTest02.id

        // 返回类中的所有的实例方法
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
        }

        // 调用私有方法
        Method my = clazz.getDeclaredMethod("my" , String.class , String.class);
        // 需要注意的是 私有方法默认也是不支持直接访问的  在这里也需要打破封装
        my.setAccessible(true);
        // 使用 invoke() 方法执行
        Object resValue = my.invoke(obj, "周星驰", "007");

        // 通过反射调用构造方法实例化对象(含参数)
        Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class, int.class);
        constructor1.setAccessible(true);
        Object object1 = constructor1.newInstance(1, "周星驰", 18);
        System.out.println(object1);

        // 通过反射调用构造方法实例化对象(不含参数)
        Constructor constructor2 = clazz.getDeclaredConstructor();
        Object object2 = constructor2.newInstance();
        System.out.println(object2);

        System.out.println("----------------------------" + "获取一个类的父类以及实现的接口" + "----------------------------" );

        // 以String为例  我们获取它的父类 和 实现的结构
        // 第一步  获取String的class对象
        Class string = Class.forName("java.lang.String");
        // 获取String的父类  调用 getSuperClass()
        Class superclass = string.getSuperclass();
        System.out.println(superclass.getName());
        // 获取String类实现的所有接口
        Class[] interfaces = string.getInterfaces();
        for (Class i : interfaces) {
            System.out.println(i.getName());
        }


        // 4.2 对象.getClass()

        // 4.3 任何类型.class
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值