Java反射的基本知识

1.反射的概念

  Java 的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法; 并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。
  通过上面的概念,可以看出有两个意义:
   - 任何一个类,都能够知道这个类的所有属性和方法
   - 任何一个对象,都能够调用它的任意一个方法
下面我们就根据上述这两个意义,来说明下反射。

2.实验的基本代码组成

  主要是创建了Student.java和App.java两个文件,其中Student代表学生类,App用作测试类。基本代码如下:

package org.example;

/**
 * @createTime 2023-02-06 10:58
 * @description
 */
public class Student {
    private String name;
    private Integer age;
    private String address;

    public Student() {
    }
    public Student(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public void like() {
        System.out.println("我的爱好是打篮球");
    }
    public void reading(String book) {
        System.out.println("我正在读" + book);
    }
    private String getFatherName() {
        System.out.println("我的父亲叫张三");
        return "张三";
    }
}
package org.example;

public class App {
    public static void main(String[] args) {
    }
}

3.任何一个类,都能够知道这个类的所有属性和方法

  下面我们对任何一个类,如何知道这个类的所有属性和方法,代码如下:

public class App {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> clazz = Class.forName("org.example.Student");
        //获得所有访问权限为public的属性
//        Field[] fields = clazz.getFields();
        //获取类中声明的所有属性
//        Field[] fields = clazz.getDeclaredFields();
//        for (Field field : fields) {
//            System.out.println(field.getName());
//        }
        //获取所有访问权限为public的方法
//        Method[] methods = clazz.getMethods();
        //获取类中声明的所有方法
//        Method[] methods = clazz.getDeclaredMethods();
//        for (Method method : methods){
//            System.out.println(method.getName());
//        }
    }
}

4.任何一个对象,都能够调用它的任意一个方法

package org.example;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class App {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> clazz = Class.forName("org.example.Student");
        //根据方法名或者其中一个方法
        Method method = clazz.getDeclaredMethod("getFatherName");
        //将该方法设置为可访问
        method.setAccessible(true);
        //获取无参构造器,然后通过构造器生成实例对象,这种方式可以使用无参或者有参的构造器
        Constructor<?> constructor = clazz.getConstructor();
        //生成对象
        Object o = constructor.newInstance();
        //直接生成无参的方式生成实例对象
//        Object o = clazz.newInstance();
        //方法调用
        Object invoke = method.invoke(o);
        System.out.println(invoke);
    }
}

5.Class类对象

  通过上面的两段代码我们看到,这其中最关键的就是要获取类的Class实例对象。每个类都有一个Class对象,用于在运行时提供或获得某个对象的类型信息,每当编译一个新类就产生一个Class对象。比如上面代码中创建一个Student类,那么JVM就会创建一个Student对应的Class类的Class对象,该Class对象保存了Student类相关的类型信息。
  反射中生成Class对象的方式主要有以下三种:

  1. 使用Class.forName静态方法
		Class<?> clazz = Class.forName("org.example.Student");
  1. 使用类的.class方法
		Class clazz = Student.class;
  1. 使用实例对象的getClass对象
        Student student = new Student();
        Class clazz = student.getClass();

6.反射基本的API使用

6.1通过反射创建对象
  1. 通过Class的newInstance()方法创建对象
  Class<?> clazz = Class.forName("org.example.Student");
  //通过Class的newInstance()方法创建对象,这种方式其实是利用无参构造器创建的对象
  Object o = clazz.newInstance();
  1. 通过Constructor的newInstance()方法创建对象,这种情况又可以分为无参和有参构造器
    Class<?> clazz = Class.forName("org.example.Student");
    //获取无参构造器
    Constructor<?> constructor = clazz.getConstructor();
    Object o = constructor.newInstance();
    //获取有参的构造器
   Constructor<?> constructor1 = clazz.getConstructor(String.class);
   Object o1 = constructor1.newInstance("张二");
6.2通过反射获取类的构造器
        Class<?> clazz = Class.forName("org.example.Student");
        //获取所有公共的构造方法,即以public修饰的
        Constructor[] constructors = clazz.getConstructors();
        //获取所有公共的构造方法,不论修饰符是什么
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        //获取一个无参构造函数
        Constructor<?> constructor = clazz.getConstructor();
        //获取一个参数类型为String的构造函数
        Constructor<?> constructor1 = clazz.getConstructor(String.class);
6.3通过反射获取类的成员变量
       Class<?> clazz = Class.forName("org.example.Student");
        //获取类的所有的公共属性,即以public来修饰的属性
        Field[] fields = clazz.getFields();
        //获取类的所有属性,不论以何种修饰符修饰的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        //根据变量名,返回一个具体的具有public属性的成员变量
        Field name = clazz.getField("name");
        //根据变量名,返回一个具体的属性
        Field name1 = clazz.getDeclaredField("name");
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值