Java中反射机制和作用详解

 更新时间:2021年05月06日 10:34:33   作者:Java大师-  
这篇文章主要给大家介绍了关于Java中反射机制和作用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象。

那么接下来大师就带你们了解一下反射是什么,为什么要学习反射?

下面我们首先通过一个实例来说明反射的好处:

方法1、不用反射技术,创建用户对象,调用sayHello方法

1.1 我们首先创建一个User类

package com.dashi;

/**
 * Author:Java大师
 * User对象,包含用户的id和姓名以及sayHello方法
 */
public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String sayHello(String who) {
        return who+ "{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

1.2 创建测试用例

package com.dashi;

import org.junit.Test;

/**
 * 创建Juinit测试对象
 */
public class Test01 {

    @Test
    public void test01(){
        User user = new User();
        user.setId(1);
        user.setName("Java大师");
        //调用sayHello方法
        System.out.println(user.sayHello("user1"));
    }
}

1.3运行结果如下,打印出sayHello结果:

user1{id=1, name='Java大师'}

Process finished with exit code 0

方法2、通过反射技术,创建用户对象,调用sayHello方法

2.1 调用测试用例

@Test
    public void test02(){
        try {
            //创建用户对象字符串
            String obj = "com.dashi.User";
            //通过用户对象字符串加载类
            Class clz = Class.forName(obj);
            //通过newInstance方法,创建用户对象
            User user = (User)clz.newInstance();
            user.setId(2);
            user.setName("Java大师2");
            //调用sayHello方法
            System.out.println(user.sayHello("user2"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

2.2 运行结果如下,打印出sayHello结果:

user1{id=1, name='Java大师'}
user2{id=2, name='Java大师2'}

Process finished with exit code 0 

通过两者以上对比,发现方法1和方法2都能创建用户对象,并调用sayHello方法,并且打印的结果都正确。但是方法2比方法1先进的地方是方法2针对字符串编程,方法1针对实体类编程。

那么针对字符串编程有什么好处呢,小伙伴们耐心接着往下看:

我们通过一个Dao层来演示下针对字符串编程的好处:

假设我们有一个IUserDao接口,里面有一个load方法,代码如下:

package com.dashi;

public interface IUserDao {
    public void load();
}

有两个实现类来实现该IUserDao接口,实现类如下:

package com.dashi;

/**
 * A实现类
 */
public class AUserDao implements IUserDao{
    @Override
    public void load() {
        System.out.println("这是AUserDao");
    }
}
package com.dashi;

/**
 * B实现类
 */
public class BUserDao implements IUserDao{
    @Override
    public void load() {
        System.out.println("这是BUserDao");
    }
}

方法3、不通过反射技术,创建IUserDao,调用load方法

@Test
    public void testDao01(){
        IUserDao userDao = new AUserDao();
        userDao.load();
    }

打印结果如下:

这是AUserDao

Process finished with exit code 0 

方法4、通过反射技术,创建IUserDao,调用load方法

@Test
    public void testDao02(){
        try {
            //创建接口实现类字符串
            String dao_str = "com.dashi.AUserDao";
            //通过类加载的方式创建IUserDao
            IUserDao userDao = (IUserDao) Class.forName(dao_str).newInstance();
            //调用load方法
            userDao.load();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

打印结果如下:

这是AUserDao
这是AUserDao

Process finished with exit code 0 

通过类加载的方式,我们也创建了IUserDao对象,调用了load方法,和方法3的运行结果一样

方法5、通过反射技术,创建IUserDao,调用load方法

@Test
    public void testDao03(){
        try {
            //创建接口实现类字符串
            String dao_str = "com.dashi.BUserDao";
            //通过类加载的方式创建IUserDao
            Class clz = Class.forName(dao_str);
            IUserDao userDao= (IUserDao)clz.newInstance();
            //创建调用方法字符串
            String mm = "load";
            //创建method对象
            Method method =  clz.getMethod(mm);
            //调用通过反射调用invoke方法
            method.invoke(userDao);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

运行结果如下:

这是AUserDao
这是AUserDao
这是BUserDao

Process finished with exit code 0 

通过method.invoke方法也可以实现load方法的调用

方法5比方法4和方法3更加灵活,不需要知道AUserDao和BUserDao实体类,只提供类的字符串和类的方法名称,通过反射就可以实现方法的调用

实战中的实际意义

假设我们的Dao层,从mysql迁移导oracle,SQL server等

运用反射技术,通过字符串编程,那么我们不需要进行Dao层实体类的更改,只需要改动我们的字符串名字就可以进行Dao层的更新。比如:

1、不通过反射技术,我们需要修改实现类中的AUserDao改为BUserDao
IUserDao userDao = new AUserDao();
userDao.load();
``如果有几百个Dao,我们需要修改几百次``
``
2、运用发射技术通过字符串编程,我们可以把字符串定义在properties文件中,通过修改properties文件中的配置即可实现Dao的更新
 //创建接口实现类字符串
 String dao_str = "com.dashi.AUserDao"; //可以改写为:String dao_str = PropertyUtil.get("dao");
 //通过类加载的方式创建IUserDao
 IUserDao userDao = (IUserDao) Class.forName(dao_str).newInstance();
 //调用load方法
 userDao.load();

这就是反射技术的实际运用,通过以上实例就可以看出字符串编程和通过实现类编程的最大的区别和实际的意义

并且通过反射技术可以使我们的编程更加灵活

灵活运用反射技术,我们可以设计出更加灵活的框架哦~

总结

到此这篇关于Java中反射机制和作用详解的文章就介绍到这了,更多相关Java反射机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java如何实现http接口参数和返回值加密

    Java如何实现http接口参数和返回值加密

    这篇文章主要介绍了Java如何实现http接口参数和返回值加密问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Tomcat使用IDEA远程Debug调试的讲解

    Tomcat使用IDEA远程Debug调试的讲解

    今天小编就为大家分享一篇关于Tomcat使用IDEA远程Debug调试的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Spring探秘之如何妙用BeanPostProcessor

    Spring探秘之如何妙用BeanPostProcessor

    BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中会回调BeanPostProcessor中定义的两个方法,这篇文章主要给大家介绍了关于Spring探秘之如何妙用BeanPostProcessor的相关资料,需要的朋友可以参考下
    2022-01-01
  • 现代高效的java构建工具gradle的快速入门

    现代高效的java构建工具gradle的快速入门

    和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作用的是Plugin,本文主要介绍了gradle入门,文中通过示例代码介绍的非常详细,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Mybatis在insert插入操作后如何返回主键id问题

    Mybatis在insert插入操作后如何返回主键id问题

    这篇文章主要介绍了Mybatis在insert插入操作后如何返回主键id问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Spring Boot利用Docker快速部署项目的完整步骤

    Spring Boot利用Docker快速部署项目的完整步骤

    这篇文章主要给大家介绍了关于Spring Boot利用Docker快速部署项目的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • 从零开始在Centos7上部署SpringBoot项目

    从零开始在Centos7上部署SpringBoot项目

    本文主要介绍了从零开始在Centos7上部署SpringBoot项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • java system类使用方法示例 获取系统信息

    java system类使用方法示例 获取系统信息

    这篇文章主要介绍了java system类使用方法,该类中的方法都是静态的。不能被实例化,没有对外提供构造函数,该类可以获取系统信息
    2014-01-01
  • SpringBoot整合阿里云OSS对象存储服务实现文件上传

    SpringBoot整合阿里云OSS对象存储服务实现文件上传

    这篇文章主要介绍了SpringBoot整合阿里云OSS对象存储实现文件上传,帮助大家更好的理解和学习使用SpringBoot,感兴趣的朋友可以了解下
    2021-04-04
  • Java设计模式之策略模式原理与用法实例详解

    Java设计模式之策略模式原理与用法实例详解

    这篇文章主要介绍了Java设计模式之策略模式原理与用法,结合实例形式较为详细的分析了Java策略模式的概念、原理、定义及使用方法,并总结了相关的优缺点,具有一定参考借鉴价值,需要的朋友可以参考下
    2018-04-04

最新评论