反射原理即使用(浅尝)

本文详细介绍了Java中的SSM框架与反射机制。首先讲解了SSM框架的底层反射原理,然后阐述了反射机制的优点和获取Class对象的三种方式。接着,通过实例展示了如何使用反射操作类的成员变量、方法和构造器。最后,演示了一个基于反射的简单框架,该框架能够根据配置文件动态创建对象并执行相应方法。
摘要由CSDN通过智能技术生成

前提:刚学习了ssm框架,对ssm框架有了初步的了解,知道框架的底层实现是基于反射机制,故而学习浅尝了反射机制,仅作为学习笔记和学习记录

反射

将类的各个组成部分封装为其他对象,即为反射机制

一、优点

  1. 可以在程序运行中,操作这些对象
  2. 可与i解耦,提高程序的可扩展性

二、获取class对象的方式

  1. Class.forName(“全类名” : 将字节码文件加载进内存,返回C对象(多用于配置文件)

    //1. Class.forName("全类名"
    Class Class1 = Class.forName("Domain.Persion");
    
  2. 类名.class : 通过类名的属性class获取(多用于参数传递)

    //类名.class
    Class Class2 = Persion.class;
    
  3. 对象.getClass() : getClass()方法在Object类中定义(多用于对象的获取字节码文件)

    //对象.getClass()
    Persion persion = new Persion();
    Class Class3 = persion.getClass();
    

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一此,无论哪种一种加载方式都式获取同一个class对象,其所在内存地址都是一个

三、Class对象功能

  1. 获取成员变量们
    • Field[ ] getFields() : 获取所有public修饰的成员变量
    • Field getField(String name) :获取指定的名称的public修饰的成员变量
    • Field[ ] getDeclaredFields() :获取所有成员变量,不管什么修饰符
    • Field getDeclaredField(String name) :获取指定的名称成员变量,无论修饰符;因此可以通过暴力反射获取访问权限的属性值(private等)
  2. 获取成员方法们
    • Methods [ ] getMethods()
    • Methods getMethod(String name, 类<?>… parameterTypes)
    • Methods[ ] getDeclaredMethods()
    • Methods getDeclaredMethod(String name, 类<?>… parameterTypes)
  3. 获取构造方法们
    • Constructor<?>[ ] getConstructors() : 获取所有public修饰的构造方法
    • Constructor getConstructor(类<?>… parameterTypes) :获取指定的参数类型的public修饰的构造方法
    • Constructor<?>[ ] getDeclaredConstructors() :获取所有构造方法,不管什么修饰符
    • Constructor getDeclaredConstructor(类<?>… parameterTypes) : 获取指定的参数类型构造方法,无论修饰符;因此可以通过暴力反射获取访问权限的属性值(private等)
  4. 获取类名
    • String getName()

四、Field : 成员变量

  1. 操作:

    .setAccessible(true) : 暴力反射,忽略访问权限修饰符的安全检查

    • 赋值

      void set(Object obj,Object value)

    • 取值

      get(Object obj)

public class Demo02 {
    public static void main(String[] args) throws Exception {

        Class<Persion> persionClass = Persion.class;
        Persion p = new Persion();

        //----------------------------获取成员变量--------------------------------------------
        System.out.println("----------------获取全部成员变量(public修饰的才能获取)---------------");
        Field[] fields = persionClass.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }

        System.out.println("---------------获取指定成员变量(public修饰的才能获取)--------------------");
        Field address = persionClass.getField("address");
        Object value = address.get(p);      //获取成员变量值
        System.out.println(value);
        address.set(p,"earth");             //设置成员变量值
        System.out.println(p);

        System.out.println("---------------------获取所有成员变量,不管什么修饰符----------------------");
        Field[] declaredFields = persionClass.getDeclaredFields();
        for (Field f: declaredFields) {
            System.out.println(f);
        }

        System.out.println("---------------------获取指定成员变量,不管什么修饰符----------------------");
        Field name = persionClass.getDeclaredField("name");
        //忽略访问权限修饰符的安全检查
        name.setAccessible(true);  //暴力反射
        Object value2 = name.get(p);
        System.out.println(value2);
    }
}

