面试官:java反射机制的应用场景?

Java技术栈 Java技术栈     2023-01-19     677

关键词:

点击关注公众号,Java干货及时送达

作者:Seven_Nee
来源:https://segmentfault.com/a/1190000010162647

近期在维护公司项目的时候遇到一个问题,因为实体类中的 set 方法涉及到了业务逻辑,因此在给对象赋值的过程中不能够使用 set 方法,为了实现功能,所以采用了反射的机制给对象属性赋值,借此机会也了解了反射的一些具体用法和使用场景,分以下两点对反射进行分析:

  • 反射的优势和劣势

  • 反射的应用场景

反射的优势和劣势

个人理解,反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。

那上帝为什么要打开这个后门呢?

这涉及到了静态和动态的概念:

两者的区别在于,动态编译可以最大程度地支持多态,而多态最大的意义在于降低类的耦合性,因此反射的优点就很明显了:解耦以及提高代码的灵活性。

因此,反射的优势和劣势分别在于:

优势

运行期类型的判断,动态类加载:提高代码灵活度

劣势

性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

反射的应用场景

在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码。

动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架,也是利用CGLIB 反射机制才得以实现,下面就举例最常见的两个例子,来说明反射机制的强大之处。

JDBC 的数据库的连接

在JDBC 的操作中,如果要想进行数据库的连接,则必须按照以上的几步完成

  1. 通过Class.forName()加载数据库的驱动程序 (通过反射加载,前提是引入相关了Jar包)

  2. 通过 DriverManager 类进行数据库的连接,连接的时候要输入数据库的连接地址、用户名、密码

  3. 通过Connection 接口接收连接

public class ConnectionJDBC   
  
    /** 
     * @param args 
     */  
    //驱动程序就是之前在classpath中配置的JDBC的驱动程序的JAR 包中  
    public static final String DBDRIVER = "com.mysql.jdbc.Driver";  
    //连接地址是由各个数据库生产商单独提供的,所以需要单独记住  
    public static final String DBURL = "jdbc:mysql://localhost:3306/test";  
    //连接数据库的用户名  
    public static final String DBUSER = "root";  
    //连接数据库的密码  
    public static final String DBPASS = "";  
      
      
    public static void main(String[] args) throws Exception   
        Connection con = null; //表示数据库的连接对象  
        Class.forName(DBDRIVER); //1、使用CLASS 类加载驱动程序 ,反射机制的体现 
        con = DriverManager.getConnection(DBURL,DBUSER,DBPASS); //2、连接数据库  
        System.out.println(con);  
        con.close(); // 3、关闭数据库  
    

Spring 框架的使用

在 Java的反射机制在做基础框架的时候非常有用,行内有一句这样的老话:反射机制是Java框架的基石。一般应用层面很少用,不过这种东西,现在很多开源框架基本都已经封装好了,自己基本用不着写。

推荐一个 Spring Boot 基础教程及实战示例:https://github.com/javastacks/spring-boot-best-practice

典型的除了hibernate之外,还有spring也用到很多反射机制。最经典的就是xml的配置模式。另外,Spring 系列面试题和答案全部整理好了,微信搜索Java技术栈,在后台发送:面试,可以在线阅读。

Spring 通过 XML 配置模式装载 Bean 的过程:

  1. 将程序内所有 XML 或 Properties 配置文件加载入内存中

  2. Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息

  3. 使用反射机制,根据这个字符串获得某个类的Class实例

  4. 动态配置实例的属性

Spring这样做的好处是:

  • 不用每一次都要在代码里面去new或者做其他的事情

  • 以后要改的话直接改配置文件,代码维护起来就很方便了

  • 有时为了适应某些需求,Java类里面不一定能直接调用另外的方法,可以通过反射机制来实现

模拟 Spring 加载 XML 配置文件:

public class BeanFactory 
       private Map<String, Object> beanMap = new HashMap<String, Object>();
       /**
       * bean工厂的初始化.
       * @param xml xml配置文件 
       */
       public void init(String xml) 
              try 
                     //读取指定的配置文件
                     SAXReader reader = new SAXReader();
                     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                     //从class目录下获取指定的xml文件
                     InputStream ins = classLoader.getResourceAsStream(xml);
                     Document doc = reader.read(ins);
                     Element root = doc.getRootElement();  
                     Element foo;
                    
                     //遍历bean
                     for (Iterator i = root.elementIterator("bean"); i.hasNext();)   
                            foo = (Element) i.next();
                            //获取bean的属性id和class
                            Attribute id = foo.attribute("id");  
                            Attribute cls = foo.attribute("class");
                           
                            //利用Java反射机制,通过class的名称获取Class对象
                            Class bean = Class.forName(cls.getText());
                           
                            //获取对应class的信息
                            java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                            //获取其属性描述
                            java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                            //设置值的方法
                            Method mSet = null;
                            //创建一个对象
                            Object obj = bean.newInstance();
                           
                            //遍历该bean的property属性
                            for (Iterator ite = foo.elementIterator("property"); ite.hasNext();)   
                                   Element foo2 = (Element) ite.next();
                                   //获取该property的name属性
                                   Attribute name = foo2.attribute("name");
                                   String value = null;
                                  
                                   //获取该property的子元素value的值
                                   for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) 
                                          Element node = (Element) ite1.next();
                                          value = node.getText();
                                          break;
                                   
                                  
                                   for (int k = 0; k < pd.length; k++) 
                                          if (pd[k].getName().equalsIgnoreCase(name.getText())) 
                                                 mSet = pd[k].getWriteMethod();
                                                 //利用Java的反射极致调用对象的某个set方法,并将值设置进去
                                                 mSet.invoke(obj, value);
                                          
                                   
                            
                           
                            //将对象放入beanMap中,其中key为id值,value为对象
                            beanMap.put(id.getText(), obj);
                     
               catch (Exception e) 
                     System.out.println(e.toString());
              
       
      
       //other codes

