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 Executors工具类的相关方法使用创建

    java Executors工具类的相关方法使用创建

    这篇文章主要为大家介绍了java Executors工具类的相关方法使用创建,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Java与Python两种编程语言的比较与应用举例详解

    Java与Python两种编程语言的比较与应用举例详解

    这篇文章主要介绍了Java与Python两种编程语言比较与应用的相关资料,Java和Python各有特点,Java适用于企业级应用开发,Python则在数据科学和机器学习领域占优势,两者在语法、应用领域、性能、开发效率等方面存在差异,需要的朋友可以参考下
    2025-02-02
  • java中的十个大类总结

    java中的十个大类总结

    java.lang.string字符串类将是无可争议的冠军在任何一天的普及和不可以否认。这是最后一个类,用来创建操作不可变字符串字面值
    2013-10-10
  • Spring Boot+RabbitMQ 通过fanout模式实现消息接收功能(支持消费者多实例部署)

    Spring Boot+RabbitMQ 通过fanout模式实现消息接收功能(支持消费者多实例部署)

    这篇文章主要介绍了Spring Boot+RabbitMQ 通过fanout模式实现消息接收(支持消费者多实例部署),本文通过案例场景分析给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • SpringBoot+Redis海量重复提交问题解决

    SpringBoot+Redis海量重复提交问题解决

    在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,所以本文介绍一下SpringBoot+Redis海量重复提交问题解决,感兴趣的可以了解一下
    2023-12-12
  • SpringBoot 整合 Shiro 密码登录的实现代码

    SpringBoot 整合 Shiro 密码登录的实现代码

    这篇文章主要介绍了SpringBoot 整合 Shiro 密码登录的实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Java中静态代理的使用与原理详解

    Java中静态代理的使用与原理详解

    这篇文章主要介绍了Java中静态代理的使用与原理详解,代理模式是为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能,需要的朋友可以参考下
    2023-09-09
  • 教你在JNA中将本地方法映射到JAVA代码中的示例

    教你在JNA中将本地方法映射到JAVA代码中的示例

    对于JNI来说,我们可以使用native关键字来定义本地方法。那么在JNA中有那些在JAVA代码中定义本地方法的方式呢?对JNA本地方法映射JAVA代码的相关知识感兴趣的朋友一起看看吧
    2022-04-04
  • Java判断一个实体是不是空的简单方法

    Java判断一个实体是不是空的简单方法

    这篇文章主要给大家介绍了关于Java判断一个实体是不是空的简单方法,实际项目中我们会有很多地方需要判空校验,文中给出了详细的示例代码,需要的朋友可以参考下
    2023-07-07
  • Spring Boot拓展XML格式的请求和响应操作过程

    Spring Boot拓展XML格式的请求和响应操作过程

    在我们开发过程中,我们经常使用的参数绝大多少事HTML和JSON格式的请求和响应处理,但是我们在实际开发过程中,我们可能经历一些,比如对于XML格式的请求,本文给大家介绍Spring Boot拓展XML格式的请求和响应,感兴趣的朋友一起看看吧
    2023-10-10

最新评论