深度掌握反射知识

反射是Java中一种强大的工具,允许程序在运行时检查和操作自身。它提供了动态创建对象、获取类信息、调用方法和访问字段的能力。反射在框架设计中起到关键作用,如Spring和MyBatis,提高了代码的灵活性和可扩展性,但同时也带来了性能损失和代码复杂性的增加。获取反射类有三种方式:Class.forName、类.Class和对象名.getClass,这些方式获取的类对象引用地址相同。通过反射可以创建对象、访问属性和方法,以及构造器,但需要注意其对程序清晰度的影响。
摘要由CSDN通过智能技术生成

一、什么是反射

计算机科学术语
反射是一种计算机处理方式。有程序可以访问、检测和修改它本身状态或行为的这种能力。能提供封装程序集、类型的对象。(程序集包含模块,而模块包含类型,类型又包含成员。)

用途

您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
1.使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。
2.使用 Module 了解如下的类似信息:包含模块的程序集以及模块中的类等。您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
3.使用 ConstructorInfo 了解如下的类似信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。
4.使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。
5.使用 MethodInfo 来了解如下的类似信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信 息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。
6.使用 FieldInfo 来了解如下的类似信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。
7.使用 EventInfo 来了解如下的类似信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。
8.使用 PropertyInfo 来了解如下的类似信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。
9.使用 ParameterInfo 来了解如下的类似信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。

优点

1、反射提高了程序的灵活性和扩展性。
2、降低耦合性,提高自适应能力。
3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

缺点

1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

本人理解:
反射它是框架设计的灵魂。

框架: 它就是一个半成品,客户可以引入该框架,在框架的基础上填写自己的业务代码。提高开发效率。 比如: springmvc mybatis框架 。

反射: 它就是把类中成员封装到其他类对象的形式。在通过该类对象可以获取成员的信息。
在这里插入图片描述

二、获取Class反射类的方式

获取反射类有三种方式

第一种方式 Class.forName(“类的全路径”)

package demo2;

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
    	 //第一种获取反射类方式
        Class<?> aClass = Class.forName("demo2.Student");
    }
}

<bean id="s" class="com.aaa.Student">
app.getBean("s");

第二种方式 类.Class

package demo2;

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种获取反射类方式
        //Class<?> aClass = Class.forName("demo2.Student");

        //第二种获取反射类方式
        Class<Student> aClass1 = Student.class;

    }
}

Mybatis----session.getMapper(StudentDao.class)

第三种方式 对象名.getClass()

package demo2;

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种获取反射类方式
        //Class<?> aClass = Class.forName("demo2.Student");

        //第二种获取反射类方式
        //Class<Student> aClass1 = Student.class;
        
        //第三种获取反射类方式
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();

    }
}

三种获取反射类的方式引用地址值相等吗?

package demo2;

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种获取反射类方式
        Class<?> aClass = Class.forName("demo2.Student");

        //第二种获取反射类方式
        Class<Student> aClass1 = Student.class;

        //第三种获取反射类方式
        Student student = new Student();
        Class<? extends Student> aClass2 = student.getClass();

        //三种获取反射类方式的引用地址值相等
        System.out.println(aClass==aClass1);
        System.out.println(aClass1==aClass2);
        System.out.println(aClass2==aClass);

    }
}

三、通过反射类获取对应的类对象

获取方式:

反射对象.newinstance()

package demo2;

public class Text1 {
    public static void main(String[] args) throws Exception {
        //获取反射类
        Class<Student> aClass = Student.class;
        //通过反射类获取反射对象
        Student student = aClass.newInstance();
        //通过反射类再次获取反射对象
        Student student2 = aClass.newInstance();
        //输出反射对象
        System.out.println(student);
        System.out.println(student2);
        //比较反射对象  比较的是引用地址值  地址值不能
        System.out.println(student==student2);
    }
}


在这里插入图片描述

四、获取属性类对象

getDeclaredField (通过反射类获取本类中单一属性对象)
getDeclaredFields (通过反射类获取本类中所有属性对象)
getField (通过反射类获取本类以及父类中由public修饰的单一属性)
getFields (通过反射类获取本类以及父类中所有public修饰的属性)

package demo2;



import java.lang.reflect.Field;

public class Text2 {
    public static void main(String[] args) throws Exception {
        //获取反射类对象
        Class<Student> aClass = Student.class;
        //通过反射类对象获取name属性
        Field name = aClass.getDeclaredField("name");
        System.out.println(name);
        //通过反射类获取本类中所有属性
        Field[] fields = aClass.getDeclaredFields();
        for (Field f : fields) {
            System.out.println(f);
        }

        //通过反射类获取name属性
        Field name1 = aClass.getField("name");
        System.out.println(name1);
        //通过反射类获取本类以及父类中所有 public 修饰的属性
        Field[] fields1 = aClass.getFields();
        System.out.println(fields1);

    }
}

      Class<Student> aClass = Student.class;
//        Field sexField = aClass.getDeclaredField("sex");
//        System.out.println(sexField);
//        Field phone = aClass.getDeclaredField("phone");
//        System.out.println(phone);
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field f:declaredFields){
            System.out.println(f);
        }
        System.out.println("获取本类以及父类中所有public属性对象");
