2018年Java面试题搜集

2018年Java面试题搜集

1、Servlet执行流程(浏览器访问servlet的过程容器)

  客户端发起http请求,web服务器将请求发送到servlet容器,servlet容器解析url并根据web.xml找到相对应的servlet,并将request、response对象传递给找到的servlet,java

servlet根据request就知道谁发出的请求、请求信息以及其余信息,当servlet处理完业务逻辑后会将信息放入到response,并响应客户端;web

2、SpringMVC执行流程

   SpringMVC是有DispatchServlet为核心的分层控制框架,首先客户端发出一个请求,web服务器解析请求的url并匹配DispatchServlet的映射url,若是匹配的上就将这个请求放入到DispatchServlet,面试

DispatchServlet根据mapping映射配置去寻找相对应的Handle,而后把处理权给找到的Handle,Handle封装了处理业务逻辑的代码,当Handle处理完后会返回一个逻辑视图ModelAndView给DispatchServlet,sql

此时ModelAndView是一个逻辑试图不是一个正式试图,因此DispatchServlet会经过ViewResource视图资源去解析ModelAndView,而后将解析后的参数放到View中返回到客户端并展示;数据库

3、Java设计模式思想(单列模式,工厂模式,策略模式,共23种设计模式)

1,单例模式

  单例模式核心只要new一个实例对象的模式;好比数据库的链接,在线人数统计等;apache

  一些网站上的在线人数统计就是经过单例模式实现的,把一个计时器放在数据库或者内存中,当有人登陆的时候取出来加一而后再放回去;可是当有两我的同时登陆的时候,会出现同时取出计时器,同时加一,编程

同时放回去,这样就的话数据就会出错,因此咱们须要一个全局变量给所有人用,只须要new出一个实例对象,这就是单例模式应用,而且单例模式节省资源,由于它控制这实例对象的个数,有利于GC回收;后端

2,策略模式

  策略模式就是将几个类中公共的方法提取到一个新的类中,从而使扩展更容易,保证代码的可移植性,可维护性强;设计模式

  好比有一个需求是写鸭子对象,鸭子有叫、飞、外形这三种方法;若是每一个鸭子类都写这三个方法,会出现代码冗余;这时候咱们能够把鸭子的叫、飞、外形这三个方法提取出来,放到鸭父类中,让每一个鸭子都继承这个鸭父类,重写这三个方法,这样封装的代码可移植性强;数组

  当客户提出新的需求,好比鸭子会游泳,那么咱们只要在鸭父类中,添加游泳方法,便可使使得全部的鸭子会游泳,让会游泳的鸭子从新鸭父类的游泳方法便可;

3,工厂模式

  简单的工厂模式主要是统一提供对象实例的引用,经过工厂模式接口获取实例对象的引用。

  好比一个登陆功能,后端有三个类:Controller类、Interface类、实现接口的实现类;当客户端发出一个请求,当请求传送到Controller类中时,Controller类获取接口的引用对象,而实现接口的实现类的实现类中封装好的登陆业务逻辑代码。当你须要加一个注册需求的时候,只须要在接口中增长一个注册方法,实现类中实现方法,Controller类获取接口的引用对象便可,不须要改动原来的代码,实现可拓展性强;

4、冒泡排序和二分查找

1,冒泡排序

public static void mp(int a[]){
    int swap = 0;
    for(int i=0;i<a.length;i++){
        for(int j=i;j<a.lenrth;j++){
            if(a[j]>a[i]){
                swap = a[j];
                a[j] = a[i];
                a[i] = swap;
            }
        }
    }
    System.out.println(""+Arrays.toString(a));
}

2,二分查找

//a[]是一个升序的数值数组
public static int ef(int a[],int tag){
    int first = 0;
    int end =  a.length;
    for(int i=0;i<a.length;i++){
        int middle = (first + end)/2;
        if(tag = a[middle]){
            return middle;
        }
        
        if(tag > a[niddle]){
            first = middle + 1;
        }

        if(tag < a[middle]){
            end = middle -1;
        }
    }
    return 0;
}

