• 每日五问(java)


    一.请你说一下Java反射的优缺点
    反射是Java语言中比较重要的特性,它能够在程序运行的过程中去构造任意一个类对象并且获取任意一个类的成员变量成员方法属性以及调用任意一个对象的方法。
    优点:
    (1)增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作。
    (2)提高代码的复用率,比如动态代理,就是用到了反射来实现
    (3)可以在运行时轻轻松松获取任意一个类的方法,属性,并且还能通过反射进行动态调用。
    缺点:
    (1)反射会涉及到动态类型的解析,所以JVM无法对这些代码进行优化,导致性能要比非反射调用更低。
    (2)使用反射以后,代码的可读性会下降。
    (3)反射可以绕过一些限制访问的属性或者方法,可能会导致破坏了代码本身的抽象性。
    二.Integer a1=100; Integer a2=100; a1==a2 运行结果和原因
    首先Integer a1=100;把一个int类型赋值给封装类型java会默认进行装箱操作调用Integer.valueof()方法把数字100包装成一个Integer类型其次在Intrger内部设计模式中用到了享元设计,享元模式是通过对象创建减少对对象的创建减少内存占用和提升性能Integer内部维护一个IntegerCache它缓存一个[-128,127]区间的数值,一旦调用Integer.valueof()方法就直接从cache获取Integer对象否则就会创建一个新的对象。\n所以两个Integer对象值都是100,因为自动装箱机制会调用Integer.valueof()方法从IntegerCache中拿到两个完全相同的值所以返回结果为true
    三.Integer 使用不当导致生产的事故
    (1)Integer 是一个封装类型。它是对应一个 int 类型的包装。
    (2)在 Java 里面之所以要提供 Integer 这种基本类型的封装类,是因为 Java 是一个
    面向对象的语言,而基本类型不具备对象的特征,所以在基本类型上做了一层对象的包装并且提供了相关的属性和访问方法来完善基本类型的操作。
    (3)在 Integer 这个封装类里面,除了基本的 int 类型的操作之外,还引入了享元模
    式的设计,对-128 到 127 之间的数据做了一层缓存,也就是说,如果 Integer
    类型的目标值在-128 到 127 之间.
    (4)就直接从缓存里面获取 Integer 这个对象实例并返回,否则创建一个新的 Integer
    对象。
    这么设计的好处是减少频繁创建 Integer 对象带来的内存消耗从而提升性能。
    因此在这样一个前提下,如果定义两个 Integer 对象,并且这两个 Integer 的取值范围正好在-128 到 127 之间。如果直接用==号来判断,返回的结果必然是 true,因为这两个 Integer 指向的内存地址是同一个。否则,返回的结果是 false。之所以在测试环境上没有把这个问题暴露出来,是因为测试环境上验证的数据量有限,使得取值的范围正好在 Integer的缓存区间,从而通过了测试。但是在实际的应用里面,数据量远远超过 IntegerCache 的取值范围,所以就导致了校验失败的问题。
    四.Bean的生命周期
    (1)创建前准备阶段
    这个阶段主要的作用是,Bean 在开始加载之前,需要从上下文和相关配置中解析并查找 Bean 有关的扩展实现,比如像 init-method-容器在初始化 bean 时调用的方法、destory-method,容器在销毁 bean 时调用的方法。以及BeanFactoryPostProcessor 这类的 bean 加载过程中的前置和后置处理。这些类或者配置其实是 Spring 提供给开发者,用来实现 Bean 加载过程中的扩展机制,在很多和 Spring 集成的中间件中比较常见,比如 Dubbo。
    (2)创建实例阶段
    这个阶段主要是通过反射来创建 Bean 的实例对象,并且扫描和解析 Bean 声明的一些属性
    (3)依赖注入阶段
    如果被实例化的 Bean 存在依赖其他 Bean 对象的情况,则需要对这些依赖 bean
    进行对象注入。比如常见的@Autowired、setter 注入等依赖注入的配置形式。同 时 , 在 这 个 阶 段 会 触 发 一 些 扩 展 的 调 用 , 比 如 常 见 的 扩 展 类 :
    BeanPostProcessors(用来实现 bean 初始化前后的扩展回调)、InitializingBean(这个类有一个afterPropertiesSet(),这个在工作中也比较常见)、BeanFactoryAware 等等。
    (4)四、容器缓存阶段
    容器缓存阶段主要是把 bean 保存到容器以及 Spring 的缓存中,到了这个阶段,
    Bean 就可以被开发者使用了。这个阶段涉及到的操作,常见的有,init-method 这个属性配置的方法, 会在这个阶段调用。
    以 及 像 BeanPostProcessors 方 法 中 的 后 置 处 理 器 方 法 如 :postProcessAfterInitialization,也会在这个阶段触发
    (5)销毁实例阶段
    当 Spring 应用上下文关闭时,该上下文中的所有 bean 都会被销毁。如果存在 Bean 实现了 DisposableBean 接口,或者配置了 destory-method 属性,会在这个阶段被调用
    补充:bean的完整生命周期只适用于单例 就是当scope=”singleton“时候当scope=”prototype“时候销毁部分不加载
    五.谈谈你对springmvc的理解?
    SpringMVC是属于 framework 生态里的模块 它是在servlet基础上使用并构建MVC模式设计的一个web框架。它的主要目的是简化传统的servlet+jsp模式下的web开发模式。其次springMVC的架构设计是对java web MVC设计模式 做了一些增强和扩展主要体现在几个方面
    (1)把传统的MVC 中的Controller拆分成前端控制器 DispatcherSrvlet和后端控制器Controller。
    (2)把Model层拆分成 服务层service和业务层repository。
    (3)在视图层可以支持不同的视图Freemark,jsp等。
    所以springMVC天生就是为MVC模式设计的因此在开发MVC应用的时候会更加方便和灵活。
    最后springMVC的整体工作流程浏览器的请求首先会去经过SpringMVC里面的核心控制器叫DispatcherSrvlet它主要是把请求分发到对应的Controller中Controller中处理完业务逻辑之后会返回ModelAndView然后DispatcherSrvlet会寻找一个或者多个ViewResolver找到ModelAndView指定的视图把数据展示到客户端。

  • 相关阅读:
    MIPI CSI-2笔记(19) -- 数据格式(用户自定义数据格式)
    【博学谷学习记录】超强总结,用心分享|架构师-Spring核心组件介绍
    EDI 许可证申请对网站有哪些要求?
    (二)基于企业现金流预测的投资决策-算法实现
    介绍a股level2数据接口委托队列的作用
    Linux 压缩和解压指令
    本周技术概要20231016-20231022与生活点滴
    【关于lombok框架一文秒懂】
    【ARM入门】ARM、SOC、ARM授权 概念篇
    NSIS:禁止选择安装路径和编辑安装目录
  • 原文地址:https://blog.csdn.net/Nicholas_giao/article/details/127901638