Java高频面试题汇总--Java职场范儿

经历了两周的面试,终于收到了几个满意的offer。换工做的过程是痛苦的,除了一天快马加鞭地跑好几家公司面试,剩下的时间基本就是背面试题了。想找到一份适合本身的面试题并不简单,好比我找的是高级Java开发的职位。出于以前公司系统架构的设计,须要准备Java、spring、springboot、mysql、mybatis、mycat、zookeeper、dubbo、kafka、redis、网络等面试题。我结合以前面试的20多家公司,以及从CSDN/简书/掘金/公众号等相关渠道搜集到的面试题,从中整理出一些高频的面试题库,帮助你们更加省力从容的应付面试。更全的整理题库,能够经过搜索微信小程序【Java职场范儿】或扫描最下方小程序二维码。轻轻松松地刷题。html

Java面试题

反射篇

1、Java获取Class文件的几种方式?java

//1.经过Object类中的getClass()方法的。
public static void getClassObject_1() {  
    Person p = new Person();  
    Class clazz = p.getClass();  
}
//2.任何数据类型都具有一个静态的属性.class来获取其对应的Class对象
public static void getClassObject_1() {  
    Class clazz = Person.class;
}
//3.只要经过给定的类的字符串名称就能够获取该类
public static void getClassObject_1() { 
    String className = "Person";  
    Class clazz = Class.forName(className); 
}

2、如何获取Class中的私有方法?mysql

Method method = e.getClass().getDeclaredMethod("私有方法名",String.class);

集合+并发篇

1、 HashMap和ConcurrentHashMap的原理(并发必问)程序员

HashMap:
1.7版本,使用一个Entry数组来存储数据,用key的hashcode取模来决定key会被放到数组里的位置,若是hashcode相同,或者hashcode取模后的结果相同(hash collision),那么这些key会被定位到Entry数组的同一个格子里,这些key会造成一个链表。在hashcode特别差的状况下,比方说全部key的hashcode都相同,这个链表可能会很长,那么put/get操做均可能须要遍历这个链表。也就是说时间复杂度在最差状况下会退化到O(n)
1.8版本,使用一个Node数组来存储数据,但这个Node多是链表结构,也多是红黑树结构,若是插入的key的hashcode相同,那么这些key也会被定位到Node数组的同一个格子里。若是同一个格子里的key不超过8个,使用链表结构存储。若是超过了8个,那么会调用treeifyBin函数,将链表转换为红黑树。那么即便hashcode彻底相同,因为红黑树的特色,查找某个特定元素,也只须要O(log n)的开销。也就是说put/get的操做的时间复杂度最差只有O(log n)。
ConcurrentHashMap:
在多线程环境下,使用HashMap进行put操做时存在丢失数据的状况,为了不这种bug的隐患,强烈建议使用ConcurrentHashMap代替HashMap。
1.7版本,使用Segment + HashEntry方式进行实现。
1.7 ConcurrentHashMap结构图
1.8版本,1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,结构以下:
1.8 ConcurrentHashMap结构图面试

更详细的内容请参考《Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析》redis

2、 常见的线程池及应用场景算法

  • newCacheThreadPool 无大小,适合时间段速度快的
  • newFixedThreadPool 有大小,负载比较重的
  • newSingleThreadExecutor 单个有序
  • newScheduleThreadPool 周期性的任务

3、 阻塞队列spring

  • arrayblockingqueue:有界,不公平的阻塞(能够经过构造器设置成公平的)
  • linkedblockingqueue:有界,先进先出
  • priorityblockingqueue:按照特定字段排序
  • delayqueue:延迟(缓存是否过时,定时调度)
  • synchronousqueue:不存储元素,充当传球手
  • linkedtransferqueue:×××,若是有消费者等待,就直接传给消费者,不然放入队列
  • linkedblockingdeque:双向阻塞sql

    4、 线程池的处理流程
    在这里插入图片描述小程序

    5、Lock与synchronized 的区别
    synchronized:
    在资源竞争不是很激烈的状况下,偶尔会有同步的情形下,synchronized是很合适的。缘由在于,编译程序一般会尽量的进行优化synchronize,另外可读性很是好,无论用没用过5.0多线程包的程序员都能理解。
    ReentrantLock:
    ReentrantLock提供了多样化的同步,好比有时间限制的同步,能够被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。可是当同步很是激烈的时候,synchronized的性能一会儿能降低好几十倍。而ReentrantLock确还能维持常态。

    JVM

    1、 JVM内存分哪几个区,每一个区的做用是什么