5、关于Ajax技术理解

  Ajax为异步请求,局部刷新技术;

  在传统的页面中,用户须要点击按钮或者事件触发请求来实现页面的刷新;而异步技术不须要用户点击便可触发事件,这样使得用户体验感加强;

  好比商城的购物车的异步加载,当你点击商品时无需请求后台而直接动态修改参数;

6、父类与子类之间的调用顺序

  (1)父类静态代码块

  (2)子类静态代码块

  (3)父类构造方法

  (4)子类构造方法

  (5)子类普通方法

  (6)重写父类的方法(重写后的方法)

 7、内部类和外部类的调用

  (1)内部类能够直接调用外部类包括private类,使用外部类引用的this关键字调用便可;

  (2)外部类调用内部类须要创建内部类对象;

8、多线程

  (1)一个进程是一个独立的运行环境,能够看做是一个程序;而线程能够看做是进程的一个任务;好比QQ是一个进程,一个QQ窗口是一个线程;

  (2)在多线程程序中,多线程并发能够提升程序的效率,CPU不会由于某个线程等待资源而进入空闲状态,它会把资源让给其余的线程;

  (3)用户线程就是咱们开发程序时建立的线程,而守护线程为系统进程,如JVM虚拟中的GC;

  (4)线程的有限级别:每个线程都有优先级别,有限级别高的能够先获取CPU资源使该线程从就绪状态转为运行状态;也能够自定义有限级别;

  (5)死锁:至少两个以上线程争夺两个以上CPU资源,避免死锁就避免使用嵌套锁,只须要在他们须要同步的地方加锁和无限等待;

 9、AOP与IOC的概念(Spring核心)

  (1)AOP:面向切面编程,主要是管理系统层的业务,好比日志、权限、事物等;

    AOP是将封装好的对象剖开,找出其中对多个对象产生的影响的公共行为,并将其封装为一个可重用的模块,这个模块命名为切面(Aspect);

    切面将那些与业务逻辑无关的,却被业务模块共同调用的逻辑提取并封装起来,减小了系统中的重复代码,下降了模块的耦合度,同时提升了系统的可维护性;

  (2)IOC:Spring是开源框架,使用框架能够减小咱们的工做量,提升工做效率而且它是分层结构,即相对应的层处理相对应的业务逻辑,减小代码的耦合度;而Spring的核心IOC控制反转和AOP面向切面编程。

    IOC控制反转主要强调的是程序之间的关系是由容器控制的;容器控制对象,控制了对外部资源的获取;

    而反转即为,在传统的编程中都是由咱们建立对象获取依赖对象,正式容器帮咱们查找和注入对象,对象是被获取,因此叫反转;

10、Hibernate的核心思想

  Hibernate的核心思想是ROM对象关系映射机制;它是将表与表之间的操做映射成对象与对象之间的操做;也就是从数据库中提取的信息会自动按照你设置的映射要求封装成待定的对象;因此Hibernate就是经过将数据库表和实体类映射,使得对对象的修改即对数据对应的行进行修改;