//        Field address = aClass.getField("address");
//        System.out.println(address);
//        Field phone = aClass.getField("phone");
//        System.out.println(phone);

        Field[] fields = aClass.getFields();
        for (Field field:fields) {
            System.out.println(field);
        }

Field类中常见的方法

setAccessible(true) 设置私有访问权限
set(obj,value)(对象名,属性值)

package demo2;

import java.lang.reflect.Field;

public class Text3 {
    public static void main(String[] args) throws Exception {
        //获取反射类
        Class<Student> aClass = Student.class;
        //通过反射类获取类对象
        Student student = aClass.newInstance();
        System.out.println(student);
        //通过反射类获取name属性  getDeclaredField 获取本类中所有属性包括私有属性
        Field name = aClass.getDeclaredField("name");
        //打开私有访问权限
        name.setAccessible(true);
        //为对象student的name属性赋值阿娇
        name.set(student,"阿娇");
        System.out.println(student);
        
    }
}

    Class<Son> sonClass = Son.class;
        Son son = sonClass.newInstance();
        System.out.println(son);
        Field nameField = sonClass.getDeclaredField("name");
        //IllegalAccessException:
        nameField.setAccessible(true); //设置私有访问权限
        nameField.set(son,"刘德华"); //为对象son的name属性赋值“刘德华”
        System.out.println(son);

五、获取方法类对象

getDeclaredMethod(通过反射类获取本类中单一方法属性 需要传入方法名以及参数)
getDeclaredMethods (通过反射类获取本类中所有方法属性 包括私有属性)
getMethod (通过反射类获取本类以及父类中public修饰的方法属性 需要传入方法名以及参数)
getMethods (通过反射类获取本类以及父类中所有public修饰的方法属性)

package demo2;

import java.lang.reflect.Method;

public class Text4 {
    public static void main(String[] args) throws Exception {
        //获取反射类
        Class<Student> aClass = Student.class;
        //获取反射类对象
        Student student = aClass.newInstance();

        
        //通过反射类获取本类中单一方法属性
        Method show = aClass.getDeclaredMethod("show", Integer.class);
        //通过反射类获取本类中所有方法属性 包括私有属性
        Method[] methods = aClass.getDeclaredMethods();


        //通过反射类获取本类以及父类中public修饰的方法属性
        Method show1 = aClass.getMethod("show", Integer.class);
        //通过反射类获取本类以及父类中所有public修饰的方法属性
        Method[] methods1 = aClass.getMethods();
    }
}

Method类中常见方法

invoke(执行方法)
语法:方法名.invoke(对象名,参数)

package demo2;

import java.lang.reflect.Method;

public class Text4 {
    public static void main(String[] args) throws Exception {
        //获取反射类
        Class<Student> aClass = Student.class;
        //获取反射类对象
        Student student = aClass.newInstance();


        //通过反射类获取本类中单一方法属性
        Method show = aClass.getDeclaredMethod("show", Integer.class);
        //通过反射类获取本类中所有方法属性 包括私有属性
        Method[] methods = aClass.getDeclaredMethods();


        //通过反射类获取本类以及父类中public修饰的方法属性
        Method show1 = aClass.getMethod("show", Integer.class);
        //通过反射类获取本类以及父类中所有public修饰的方法属性
        Method[] methods1 = aClass.getMethods();
        
        //执行获取到的方法  invoke执行该方法  ()传入对象以及方法的参数
        Object invoke = show.invoke(student, 18);

    }
}

六、获取Constructor对象

getConstructor(通过反射类获取本类中的构造方法)

package demo2;

import java.lang.reflect.Constructor;

public class Text5 {
    public static void main(String[] args) throws Exception {
        //获取反射类
        Class<Student> aClass = Student.class;
        //通过反射类获取无参构造
        Constructor<Student> constructor = aClass.getConstructor();
        //通过无参构造创建对象
        Student student = constructor.newInstance();
        //通过反射类获取有参构造
        Constructor<Student> constructor1 = aClass.getConstructor(String.class);
        //通过有参构造创建对象
        Student student1 = constructor1.newInstance("阿娇");
    }
}

package demo2;

public class Student extends Fun {
    private String name;
    public int age;
    String sex;


    public void show(Integer id){

    }

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

    public Student() {
    }

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

package com.demo03;

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

/**
 * @program: test
 * @description:
 * @author: 闫克起2
 * @create: 2023-06-07 11:04
 **/
public class Test03 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("com.demo03.Son");
        Constructor<?> constructor = aClass.getConstructor();
        Object o = constructor.newInstance(); //<bean />
        System.out.println(o);
        Constructor<?> constructor1 = aClass.getConstructor(Object.class, int.class);
        Object instance = constructor1.newInstance("刘德华", 28);
        System.out.println(instance);
    }
}

class Son{
    private String name;//private=2  public=1 default=0 protected=4
    public int age;
    public void show(Integer a,String n){
        System.out.println("~~~~~~~~~~~~~~~~~~show~~~~~~~~~~~~~"+a+";;name="+n);
    }

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

    public Son() {
    }

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值