Java反射(个人学习笔记)

Java反射

反射的定义:

Java反射是指在运行时动态地获取类的信息,并可以通过该信息来操作类或对象。通过反射,我们可以在运行时获取类的字段、方法、构造函数等信息,并能够动态地创建对象、调用方法、访问和修改字段的值。

反射相关的类:

Class类

代表类的实体,在运行的Java应用程序中表示类和接口

Field类

代表类的成员变量/字段

Method类

代表类的方法

Constructor类

代表类的构造方法

获得反射的三种方式:

一、Class.forName("全类名") 【最常用】

//1、Class.forName("全类名")
        Class clazz1= Class.forName("org.example.Student");
        System.out.println(clazz1);

二、类名.class

//2、类名.class
        Class clazz2 = Student.class;
        System.out.println(clazz2);
        System.out.println(clazz2 == clazz1);

三、对象.getClass();

 //3、对象.getClass();
        Student s = new Student();
        Class clazz3 = s.getClass();
        System.out.println(clazz3);

上面显示的两个ture证明,该三种方式获得的Class字节码文件对象是一样的。

反射获取构造方法

Class类中用于获取构造方法的方法:

Constructor<?>[]getConstructors():返回所有公共构造方法对象的数组

Constructor<?>[]getDeclaredConstructors():返回所有构造方法对象的数组

Constructor<T>getConstructor(Class<?>...parameterTypes):返回单个公共构造方法对象

Constructor<T>getDelcaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象

Constructor类中用于创建对象的方法:

T newInstance(Obeject... initargs):根据指定的构造方法创建对象

setAccessible(boolean flag):设置为true,表示取消访问检查

Demo举例

package org.example.reflect;

public class Student {
    private String name;
    private int age;
    public Student(){
    }