11、Struts1和Struts2的区别

  Struts2是一个兼容Struts1和WebWork的MVC框架;

  二者的区别:

  (1)Action类

  • Struts1要求Action类继承一个抽象基类。Struts1的一个广泛问题是使用抽象类编程而不是接口。
  • Struts 2 Action类能够实现一个Action接口,也可实现其余接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现 经常使用的接口。Action接口不是必须的,任何有execute标识的POJO对象均可以用做Struts2的Action对象。

    (2)线程模式

  • Struts1 Action是单例模式而且必须是线程安全的,由于仅有Action的一个实例来处理全部的请求。单例策略限制了Struts1 Action能做的事,而且要在开发时特别当心。Action资源必须是线程安全的或同步的。
  • Struts2 Action对象为每个请求产生一个实例,所以没有线程安全问题。(实际上,servlet容器给每一个请求产生许多可丢弃的对象,而且不会致使性能和垃圾回收问题)

    (3)Servlet依赖

  • Struts1 Action 依赖于Servlet API ,由于当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
  • Struts 2 Action不依赖于容器,容许Action脱离容器单独被测试。若是须要,Struts2 Action仍然能够访问初始的request和response。可是,其余的元素减小或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。

    (4)可测性

  • 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
  • Struts 2 Action能够经过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。

   (5)捕获输入

  • Struts1 使用ActionForm对象捕获输入。全部的ActionForm必须继承一个基类。由于其余JavaBean不能用做ActionForm,开发者常常建立多余的类捕获输入。动态Bean(DynaBeans)能够做为建立传统ActionForm的选择,可是,开发者多是在从新描述(建立)已经存在的JavaBean(仍然会致使有冗余的javabean)。
  • Struts 2直接使用Action属性做为输入属性,消除了对第二个输入对象的需求。输入属性多是有本身(子)属性的rich对象类型。Action属性可以经过web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,可以用做输入/输出对象。这种ModelDriven 特性简化了taglib对POJO输入对象的引用。

   (7)表达式语言

  • Struts1 整合了JSTL,所以使用JSTL EL。这种EL有基本对象图遍历,可是对集合和索引属性的支持很弱。
  • Struts2可使用JSTL,可是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).

   (8)绑定值到页面(view)

  • Struts 1使用标准JSP机制把对象绑定到页面中来访问。
  • Struts 2 使用 "ValueStack"技术,使taglib可以访问值而不须要把你的页面(view)和对象绑定起来。ValueStack策略容许经过一系列名称相同但类型不一样的属性重用页面(view)。

   (9)类型转换

  • Struts 1 ActionForm 属性一般都是String类型。Struts1使用Commons-Beanutils进行类型转换。每一个类一个转换器,对每个实例来讲是不可配置的。
  • Struts2 使用OGNL进行类型转换。提供基本和经常使用对象的转换器。

   (10)校验

  • Struts 1支持在ActionForm的validate方法中手动校验,或者经过Commons Validator的扩展来校验。同一个类能够有不一样的校验内容,但不能校验子对象。
  • Struts2支持经过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性

  (11)Action执行控制

  • Struts1支持每个模块有单独的Request Processors(生命周期),可是模块中的全部Action必须共享相同的生命周期。
  • Struts2支持经过拦截器堆栈(Interceptor Stacks)为每个Action建立不一样的生命周期。堆栈可以根据须要和不一样的Action一块儿使用。

12、最优删除字符串中的某个字符

//String.replace()方法用法
String b = "abcabcabc";
b=b.replace("b","");

十3、Arraylist和Linkedlist的区别

  两者都是实现List接口的列表;Arraylist是基于数组的数据结构,Linkedlist是基于链表的数据结构;

  当获取特定元素时,Arraylist效率比较快,它经过数组小标便可获取;而Linkedlist须要移动指针;

  当存储和删除元素时,Linkedlist效率快,只须要将指针移动指定位置增长或者删除便可;而Arraylist须要移动数据;