Java虚拟机主要分为如下一个区:

  1. 方法区:

    • 有时候也成为永久代,在该区内不多发生垃圾回收,可是并不表明不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载
    • 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。
    • 该区域是被线程共享的。
    • 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具备动态性,也就是说常量并不必定是编译时肯定,运行时生成的常量也会存在这个常量池中。
  2. 虚拟机栈:

    • 虚拟机栈也就是咱们日常所称的栈内存,它为java方法服务,每一个方法在执行的时候都会建立一个栈帧,用于存储局部变量表、操做数栈、动态连接和方法出口等信息。
    • 虚拟机栈是线程私有的,它的生命周期与线程相同。
    • 局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个对象引用有多是指向对象起始地址的一个指针,也有多是表明对象的句柄或者与对象相关联的位置。局部变量所需的内存空间在编译器间肯定
    • 操做数栈的做用主要用来存储运算结果以及运算的操做数,它不一样于局部变量表经过索引来访问,而是压栈和出栈的方式
    • 每一个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程当中的动态链接.动态连接就是将常量池中的符号引用在运行期转化为直接引用。
  3. 本地方法栈

    • 本地方法栈和虚拟机栈相似,只不过本地方法栈为Native方法服务。
    • java堆是全部线程所共享的一块内存,在虚拟机启动时建立,几乎全部的对象实例都在这里建立,所以该区域常常发生垃圾回收操做。
  4. 程序计数器
    • 内存空间小,字节码解释器工做时经过改变这个计数值能够选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理和线程恢复等功能都须要依赖这个计数器完成。该内存区域是惟一一个java虚拟机规范没有规定任何OOM状况的区域。

2、java中垃圾收集的方法有哪些?

  1. 标记-清除:
    这是垃圾收集算法中最基础的,根据名字就能够知道,它的思想就是标记哪些要被回收的对象,而后统一回收。这种方法很简单,可是会有两个主要问题:1.效率不高,标记和清除的效率都很低;2.会产生大量不连续的内存碎片,致使之后程序在分配较大的对象时,因为没有充足的连续内存而提早触发一次GC动做。
  2. 复制算法:
    为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,而后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,而后一次性清楚完第一块内存,再将第二块上的对象复制到第一块。可是这种方式,内存的代价过高,每次基本上都要浪费通常的内存。
    因而将该算法进行了改进,内存区域再也不是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那分内存交Eden区,其他是两块较小的内存区叫Survior区。每次都会优先使用Eden区,若Eden区满,就将对象复制到第二块内存区上,而后清除Eden区,若是此时存活的对象太多,以致于Survivor不够时,会将这些对象经过分配担保机制复制到老年代中。(java堆又分为新生代和老年代)
  3. 标记-整理
    该算法主要是为了解决标记-清除,产生大量内存碎片的问题;当对象存活率较高时,也解决了复制算法的效率问题。它的不一样之处就是在清除对象的时候现将可回收对象移动到一端,而后清除掉端边界之外的对象,这样就不会产生内存碎片了。
  4. 分代收集
    如今的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,因为对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,因此可使用标记-整理 或者 标记-清除。

3、java内存分配与回收策率以及Minor GC和Major GC

  1. 对象优先在堆的Eden区分配。
  2. 大对象直接进入老年代.
  3. 长期存活的对象将直接进入老年代.
  4. 当Eden区没有足够的空间进行分配时,虚拟机会执行一次Minor GC.Minor Gc一般发生在新生代的Eden区,在这个区的对象生存期短,每每发生Gc的频率较高,回收速度比较快;Full Gc/Major GC 发生在老年代,通常状况下,触发老年代GC的时候不会触发Minor GC,可是经过配置,能够在Full GC以前进行一次Minor GC这样能够加快老年代的回收速度。
相关文章
相关标签/搜索