[JavaSE](​反射--获取Class类对象的三种方式分类、反射获取构造方法并使用、反射获取成员变量并使用、反射获取成员方法并使用)

 ✨✨个人主页:沫洺的主页

📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 

                           📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏

                           📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏     

💖💖如果文章对你有所帮助请留下三连✨✨

🍓反射

反射机制概述

  • 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意属性和方法; 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
  • 利用反射可以无视修饰符获取类里面所有的属性和方法
  • 先获取配置文件中的信息,动态获取信息并创建对象和调用方法

反射创建对象调用方法与new创建对象的区别

  • new 类名(); 这种语法就限制着我们写代码的时候,必定会写死数据类型;(硬编码)
  • 反射的技术就可以让我们在写代码的时候,数据类型不写死,通过一个字符串表示,而且字符串还可以写在配置文件中,将来通过一些技术读配置文件中的字符串类,然后反射的技术就可以根据字符串中指定的类,反射的方式创建出这个类的对象,并且还可以用反射的方式执行这个类中的任意一个构造方法,成员方法,成员变量;(解决了硬编码问题)

反射相关类

  • Class 表示字节码文件对象,也就是类加载器加载.class文件后生成的对象;

  • Constructor 表示构造方法对象,任意一个类中的构造方法单独提取出来之后形成的对象就是这个类型;

  • Field 表示属性对象,任意一个类中的成员变量,单独提取出来之后形成的对象就是这个类型;

  • Method 表示方法对象,任意一个类中的方法,单独提取出来之后形成的对象就是这个类型;

反射的规则

  • 但凡反射,第一步一定是先获取字节码文件对象;(Class)
  • 接下来我们要反射什么东西,就一定都是 getXxx开头的方法;如果方法名后面带s获取的一定是多个,不带s获取的一定是某一个;
  • 如果方法名中带 Declared 这个单词,那么就表示暴力反射(即使是私有的,也可以反射得到);不推荐使用,因为设计类的人既然已经使用了private权限,就是希望我们不要直接操作的;如果暴力反射得到了私有的内容,执行的时候,需要忽略权限检查!
  • 反射得到的任意一个组成部分.setAccessible(true); // 忽略权限检查!

🍑获取Class类对象的三种方式分类

  • 类名.class属性

  • 对象名.getClass()方法------最简单的方法

  • Class.forName(全类名)方法------最常用的方法

代码示例

package cn.moming1;