十4、Mybatis与Ibatis的区别

  随着开发团队转投Google Code旗下,ibatis3.x正式改名为Mybatis;

  Mybatis与Ibatis2.x区别:

  (1)Mybatis实现了接口绑定(最重要的改进)

  在Ibatis2.x中咱们须要在DAO的实现类中指定具体对应哪一个xml映射文件,而Mybatis实现了DAO接口与xml映射文件的绑定,自动为咱们生成接口的具体实现,使用起来变得更加省事和方便。 

  注意: 虽然Mybatis支持在接口中直接使用annotation的配置方式来简化配置,不过强烈建议仍然使用xml配置的方式。毕竟annotation的配置方式功能有限且代码入侵性太强。使用xml配置方式才能体现出Mybatis的优点所在;

  (2)对象关系映射的改进(效率更高)

  在使用ibatis2.x的朋友并无经过ibatis的xml映射文件来实现对象间的关系映射。其实也确实没有必要那么作,由于ibatis2.x采用的是“嵌套查询”的方式将对象之间的关系经过查询语句的直接拼装来实现,其效果和在DAO或Service中自行封装是同样的。

  不过这种方式存在“N+1查询问题”。

  归纳地讲,N+1查询问题能够是这样引发的: 

   你执行了一个单独的SQL语句来获取结果列表(就是+1)。  

  对返回的每条记录,你执行了一个查询语句来为每一个加载细节(就是N)。 

  这个问题会致使成百上千的SQL语句被执行。这一般不是指望的。

  而在Mybatis中,除了兼容ibatis2.x中的“嵌套查询”方式外,还提供了直接“嵌套结果”的方式,其效果至关于直接经过一句sql将查询出的dto对象自动封装成所需的对象。 

  不过实际上这一改进所带来的好处也是颇有限的。由于这一方式在使用分页的时候并不起做用,或者说嵌套对象的结果集是不容许进行分页的。这一点在Mybatis框架中已经作出了明确的限制org.apache.ibatis.executor.resultset.NestedResultSetHandler里34行),而实际项目中须要分页的状况又特别多…… 

  仔细一想,一对多映射确实不能经过配置文件来分页,由于这时查询出的记录数并不等于实际返回对象的size,不过一对一映射为何也不容许就不太明白了。多是由于一对一是一对多的特例,而在设计框架的时候并无考虑去处理或是难于处理这一特例吧。

  (3)MyBatis采用功能强大的基于OGNL的表达式来消除其余元素

  MyBatis采用OGNL表达式简化了配置文件的复杂性,使用起来更简洁。 

十5、数据库优化

  (1)选择合适的字段,好比邮箱字段能够设为char(6),尽可能把字段设置为not null,这样查询的时候数据库就不须要比较null值

  (2)使用关联查询( left join on)查询代替子查询

  (3)使用union联合查询手动建立临时表

  (4)开启事物,当数据库执行多条语句出现错误时,事物会回滚,能够维护数据库的完整性

  (5)使用外键,事物能够维护数据的完整性可是它却不能保证数据的关联性,使用外键能够保证数据的关联性

  (6)使用索引,索引是提升数据库性能的经常使用方法,它能够令数据库服务器以比没有索引快的多的速度检索特定的行,特别是对于max,min,order by查询时,效果更明显

  (7)优化的查询语句,绝大多数状况下,使用索引能够提升查询的速度,但若是sql语句使用不恰当的话,索引没法发挥它的特性。

十6、Tomcat服务器优化(内存,并发链接数,缓存)

  (1)内存优化:主要是对Tomcat启动参数进行优化,咱们能够在Tomcat启动脚本中修改它的最大内存数等等。

  (2)线程数优化:Tomcat的并发链接参数,主要在Tomcat配置文件中server.xml中配置,好比修改最小空闲链接线程数,用于提升系统处理性能等等。

  (3)优化缓存:打开压缩功能,修改参数,好比压缩的输出内容大小默认为2KB,能够适当的修改。

十7、HTTP协议

  (1)经常使用的请求方法有get、post

  (2)Get与post的区别:传送数据,get携带参数与访问地址传送,用户能够看见,这的话信息会不安全,致使信息泄露。而post则将字段与对应值封装在实体中传送,这个过程用户是不可见的。Get传递参数有限制,而post无限制。