最后,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 Java 系列面试题和答案,非常齐全。



关注Java技术栈看更多干货

获取 Spring Boot 实战笔记!

面试官问:“说一下java的反射机制吧”。

1.简介Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助ReflectionAPI取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。透过反射的简介我们可以了解到反射的一个比较重要... 查看详情

面试官问:“说一下java的反射机制吧”。

1.简介Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助ReflectionAPI取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。透过反射的简介我们可以了解到反射的一个比较重要... 查看详情

面试官问:“说一下java的反射机制吧”。

...类的class对象,通过A的class对象创建A类对象。3.对答面试官加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通... 查看详情

长篇图解java反射机制及其应用场景

一、什么是java反射?在java的面向对象编程过程中,通常我们需要先知道一个Class类,然后​​new类名()​​方式来获取该类的对象。也就是说我们需要在写代码的时候(编译期或者编译期之前)就知道我们要实例化哪一个类,运... 查看详情

java反射机制的适用场景及其利与弊

...ps://blog.csdn.net/zolalad/article/details/29370565   一、反射的适用场景是什么?1).Java的反射机制在做基础框架的时候非常有用,有一句话这么说来着:反射机制是很多Java框架的基石。而一般应用层面很少用,不过这种东西... 查看详情

面试题之------java反射机制

 一、反射机制概述Java反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功... 查看详情

java基础java反射机制浅解(代码片段)

文章目录反射的某场景说明反射代码应用代码安全问题总结基础知识类、实例、Class实例(第2行代码)参考反射的某场景说明应用场景:当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他... 查看详情

java反射机制

反射机制:在运行状态中,对于任意一个类,都可以知道他的所有属性和方法,对于任意一个对象,都可以调用它所有的方法,这种可以动态获取和动态调用对象方法的功能称为反射机制。使用场景:逆向代码,如反编译动态注... 查看详情

java--反射机制原理几种class获取方式及应用场景(代码片段)

目录📢学习背景🎹一、Java反射机制是什么?🎸1.1反射原理📣1.2反射例子🎵二、Java反射机制中获取Class的三种方式及区别?📀2.1Class的几种获取方式🔊2.2代码演示几种方式的区别💥三、Ja... 查看详情

深入理解java的反射机制

今天将从以下4方面来系统的学习一下java的反射机制:java反射是什么java反射(Reflection)底层实现原理java反射的简单演示java反射的应用场景1,java反射是什么首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你... 查看详情

面试官:能说说redis的持久化机制吗?

我们先来看这么一段面试场景——面试官:你们项目缓存技术用到了什么缓存技术?小帅:Redis面试官:那么问一下,Redis缓存技术用到的持久化机制是哪一种机制?小帅:AOF面试官:好吧,回... 查看详情

正式加入阿里巴巴!java反射机制面试题

...#xff1a;总结+分享看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别 查看详情

面试官:会玩牌吧?给我讲讲洗牌算法和它的应用场景吧!(代码片段)

一个在阿里云打工的清华学渣!有一次参加面试,面试官问我:“会玩牌吧?”内心:“咋滴,这是要玩德州扑克(或者炸金花),赢了他就能通过面试么?”结果……没想到面试官的下一句话:“给我讲讲洗牌算法以及它的应... 查看详情

年后上来面试了13家企业android岗位,面试题整理

先卖个关子,如果你是面试官,你希望招一个什么样的人进来?如果这个问题搞明白了,那么可以说测试岗位的面试,就变得非常轻松了。按照一般的惯例,面试官都会让你自我介绍,介绍你的项目经... 查看详情

什么是反射?以及应用场景?(代码片段)

  对编程语言比较熟悉的朋友,应该知道“反射”这个机制。Python作为一门动态语言,当然不会缺少这一重要功能。然而,在网络上却很少见到有详细或者深刻的剖析论文。下面结合一个web路由的实例来阐述python的反射机制的... 查看详情

深入浅出java!java反射复制对象

一轮:第一轮面试官(是一位女性,喜欢钻研一些细节性的东西)自我介绍1、HashMap和ArrayList的原理解释下。2、Netty原理介绍下。3.了解过NIO,BIO,AIO么?介绍下异同,代码中如何使用?4.分布式锁用过么?... 查看详情

面试官:你知道java中的回调机制吗?我竟然答不来。。(代码片段)

来源:https://www.cnblogs.com/prayjourney/p/9667835.html在一个应用系统中,无论使用何种语言开发,必然存在模块之间的调用,调用的方式分为几种。1.同步调用同步调用是最基本并且最简单的一种调用方式,类A的方法a()调用类B的方法b(),... 查看详情

面试官:countdownlatch与cyclicbarrier的使用场景?有什么区别?(代码片段)

...看到各种介绍原理,代码的,以及他们区别(应付面试)的,但是很少能讲清楚:他们到底有啥作用,怎么用,应用那些场景?为什 查看详情