面经内容
1.equals与==的使用有什么区别?
什么是==?
== 等于比较运算符,如果进行比较的两个操作数都是数值类型,即使他们的数据类型不相同,只要他们的值相等,也都将返回true。如果两个操作数都是引用类型,那么只有当两个引用变量的类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象,才会返回true。(在这里我们可以理解成==比较的是两个变量的内存地址)
什么是equals()?
equals()方法是Object类的方法,在Object类中的equals()方法体内实际上返回的就是使用==进行比较的结果,但是我们知道所有的类都继承Object,而且Object中的equals()方法没有使用final关键字修饰,那么当我们使用equal()方法进行比较的时候,我们需要关注的就是这个类有没有重写Object中的equals()方法。
区别
== 是java提供的等于比较运算符,用来比较两个变量指向的内存地址是否相同,而equals()是Object提供的一个方法,Object中equals()方法的默认实现就是返回两个对象==的比较结果,但是equals()可以被重写,所以我们在具体使用的时候需要关注equals()方法有没有被重写。
2.try catch finally执行顺序?
1.finally语句总会执行
2.如果try、catch中有return语句,finally中没有return,那么在finally中修改除包装类型和静态变量、全局变量以外的数据都不会对try、catch中返回的变量有任何的影响(包装类型、静态变量会改变、全局变量)
3.尽量不要在finally中使用return语句,如果使用的话,会忽略try、catch中的返回语句,也会忽略try、catch中的异常,屏蔽了错误的发生
4.finally中避免再次抛出异常,一旦finally中发生异常,代码执行将会抛出finally中的异常信息,try、catch中的异常将被忽略
所以在实际项目中,finally常常是用来关闭流或者数据库资源的,并不额外做其他操作。
3.Java异常有哪些?对于这两种异常分别怎么处理?
Throwable是所有异常的根,java.lang.Throwable
Error:错误,Java.lang.Error
Exception:异常,java.lang.Exception
Error代表了JVM本身的错误,不能被程序员通过代码处理,如内存溢出。
Exception分为CheckedException和RuntimeException,所有RuntimeException类及其子类的实例被称为Runtime异常,不属于该范畴的异常则被称为CheckedException。
①checkedException:
只有Java语言提供了Checked异常,Java认为checked异常都是可以被处理的异常,所以Java程序必须显示处理checked异常。如果程序没有处理checked异常,该程序在编译时会发生错误无法编译。这体现了Java的设计哲学:没有完善错误处理的代码根本没有机会被执行。
对Checked异常处理方法有两种:
1、当前方法知道如何处理该异常,则用try…catch块来处理。
2、当前方法不知道如何处理,则在定义该方法时声明抛出该异常。
②RuntimeException
Runtime如除数是0和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们。
4.OOM你遇到过哪些情况?SOF你遇到过哪些情况?
OOM(OutOfMemoryError)
除了PC外,其他几个运行时区域都有发生OOM异常的可能性。
(1) Java堆
如果堆中没有内存完成实例分配,且堆无法扩展,抛出OOM。
(2) Java栈和本地方法栈
若线程请求的栈深度大于虚拟机所允许的最大深度,将抛出SOF;
如虚拟机在扩展栈时,仍无法申请到足够的内存空间,则抛出OOM。
(3) 方法区
如果方法区无法满足内存分配需求时,将抛出OOM。
(4) 运行时常量池
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的作用是:如果池中已经包含一个等于此String的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量。
SOF(StackOverFlowError)
程序中一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过默认大小而导致溢出。
栈溢出的原因:
(1) 递归调用
(2) 大量循环或死循环
(3) 全局变量是否过多
(4) 数组、List、Map数据过多
5.谈一谈你对IOC的理解? 谈一谈你对DI的理解?
1、较浅的层次——从名字上解析
“控制”就是指对 对象的创建、维护、销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个对象(创建),在使用过程中保持引用(维护),在失去全部引用后由GC去回收对象(销毁)。
“反转”就是指对 对象的创建、维护、销毁等生命周期的控制由程序控制改为由IOC容器控制,需要某个对象时就直接通过名字去IOC容器中获取。
2、更深的层次——提到DI,依赖注入,是IOC的一种重要实现
一个对象的创建往往会涉及到其他对象的创建,比如一个对象A的成员变量持有着另一个对象B的引用,这就是依赖,A依赖于B。IOC机制既然负责了对象的创建,那么这个依赖关系也就必须由IOC容器负责起来。负责的方式就是DI——依赖注入,通过将依赖关系写入配置文件,然后在创建有依赖关系的对象时,由IOC容器注入依赖的对象,如在创建A时,检查到有依赖关系,IOC容器就把A依赖的对象B创建后注入到A中(组装,通过反射机制实现),然后把A返回给对象请求者,完成工作。
3、IOC的意义何在?
IOC并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了对 对象的可靠的管理,极大地降低了开发的复杂性。
6.Aop的原理是什么?
AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect).
SpringAOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:
(1)JDK 动态代理只提供接口代理,不支持类代理,核心 InvocationHandler 接口和Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起,Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例, 生成目标类的代理对象。
(2) 如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
7.Spring 框架中都用到了哪些设计模式?
1. 工厂模式:BeanFactory 就是简单工厂模式的体现,用来创建对象的实例
2. 单例模式:Bean 默认为单例模式
3. 代理模式:Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术
4. 模板方法 :用来解决代码重 复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate
5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener
8.springmvc的调用过程?
1. 用户发送请求到前端控制器(DispatcherServlet)
2. 前端控制器(DispatcherServlet)收到请求调用处理器映射器 (HandlerMapping),去查找处理器(Handler)
3. 处理器映射器(HandlerMapping)找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。
4. 前端控制器(DispatcherServlet)调用处理器映射器(HandlerMapping)
5. 处理器适配器(HandlerAdapter)去调用自定义的处理器类(Controller,也叫后端控制器)。
6.自定义的处理器类(Controller,也叫后端控制器)将得到的参数进行处理并返回结果给处理器映射器(HandlerMapping)
7. 处理器适配器(HandlerAdapter)将得到的结果返回给前端控制器 (DispatcherServlet)
8. DispatcherServlet( 前端控制器)将ModelAndView传给视图解析器(ViewReslover)
9. 视图解析器(ViewReslover)将得到的参数从逻辑视图转换为物理视图并返回给前端控制器(DispatcherServlet)
10. 前端控制器(DispatcherServlet)调用物理视图进行渲染并返回
11. 前端控制器(DispatcherServlet)将渲染后的结果返回
9.常用的数据库有哪些?
关系型:mysql, oracle,sql server
非关系型:redis,MongodDB
其中:mysql性能较好,适应于所有平台,开源,是中小企业中最流行的关系型数据库。而sqlserver只能在Windows上运行。
还有一种比较主流的数据库是oracle,oracle数据库适合大型数据库,mysql和sqlserver适合中小型数据库,一般使用mysql就可以,比较轻量,而且性能较好。