十8、TCP/UDP协议

  (1)TCP协议:面向链接(如打电话须要先拨号链接);

    UDP协议:无链接,即发送数据以前不须要先创建链接;

  (2)TCP协议:提供可靠的服务,即经过TCP传输的数据,无差错,不丢失,不重复,且按序到达;

    UDP协议:尽最大努力交付,即不保证可靠交付;

  (3)TCP协议:TCP面向字节流,其实是TCP把数据看出一串无结构的字节流;

    UDP协议:UDP是面向报文的,UDP没有拥塞控制,所以网络出现拥塞不会使源主机的发送速率下降(对实时应用颇有用,如IP电话、视频会议等);

  (4)TCP协议:每一条TCP链接只能点到点;

    UDP协议:UDP支持一对1、一对多、多对1、多对多的交互通信;

  (5)TCP协议:TCP首部开销20个字节;

    UDP协议:UDP首部开销8个字节;

  (6)TCP协议:TCP的逻辑通讯信道是全双工的可靠信道;

    UDP协议:是不可靠信道;

十9、Java集合类框架的基本接口有哪些

1,Collection接口:元素集合,单列集合根接口;

  (1)List接口:继承Collection接口,有序元素集合,元素可重复;

    <1> ArrayList类:实现List接口,基于数组的数据结构,适合查询,不适合增删;

    <2> LinkedList类:实现List接口,基于链表的数据结构(底层是双向循环链表),适合增删,不适合查询;

    <3> Vector类:实现List接口;

      ① Stack类:继承Vector类;

  (2)Set接口:继承Collection接口,无序元素集合,元素不可重复;

    <1> HashSet类:实现Set接口,根据对象的哈希值肯定元素在集合中的位置;

    <2> SortedSet类:实现Set接口;

      ① TreeSet类:继承SortedSet类,以二叉树的方式存储元素,实现对集合中的元素进行排序;

2,Map接口:键值对集合,双列集合的根接口;

  (1)hashMap类:实现Map接口,性能好;

  (2)HashTable类:实现Map接口,线程安全;

  (3)SortedMap类:实现Map接口,用于存储键值的映射关系,不能出现重复的键(key);

    ① TreeMap类:继承SortedMap类,用于存储键值的映射关系,不能出现重复的键(key),全部的键按照二叉树的方式排列;

java.util.Collection [I]
|—java.util.List [I]
    |—java.util.ArrayList [C]
    |—java.util.LinkedList [C]
    |—java.util.Vector [C]
        |—java.util.Stack [C]
|—java.util.Set [I]
    |—java.util.HashSet [C]
    |—java.util.SortedSet [I]
        |—java.util.TreeSet [C]

java.util.Map [I]
|—java.util.SortedMap [I]
    |—java.util.TreeMap [C]
|—java.util.Hashtable [C]
|—java.util.HashMap [C]
    |—java.util.LinkedHashMap [C]
|—java.util.WeakHashMap [C]

二10、类加载的过程

  遇到一个新的类时,首先会在方法区去找class文件,若是没有找到就会去硬盘中找class文件,找到后返回将class文件加载到方法区中;在类加载的时候,静态成员变量会被分配到方法区的静态区域;非静态成员变量分配到非静态区;而后开始给静态成员变量初始化,赋默认值;赋完默认值后,会根据静态成员变量的书写位置赋显示值,而后执行静态代码;当全部的静态代码执行完,类加载才算完成;

二11、对象的建立

  对象建立的过程:

  (1)遇到一个新类时,会进行类加载,定位到class文件;

  (2)对全部静态成员变量初始化,静态代码块也会执行,并且只在类加载的时候执行一次;

  (3)NEW对象时,JVM会在堆中分配一个足够大的存储空间;

  (4)存储空间清空,为全部的变量赋默认值,全部对象的引用赋值为NULL;

  (5)根据书写的位置给变量一些初始化的操做;

  (6)调用构造器方法(没有继承);

二12、JVM优化

  (1)设置参数,设置JVM的最大内存数;

  (2)垃圾回收器的选择;