    public Student(String name) {
        this.name = name;
    }
    private Student(String name,int age){
        this.name = name;
        this.age = age;
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
package org.example.reflect;

import java.lang.reflect.Constructor;

public class myReflect {
/** Class类中用于获取构造方法的方法
           Constructor<?>[]getConstructors():返回所有公共构造方法对象的数组
           Constructor<?>[]getDeclaredConstructors():返回所有构造方法对象的数组
           Constructor<T>getConstructor(Class<?>...parameterTypes):返回单个公共构造方法对象
           Constructor<T>getDelcaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象

     Constructor类中用于创建对象的方法
           T newInstance(Obeject... initargs):根据指定的构造方法创建对象
           setAccessible(boolean flag):设置为true,表示取消访问检查
**/
public static void main(String[] args) throws ClassNotFoundException {
    //1、获取class字节码文件的对象
    Class clazz = Class.forName("org.example.reflect.Student");

    //2、获取构造方法
    Constructor[] cons = clazz.getConstructors();
    for (Constructor con : cons) {
        System.out.println(con);
    }
}
}
返回所有公共构造方法对象的数组

获取到两个public构造方法,一个空参,一个参数是String类型

返回所有构造方法对象数组
Constructor[] cons2 = clazz.getDeclaredConstructors();
    for (Constructor con : cons2) {
        System.out.println(con);

获取单个(包括公共)构造方法
//Constructor<T>getDelcaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象
    Constructor con1 = clazz.getDeclaredConstructor();
    System.out.println(con1);

单个参数,传入String类型的字节码文件:String.class
//Constructor<T>getDelcaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象
    Constructor con1 = clazz.getDeclaredConstructor();
    System.out.println(con1);

    Constructor con2 = clazz.getDeclaredConstructor(String.class);
    System.out.println(con2);

    Constructor con3 = clazz.getDeclaredConstructor(int.class);
    System.out.println(con3);

    Constructor con4 = clazz.getDeclaredConstructor(String.class,int.class);
    System.out.println(con4);

(参数要和构造方法里面的参数保持一致)

单个参数,传入String类型的字节码文件:String.class

两个参数,传入int.class和String.class

构造方法之后

我们获得到构造方法之后我们就能做下面这些事情

一、获取修饰符
Constructor con4 = clazz.getDeclaredConstructor(String.class,int.class);
    System.out.println(con4);

//获取修饰符
    int modifiers = con4.getModifiers();
    System.out.println(modifiers);

打印出了一个2

这里为什么是2呢?

在JDK api文档中的《常量字段值》,其中指出private的字段值为2

二、获取名字。

获取对象的名称

String name = con4.getName();
    System.out.println(name);

三、获取形参。
 //获取参数
    Parameter[] parameters = con4.getParameters();
    for (Parameter parameter : parameters) {
        System.out.println(parameter);
    }

四、创建对象。
con4.Accessible(true);
Rsecret = (Student) con4.newInstance("Rsecret",16);
System.out.println(Rsecret);

直接创建对象是会报错的,原因是:(私有方法)

于是需要再调用一个方法 setAccessible()

这样对象就可以创建成功了

反射获取成员变量

Class类中用于获取成员变量方法:

Field[] getFields():返回所有公共成员变量对象的数组

Field[] getDeclaredFields():返回所有成语变量对象的数组

Field[] getField(String name):返回单个公共成员变量对象

Field[] getDeclaredField(String name):返回单个成员变量对象

Field类中用于创建对象的方法

void set(Object obj,Object value):赋值

Object get(Object obj):获取值

Demo举例

package org.example.reflect1;

public class Student {
    private String name;
    private int age;
    public String gender;
    public Student(){

    }
    public Student(String name, int age, String gender){
        this.name=name;
        this.age=age;
        this.gender=gender;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}

一、获取class字节码文件对象

Class clazz = Class.forName("org.example.reflect1.Student");

二、获取成员变量

获取所有成员变量
Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
获取全部的成员变量  需要加Declared
eg:
Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

获取单个成员变量
Field gender = clazz.getDeclaredField("name");
    System.out.println(gender);
    //这里的gender变量名可以换做name更好看

获取权限修饰符
int modifiers = name.getModifiers();
        System.out.println(modifiers);

获取成员变量的名字和数据类型
//获取成员变量的名字
        String n =name.getName();
        System.out.println(n);
//获取成员变量的数据类型
        Class<?> type = name.getType();
        System.out.println(type);

获取成员变量记录的值

这里报错的原因就是:name和age都是private私有的,所以我们需要在上面加

name.setAccessible(true);

//获取成员变量记录的值
        Student s = new Student("Rsecret",15,"男");
        name.setAccessible(true);
        String value = (String) name.get(s);
        System.out.println(value);

如图:输出了Rsecret

修改对象里面记录的值
//修改对象里面记录的值
        name.set(s,"2Rsecret");
        System.out.println(s);

反射获取成员方法

Class类中用于获取成员方法的方法:

Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的

Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的

Method getMethod(String name,Class<?>..parameterTypes):返回个人公共成员方法对象

Method getDeclaredMethod(String name,Class<?>...parameterTypes):返回单个成员方法对象

Method类中用于创建对象的方法:

Object invoke(Object obj,Object...args):运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

Demo举例

package org.example.reflect2;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public Student(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }


    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    public int getAge(int age) {
        this.age = age;
        return age;
    }

    public void sleep() {
        System.out.println("睡觉");
    }

    private void eat(String something) {
        System.out.println("在吃" + something);
    }

    public String toString() {
        return "Student{name = " + name + "}";
    }
}

获取class字节码文件对象

Class clazz = Class.forName("org.example.reflect2.Student");

获取所有的方法对象

Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);

由于没有使用Declared,因此打印出来的都是public,

为什么那么多public呢? 因为也包括父类的

加上Declared,不能获取父类的了 ,但是可以获取自己所有的方法对象了

获取指定的单一方法

Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);
获取方法的修饰符
Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);

        int modifiers = m.getModifiers();
        System.out.println(modifiers);

私有属性,因此打印出的2

获取方法的名字
String name = m.getName();
System.out.println(name);

获取方法的形参
Parameter[] parameters = m.getParamet
for (Parameter parameter : parameters
    System.out.println(parameter);

获取方法的返回值
获取方法抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
        for (Class exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

方法运行

Method类中用于创建对象的方法:

Object invoke(Object obj,Object...args):运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

Student s = new Student();
m.setAccessible(true);
Object Rsecret = m.invoke(s, "Rsecret","苹果");

获取返回值

将上面的 Rsecret,打印出来就行了

并且注意eat方法的返回值不要再设置void了,因为我们返回的是字符串,所以要设置为String类型

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值