java学习之路——反射

什么是反射

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。反射也被称作框架设计的灵魂。
将类的各个组成部分封装为其他对象,这就是反射机制。

反射的功能

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
反射的好处就是:1.可以在运行过程中操作对象。2.可以解耦,提高程序的可扩展性。

解说一下

反射的概念太抽象,我刚开始接触的时候也是一脸懵逼,不知道到底是干什么的。在这里解说一下:

java代码在计算机中经历的三个阶段

源代码阶段

我们在写代码时,会先写好一个类,比如:
Person.java

public class Person {
    private String name; // 成员变量
    private int age;
    public String a;
    protected String b;
    String c; // 默认defult
    private  String d;
    public String getName() {  // 成员方法
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public Person() {}
    public Person(String name, int age) { // 构造函数
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
    public void eat() {
        System.out.println("eat...");
    }
}

以上就是我们平时写的一个代码。写完以后,我们可以通过java自带的编译器或者命令行“javac”来编译,在我们代码没有出现语法错误的情况下,会生成一个类文件“Person.class”存储在硬盘上。

Class对象阶段

类加载器(ClassLoader)将“Person.class”加载到内存里面。
在java中有Class类,就是用来描述所有字节码文件的一些共同的特征和行为。
——将成员变量封装为Field对象
——将构造方法封装为Constructor对象
——将成员方法封装为Method对象
在Class类中,用数组来描述所有的成员变量、构造方法、成员方法

运行阶段

创建对象

new Person

在这里插入图片描述

Class对象的功能

获取成员变量

Field[] getFields() 获取所有public 修饰的成员变量

import java.lang.reflect.Field;

public class ReflectDemo {
    public static void main(String[] args) {
        // 获取Person的Class对象
        Class personClass = Person.class;
        // 获取所有的成员变量
        Field[] fields = personClass.getFields(); // 获取所有public 修饰的成员变量
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-----------");
        Field a = personClass.getField("a");  // 获取指定名称的public修饰的成员变量,会有返回值
        Person p = new Person("Mike",18);
        Object value = a.get(p);
        System.out.println(value);
        a.set(p,"路人甲");
        System.out.println(p);
        System.out.println("==================");
        // 获取所有成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        // 获取单个成员变量
        Field d = personClass.getDeclaredField("d");
        // 忽略访问权限修饰符的安全检查
        d.setAccessible(true); // 暴力反射,无视修饰符,可以访问私有变量
        Object value2 = d.get(p);
        System.out.println(value2);
    }
}

在这里插入图片描述

Field成员变量

操作:
1.设置值
get(Object obj)
2.获取值
set(Object obj,String name)
3.忽略访问权限修饰符的安全检查
setAccessible(true); 暴力反射

获取构造方法

import java.lang.reflect.Constructor;

public class ReflectMethod {
    public static void main(String[] args) throws Exception {
        Class personClass = Person.class;
        // 语法:Constructor<T> getConstructor(类<?>……parameterTypes)
        Constructor constructor = personClass.getConstructor(String.class,int.class);
        System.out.println(constructor);
        // 创建对象
        Object person = constructor.newInstance("路人甲",18);
        System.out.println(person);
        System.out.println("-----------");
//        // 空参情况下
//        Constructor constructor1 = personClass.getConstructor();
//        System.out.println(constructor1);
//        Object person1 = constructor.newInstance();
//        System.out.println(person1);
//        // 暴力反射
//        constructor1.setAccessible(true);
//        // 使用空参数构造方法创建对象,操作可以简化成Class对象的newInstance方法
//        Object o = personClass.newInstance();
//        System.out.println(o);
        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class,int.class);
        System.out.println(declaredConstructor);
        Constructor[] c = personClass.getConstructors();
        for (Constructor cs : c ) {
            System.out.println(cs);
        }
    }
}

在这里插入图片描述

获取成员方法

import java.lang.reflect.Method;

public class ReflectMethods {
    public static void main(String[] args) throws Exception{
        Class personClass = Person.class;
        // 获取指定名称的方法
        // 若有参数,还需要加上参数
        Method eat_method = personClass.getMethod("eat"); // getMethod(name:"eat",String.class)
        Person p = new Person("张飞",18);
        // 执行方法
        eat_method.invoke(p);
        System.out.println("----------------");
        // 获取所有public修饰的方法 包含自定义方法和object本身自带的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            // 获取方法名
            String name = method.getName();
            System.out.println(name);
            // 支持暴力反射
        }
        // 获取类名
        String className = personClass.getName();
        System.out.println(className); // 获取全类名(包名。类名)
    }

在这里插入图片描述

获取Class对象的方式

1.Class.forName(“全类名”):将字节码文件加载进内存,返回class对象。用在第一阶段。
2.类名.class:通过类名的属性class获取。在第二阶段使用
3.对象.getClass:封装在object类中。适用于已经有对象的情况下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值