二十3、高并发处理

  (1)代码层次:Java的同步锁,典型的就是同步关键字Synchronized;

  (2)数据库层次:悲观锁和乐观锁;

    <1> 悲观锁:是指对数据被外界(包括本系统当前的其余事物,以及来自外部系统的事物处理)修改保持保守态度,所以,在整个数据处理过程当中,将数据处于锁定状态;

      悲观锁的实现,每每依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,不然,即便在本系统中实现了加锁机制,也没法保证外部系统不会修改数据);

    <2> 乐观锁:乐观锁机制采起了更加宽松的加锁机制,大多数基于数据版本(Version)记录机制实现;

      乐观锁的实现,是将数据表增长一个字段版本(Version),对于不一样的人员操做数据库时,都会有个版本好1,2,3这样的数字;

      当数据库接受更新数据的时候,会根据“提交数据版本大 于数据库记录当前版本”来判断是否更新或者驳回的乐观锁策略;

      因为整个过程没有对数据库进行数据加锁,因此大大提升了大并发量下的系统总体性能表现;

      乐观锁机制每每基于系统中的数据存储逻辑,所以有必定的局限性(外部系统对数据的更新操做,咱们能够采用将乐观锁策略在数据存储过程当中实现来解决,开放存储过程更新路径,不直接开放数据表);

  (3)常见案例

    <1> 案例一:订票系统,某航班只有一张机票,假定有1W人打开你的网站来订票,问你如何解决并发问题(能够扩展到任何高并发网站要考虑的并读写问题)

      问题分析:a:1W人来访问,票没出去前要保证你们都能看到有票,不可能一我的在看到票的时候其余人就都看不到了;到底谁能抢到,那得看网速;

              b:并发问题,1W人同时点击购买,到底谁能成交?总共就一张票;

      解决方案:采用乐观锁;乐观锁是在不锁表的状况下,利用业务的控制来解决并发问题,这样既保证了数据的并发可读性又保证了数据的排他性,保证性能的同时解决了并发带来的脏数据问题;

      实现思路:Hibernate实现乐观锁;

             前提:在表中增长一个冗余字段,Version版本号,long类型;

           原理:只有当前版本号>=数据库版本号,才能提交;提交成功后,版本号Version++;

           代码:在ormpping增长一属性optimistic-lock = "version"便可,

              <hibernate-mapping>

                <class name = "com.insigma.stock.ABC" optimistic-lock = "version" table = "T_Stock" schema = "STOCK">

              </hibernate-mapping>

    <2> 案例二:股票交易系统,银行系统,大数据量你是如何考虑

      问题分析:Oracle数据单张表达到100万记录后,查询性能就不好;

      解决方案:大数据量系统必须考虑表拆分(表名字不同,但结构彻底同样)

          a:按业务分:好比手机号的表,咱们能够根据前3位数来拆分表;

          b:利用Oracle的表拆分机制作分表;

          c:若是是交易系统,咱们能够考虑采用时间轴来拆分;

      注意:还要考虑缓存:hibernate自己提供的一级二级缓存、内存缓存;

         好比常常搜索的商品,将信息放在内存缓存中,能够大大的提升性能;专业的独立缓存框架memcached等,可独立部署一个缓存服务器;

二十4、事物的理解

  事物具备原子性、一致性、持久性、隔离性;

  (1)原子性:是指一个事物中,要么所有执行,要么所有失败回滚;

  (2)一致性:事物执行以前和执行以后都出于一致性状态;

  (3)持久性:事物对数据的操做是永久性;

  (4)隔离性:当一个事物正在对数据进行操做时,另外一个事物是不能够对数据进行操做,也就是多个事物之间是相互隔离的;

二十5、Struts工做流程

  (1)客户端发出一个请求到servlet容器;

  (2)请求通过一些列过滤FilterDispatch调用,FilterDispatch经过ActionMapper去找相对应的Action;

  (3)ActionMapper找到相对应的Action返回给FilteDispatch,Dispatch把处理权交给ActionProxy

  (4)ActionProxy经过配置文件找到对应的Action类;

  (5)ActionProxy建立一个ActionLinvocation的实例处理业务逻辑;

  (6)Action处理完毕,ActionInocation负责根据struts.xml的配置找到对应的返回结果(返回结果一般是Jsp页面);

相关文章
相关标签/搜索