/**
 * 获取Class对象的三种方法
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Class类中的静态方法forName("全类名")
        //全类名:包名+类名
        Class clazz1 = Class.forName("cn.moming1.Student");
        System.out.println(clazz1);
        //2.通过class属性来获取
        Class clazz2 = Student.class;
        System.out.println(clazz2);
        //3.利用对象的getClass方法来获取class对象
        //getClass方法是定义在Object类中的
        Student student = new Student();
        Class clazz3 = student.getClass();
        System.out.println(clazz3);

        System.out.println(clazz1==clazz2);
        System.out.println(clazz1==clazz3);
    }
}
class cn.moming1.Student
class cn.moming1.Student
class cn.moming1.Student
true
true

获取全类名的方式

 由于IDEA版本不同,可能不太一样,但操作差不多

🍎反射获取构造方法并使用

🥭Class类获取构造方法对象的方法

方法介绍

方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回单个构造方法对象

代码示例

🍋Constructor类用于创建对象的方法

方法介绍

方法名说明
T newInstance(Object...initargs)根据指定的构造方法创建对象
setAccessible(boolean flag)设置为true,表示取消访问检查

代码示例

学生类

package cn.moming1;

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

    public Student() {
    }

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

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

    private Student(int age) {
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package cn.moming1;

import java.lang.reflect.Constructor;

/**
 * 获取Constructor对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //getConstructors()返回所有公共构造方法对象的数组
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("=================================");
        //getDeclaredConstructors()返回所有构造方法对象的数组(包括私有)
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("=================================");
        //getConstructor(class<?>... parameterTypes)返回单个公共构造方法对象
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //getDeclaredConstructor(Class<?>... parameterTypes)返回单个构造方法对象(包括私有)
        System.out.println("=================================");
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);


    }
}
public cn.moming1.Student()
public cn.moming1.Student(java.lang.String,int)
=================================
public cn.moming1.Student()
private cn.moming1.Student(int)
private cn.moming1.Student(java.lang.String)
public cn.moming1.Student(java.lang.String,int)
=================================
public cn.moming1.Student(java.lang.String,int)
=================================
private cn.moming1.Student(java.lang.String)

获取Constructor对象并创建对象

学生类

package cn.moming1;

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

    //公共的无参构造
    public Student() {
        System.out.println("public...Student...无参构造方法");
    }
    //公共的有参构造
    public Student(String name, int age) {
        System.out.println("name为:"+name+"  age为:"+age);
        System.out.println("public...Student...有参构造方法");
    }
    //私有的有参构造
    private Student(String name) {
        System.out.println("name为:"+name);
        System.out.println("private...Student...有参构造方法");    }
}

反射创建对象类

package cn.moming1;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 获取Constructor对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //2.获取公共有参构造方法对象
        Constructor constructor = clazz.getConstructor(String.class,int.class);
        //3.利用newInstance创建Student对象----抛出异常、强转
        Student student = (Student) constructor.newInstance("沫洺", 18);
        //4.打印学生对象
        System.out.println(student);
        System.out.println("=================================");
        //2.获取公共无参构造方法对象
        Constructor constructor1 = clazz.getConstructor();
        Student student1 = (Student) constructor1.newInstance();
        System.out.println(student1);
        System.out.println("=================================");
        //2.获取私有有参构造方法对象
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
        //被private修饰的成员不能直接使用
        //如果用反射强行获取并使用,需要临时取消访问检查
        declaredConstructor.setAccessible(true);
        Student student2 = (Student) declaredConstructor.newInstance("沫洺");
        System.out.println(student2);
    }
}
name为:沫洺  age为:18
public...Student...有参构造方法
cn.moming1.Student@2d98a335
=================================
public...Student...无参构造方法
cn.moming1.Student@16b98e56
=================================
name为:沫洺
private...Student...有参构造方法
cn.moming1.Student@27d6c5e0

在上面的代码中,全都使用了强转(硬编码,写死了数据类型),这里只是为了方便演示,实际开发中,一般使用多态的方式接收对象,将来实际运行的方法的时候,运行的是子类的方法(即多态中的方法,编译看左,运行看右)

如下代码

package cn.moming1;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 获取Constructor对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //2.获取公共有参构造方法对象
        Constructor constructor = clazz.getConstructor(String.class,int.class);
        //3.利用newInstance创建Student对象----抛出异常
        //以多态的形式接收对象,将来实际运行方法的时候,运行的是子类的方法
        Object student = constructor.newInstance("沫洺", 18);
        //4.打印学生对象
        System.out.println(student);

    }
}
name为:沫洺  age为:18
public...Student...有参构造方法
cn.moming1.Student@2d98a335

🍊小结

获取class对象三种方式:

  • Class.forName(“全类名”)
  • 类名.class
  • 对象名.getClass()

获取里面的构造方法对象

  • getConstructor (Class<?>... parameterTypes)
  • getDeclaredConstructor (Class<?>... parameterTypes)

如果是public的,直接创建对象

  • newInstance(Object... initargs)
  • 普通的对象 = 构造方法对象.newInstance(构造方法的实际参数);
  • 不用强转,以多态的形式保存对象,这样可以避免硬编码

如果是非public的,需要临时取消检查,然后再创建对象

  • setAccessible(boolean) 暴力反射

🍐反射获取成员变量并使用

🍍Class类获取成员变量对象的方法

方法分类

方法名说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象

代码示例

package cn.moming1;

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

/**
 * 获取Field对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //1.获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //2.获取Field对象
        //getFirlds()返回所有公共成员变量对象的数组
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("===============================");
        //getDeclaredFirlds()返回所有成员变量对象的数组
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("===============================");
        //getFirld()返回单个公共成员变量对象
        Field field = clazz.getField("name");
        System.out.println(field);
        System.out.println("===============================");
        //getDeclaredFirld()返回单个成员变量对象
        Field declaredField = clazz.getDeclaredField("money");
        System.out.println(declaredField);
    }
}
public java.lang.String cn.moming1.Student.name
public int cn.moming1.Student.age
public java.lang.String cn.moming1.Student.gender
===============================
public java.lang.String cn.moming1.Student.name
public int cn.moming1.Student.age
public java.lang.String cn.moming1.Student.gender
private int cn.moming1.Student.money
===============================
public java.lang.String cn.moming1.Student.name
===============================
private int cn.moming1.Student.money

🍉Field类用于给成员变量赋值的方法

方法介绍

方法名说明
void set(Object obj, Object value)赋值
Object get(Object obj)获取值

代码示例

学生类

package cn.moming1;

public class Student {
    public String name;
    public int age;
    public String gender;
    private int money = 300;
}

反射set/get类

package cn.moming1;

import java.lang.reflect.Field;

/**
 * 获取Field对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //1.获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //公共成员变量
        //2.获取Field对象
        //getFirld()返回单个公共成员变量对象
        Field field = clazz.getField("name");
        //3.调用set方法赋值
        //创建一个Student对象(获取公共无参构造对象的简化方式)多态
        Object student = clazz.newInstance();
        field.set(student,"沫洺");
        Object name = field.get(student);
        System.out.println(name);
        System.out.println("=============");
        //私有成员变量
        //2.获取成员变量Filed的对象
        Field field1 = clazz.getDeclaredField("money");
        //3.取消一下访问检查
        field1.setAccessible(true);
        //创建对象--多态
        Object student1 = clazz.newInstance();
        //4.获取指定对象的money的值
        Object money = field1.get(student1);
        //5.打印
        System.out.println(money);
    }
}
沫洺
=============
300

🍈反射获取成员方法并使用

🥥Class类获取成员方法对象的方法

方法分类

方法名说明
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象

代码示例

学生类

package cn.moming1;

public class Student {
    //私有的,无参无返回值
    private void show(){
        System.out.println("私有方法,无参无返回值");
    }
    //公共的,无参无返回值
    public void function1(){
        System.out.println("function1方法,无参无返回值");
    }
    //公共的,有参无返回值
    public void function2(String name){
        System.out.println("function2方法,有参无返回值:"+name);
    }
    //公共的,无参有返回值
    public String function3(){
        System.out.println("function3方法,无参有返回值");
        return "moming";
    }
    //公共的,有参有返回值
    public String function4(String name){
        System.out.println("function4方法,有参有返回值:"+name);
        return "沫洺";
    }
}

获取成员方法对象类

package cn.moming1;

import java.lang.reflect.Method;

/**
 * 获取Method对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException{
        //获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //1.getMethods()返回所有公共成员方法对象的数组,包括继承的
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("===================");
        //2.getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("===================");
        //3.getMethod(String name,Class<?>...parameterTypes)返回单个公共成员方法对象
        Method method1 = clazz.getMethod("function1");
        System.out.println(method1);
        Method method2 = clazz.getMethod("function2", String.class);
        System.out.println(method2);
        System.out.println("===================");
        //4.getDeclaredMethod(String name,Class<?>...parameterTypes)放回单个成员方法对象
        Method method = clazz.getDeclaredMethod("show");
        System.out.println(method);
    }
}
public void cn.moming1.Student.function1()
public java.lang.String cn.moming1.Student.function4(java.lang.String)
public void cn.moming1.Student.function2(java.lang.String)
public java.lang.String cn.moming1.Student.function3()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
===================
public void cn.moming1.Student.function1()
public java.lang.String cn.moming1.Student.function4(java.lang.String)
public void cn.moming1.Student.function2(java.lang.String)
public java.lang.String cn.moming1.Student.function3()
private void cn.moming1.Student.show()
===================
public void cn.moming1.Student.function1()
public void cn.moming1.Student.function2(java.lang.String)
===================
private void cn.moming1.Student.show()

🥝Method类用于执行方法的方法

方法介绍

方法名说明
Object invoke(Object obj, Object... args)运行方法
  • 参数一: 用obj对象调用该方法
  • 参数二: 调用方法的传递的参数(如果没有就不写)
  • 返回值: 方法的返回值(如果没有就不写)

代码示例

package cn.moming1;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 获取Method对象
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //1.获取Class对象
        Class clazz = Class.forName("cn.moming1.Student");
        //2.获取成员方法对象
        Method method = clazz.getMethod("function4", String.class);
        //3.运行function4方法
        //创建一个Student对象,当作方法的调用者,多态
        Object student = clazz.newInstance();
        Object result = method.invoke(student, "moming");
        //4.打印返回值
        System.out.println(result);
    }
}
function4方法,有参有返回值:moming
沫洺

注意使用多态创建对象时,不能使用子类的方法(student.function4()),但是可以通过反射去解决这个问题

使用method对象调用invoke方法的时候,相当于把method方法对象执行起来,只需要传递普通对象和实际参数即可执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沫洺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值