五、Constructor :构造方法

  1. 操作:

    • 创建对象

      T newInstance(Object… initargs)

    • 无参构造方法

      使用class对象直接构造

      T newInstance()

public class Demo03 {
    public static void main(String[] args) throws Exception {

        Class<Persion> persionClass = Persion.class;
        Persion p = new Persion();

        //----------------------------获取构造方法--------------------------------------------
        System.out.println("----------------获取全部构造方法(public修饰的才能获取)---------------");
        Constructor<?>[] constructors = persionClass.getConstructors();
        for (Constructor c: constructors) {
            System.out.println(c);
        }

        System.out.println("---------------获取指定构造方法(public修饰的才能获取)--------------------");
        Constructor<Persion> constructor = persionClass.getConstructor(String.class, int.class, char.class);
        //创建对象
        Persion persion = constructor.newInstance("zhangsan", 21, '男');
        System.out.println(persion);

        System.out.println("---------------------获取所有构造方法,不管什么修饰符----------------------");
        Constructor<?>[] declaredConstructors = persionClass.getDeclaredConstructors();
        for (Constructor c: declaredConstructors) {
            System.out.println(c);
        }

        System.out.println("---------------------获取指定构造方法,不管什么修饰符----------------------");
        Constructor<Persion> declaredConstructor = persionClass.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        Persion persion1 = declaredConstructor.newInstance("lisi", 58);
        System.out.println(persion1);
    }
}

六、Method:成员方法

主要掌握方法的执行:

method.invoke(String name,Object… args)

具有有参和无参之分

public class Demo04 {
    public static void main(String[] args) throws Exception {
        Class<Persion> persionClass = Persion.class;
        Persion p = new Persion();

        System.out.println("------------------获得方法(无参)---------------");
        Method say = persionClass.getMethod("say");  //传入方法名
        //执行方法
        say.invoke(p);

        System.out.println("------------------获得方法(有参参)---------------");
        Method says = persionClass.getMethod("say", String.class);//传入方法名,参数类型
        //执行方法
        says.invoke(p,"nothings");

        System.out.println("----------------------获得所有public方法---------------");
        Method[] methods = persionClass.getMethods();
        for (Method m: methods) {
            System.out.println(m);     //将会获得全部放啊,包括persion的自身方法,包括继承的Object类的隐藏方法
            System.out.println(m.getName());
        }

    }
}

七、实践测试

目标:编写一个"框架",要求只改变配置文件的情况下,自动创建对象,并执行相应方法。

如:

要求根据类名和方法名,自动创建方法并执行对象中的相应方法

----------------------------------------------------------实现-------------------------------------

功能:开发人员自定义类,只需在配置文件中写入类的全限定名、需执行方法名、属性名、属性值即可实现程序的自动加载创建对象,并执行相应方法

实现方法:

public class reflectTest {
    public static void main(String[] args) throws Exception {

        //1.加载完配置文件
        Properties pro = new Properties();
        //1.1获取配置路径
        ClassLoader classLoader = reflectTest.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
        //1.2加载文件
        pro.load(resourceAsStream);
        String classname = pro.getProperty("classname");
        String methodname = pro.getProperty("methodname");
        String proname = pro.getProperty("proname");
        String provalue = pro.getProperty("provalue");

        //2.获取类对象
        Class aClass = Class.forName(classname);
        //3.获得目标类的构造方法
        Constructor constructor = aClass.getConstructor();
        //4.创建对象
        Object o = constructor.newInstance();
        //5.设置对象属性
        Field declaredField = aClass.getDeclaredField(proname);
        declaredField.setAccessible(true);   //暴力反射
        declaredField.set(o,provalue);
        //获取方法,并执行
        Method method = aClass.getMethod(methodname);
        method.invoke(o);
    }
}

自定义类(可随意定义类):

package Domain;

public class students {

    private String username;

    public void sleep(){
        System.out.println(this.username + " is sleeping");
    }

    public void eat(){
        System.out.println(this.username + " is eating");
    }

    public String getName() {
        return username;
    }

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

配置文件(pro.proterties):

#全类名
classname=Domain.students
#方法名
methodname=eat
#属性名
proname=username
#属性值
provalue=zhangsan

输出:

zhangsan is eating
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值