随便分享点不那么常规的面试题(一)

1. 为何HashMap容许key和value为空,而Hashtable和ConcurrentHashMap不容许key和value为空?

本题主要考察是否熟悉各类map的应用场景,若是只说出key/value为空无心义是不够的,要能考虑到更根本的缘由java

直接缘由mysql

  • HashMap将null的hash值设置为0,因此容许key和value为空
  • Hashtable会检测当value为空时抛出NPE,同时在计算hash值时直接调用了key的hashcode方法,若是key为空会抛出NPE
  • ConcurrentHashMap会检测当key或value为空时抛出NPE

根本缘由linux

  • HashMap是线程不安全的,因此在设计时能够只考虑单线程执行场景。使用get(key)方法前想判断一个key-value键值对是否存在于Map中时,能够调用containsKey方法,该方法是根据是否存在索引节点来判断的,因此value为空也无所谓,又由于是单线程的,因此containsKey方法和get方法不会出现线程安全问题
  • Hashtable和ConcurrentHashMap是线程安全的,在设计时,默认使用场景是多线程下。若是容许value为空,则用户调用get(key)方法后返回null不能判断是否存在对应的key-null键值对,须要额外使用containsKey来进行判断,在多线程场景下须要用户手动进行加锁。为了减小用户使用的负担,以及避免因为误使用带来严重的后果,同时也考虑到key/value为空也没有太大的意义,因此就禁止key/value为空

2. 讲一下linux的awk命令

本题主要考察对linux的使用深度,属于加分项,没有用过awk至少要让面试官知道你用过grep,若是都没有用过的话,面试官会怀疑你是否有linux的使用经验程序员

awk是一个文本分析工具,将文件逐行读入,而后默认按空格进行切片,对切开的部分进行单独分析面试

格式是awk [options] '{command}' filename,如awk '{print $1}' out.txt,其中$1表明第1列,awk会默认按照分隔符来切分每一行算法

分隔符也能够经过在awk后使用-F来指定,如awk -F ':' '{ print $1 }' out.txtspring

3. 数据库水平分表以后怎么查询

本题主要考察你是否有考虑过度表以后的事情,而不是仅仅背了几道面试题,说出聚合操做后这道题基本就经过了sql

若是查询单条记录,能够根据查询条件和分表规则找到对应的表,而后进行查询并返回结果数据库

若是查询多条记录,则分开查询,将全部查询结果作聚合,将聚合后的结果返回编程

4. mysql中select *** from *** limit offset, rows会有什么问题,怎么解决

本题主要考察数据库查询优化的知识,至少要能给出两种解决方案,并说出其各自的优缺点

存在问题:当offset很大时,查询效率会下降,由于mysql并不能直接定位到offset处进行查询,而是查询前offset+rows行,而后只取后rows条数据,将前面的数据舍弃,因此效率会很低

解决方案:

  1. limit offset, rows删去,使用where 主键 > offset limit rows代替,可是使用前提是没有其余where条件对数据进行过滤
  2. 在子查询中查出索引,外层查询根据索引来定位数据,前提也是不能有其余where条件对数据进行过滤
  3. 若是偏移量超过记录数的一半,则反序查询,能够保证偏移量不会超过记录数的一半
  4. 限制limit的偏移量,不容许超过某个值
  5. 用额外的表记录数据和页数的关系,可是只适用于每页条数固定的状况

5. Java中final的实现原理是什么

本题主要考察一些语言层面上的知识,若是知道泛型是语法糖的话,这个问题也能很容易回答出来

Java中final和private、泛型同样,都是一种编程约束,编译器会检查final修饰的变量是否被从新赋值等,在编译后与普通变量没有区别

8. Java是编译型语言仍是解释型语言,JVM是编译器吗,什么是JIT?

本题主要考察对Java语言的熟悉程度,能所有说正确固然最好,至少也得要能说出JVM是解释器,Java是解释型语言

Java既是解释型语言也是编译型语言。Java代码须要通过javac编译器编译成class文件,交给JVM进行解释执行,为了加快执行效率,同时Java引入JIT编译技术(Just-in-Time Compile,即时编译技术),将部分热点代码编译成机器码优化执行

7. 逃逸分析了解吗

本题主要考察对Java优化技术的了解程度,属于加分项,回答好的话能给面试官留下深入印象

Java引入JIT技术后,会将热点代码编译成本地机器相关的机器码,编译时会进行相应的优化,逃逸分析就是JIT优化的基础

一个对象在方法中被定义后,若是被外部方法所引用,好比经过参数传递给其余方法,就叫作(方法)逃逸。一样地,若是一个对象能被其余线程访问到,也叫作逃逸。逃逸分析就是来分析对象是否发生了逃逸,经过逃逸分析,Java编译器能够分析出一个对象的使用范围

当JIT使用逃逸分析时,能够执行相应的优化策略:

  • 同步省略/锁消除:若是同步块只能被一个线程所访问,则加锁是没有必要的,在优化时,同步块上的锁会被省略
  • 对象分离/标量替换:若是一个对象不会发生逃逸,则将对象属性的引用替换为标量,从而避免建立对象
  • 栈上分配:将不会发生逃逸的对象直接在栈上分配内存,而不是堆中,这样能够省略垃圾回收的操做(实际上仍是使用标量替换来完成的,没有真正实现栈上分配)

逃逸分析这项技术至今仍不成熟,没法保证逃逸分析所提升的运行效率能超过它的性能损耗,可是逃逸分析依然是JIT编译器优化技术中一个重要手段

8. TCP粘包问题了解过吗,怎么解决

本题主要考察对TCP协议的了解程度,能回答出来TCP这块基本就不会再问了。通常TCP部分的问题深度由浅至深分别是:TCP/UDP区别 => 三次握手与四次挥手 => 流量控制和拥塞控制 => TCP优化技术与常见问题,必需要作好准备

粘包问题有两种常见状况:

  1. TCP协议为了将包更有效地发送到对象,因此使用Nagle优化算法,将多个小数据包合并成大数据块进行封包,由于TCP传输的数据是没有边界的,因此接收方会收到一个粘成一团的包
  2. 接收方没有即时接收消息,致使接收方的TCP缓冲区存放了几段数据,接收方的应用层就会收到不完整的数据

解决方案有两种,一种是只发送固定长度的包,另外一种是在发送消息时带上消息的长度,同时使用特殊标记来标记消息边界

9. 为何主键索引最好是自增的

本题考察的是你的思考能力,若是这题答得很差会给面试官留下只会背题的印象,此题不难,即便不知道答案只要给出本身的想法便可,重点是联系到索引的数据结构上

由于innodb索引采用b+树的结构存储,避免插入非规律主键的数据时,致使页分裂

10. 接口和抽象方法哪个调用速度快,为何

本题考察对JVM知识的掌握程度,虽然本题应用意义不大,可是能很好地考察出被面试者对JVM底层原理的了解状况

抽象方法调用速度快,由于抽象类属于实现类的父类,抽象方法的实现属于方法覆写,能够直接根据偏移量来定位方法,而接口则只能经过遍从来找

11. 看下面这段代码,执行结果是什么,为何

String a1 = new String("a") + new String("a");  // 1
        a1.intern();                                    // 2
        String a2 = "aa";                               // 3
        
        System.out.println(a1 == a2);

        // -------------------------------------
        
        String b1 = new String("b") + new String("b");  // 4 
        String b2 = "bb";                               // 5
        b1.intern();                                    // 6
        
        System.out.println(b1 == b2);
复制代码

本题考察的是面试者对String的理解深度,此题的要点就是能答出intern方法的实现原理,可以彻底答对很是难,基本能打趴绝大多数面试者,可以回答出来讲明对JVM的常量池很熟悉,绝对是一个加分项,不过遗憾的是基本没有面试官会问这么深

在jdk1.7以前,返回false false[1],在jdk1.7及以后的jdk版本中,返回true false

为何在jdk1.7以前返回false false

  • 由于在jdk1.6中,字符串常量池在“永久代”中,调用String#intern方法时,若是常量池中已经存在该字符串对象,会直接返回常量池中的对象引用;不然会在常量池中建立一个对象,并返回常量池中对象的引用
  • 回到代码中,代码1在堆中建立了“aa”字符串对象,池中没有“aa”字符串对象;代码2发现常量池中没有“aa”对象,则在池中建立“aa”对象;代码3发现池中存在“aa”对象,直接返回常量池中对象的引用;此时,a1为堆中字符串对象引用,a2为常量池中字符串对象引用,显然指向的不是同一个对象
  • 代码4在堆中建立了“bb”字符串对象,池中没有“bb”字符串对象;代码5发现池中没有“bb”对象,则在池中建立“bb”对象;代码6发现常量池中存在“bb”对象,不执行操做;此时,b1为堆中字符串对象引用,b2为常量池中字符串对象引用,显然指向的不是同一个对象

为何在jdk1.7及以后返回true false

  • 在jdk1.7中,常量池被存放在Java堆中,jdk1.8中,常量池被放在元空间中,与堆独立(其实主要跟intern方法的实现改变有关,和常量池在哪没有太大关系,因此别被误导了,这一点只是作个知识扩展)
  • 当调用String#intern方法时,若是常量池中已经有该对象,则返回常量池中对象的引用;不然,将Java堆中的对象引用添加到常量池中,并返回该引用;若是Java堆中也不存在,则在常量池中建立该字符串对象,并返回其引用
  • 回到代码中,代码1在堆中建立了“aa”字符串对象,池中没有“aa”字符串对象;代码2发现常量池中不存在“aa”对象,则检查Java堆,发现存在“aa”对象,则将堆中该对象的引用添加到常量池中;代码3发现常量池中存在“aa”对象的引用,则返回该引用;此时,a1为堆中对象的引用,a2也为堆中该对象的引用,指向的是同一对象
  • 代码4/5/6与jdk1.6中的原理彻底一致,就再也不赘述了

12. ConcurrentHashMap的扩容是如何实现的

本题考察的是对ConcurrentHashMap源码熟悉程度,答题要点是分区间处理和单节点加锁。若是是考察HashMap的扩容,则答题要点是先建立新数组,再拷贝原数据

  1. 根据处理器个数,计算出每一个处理器要处理的区间个数
  2. 建立一个新数组
  3. 计算每一个线程须要处理的区间段大小
  4. 遍历每一个索引位置,遍历到时对索引节点单个进行加锁
    1. 将索引位置下全部节点分为两个链表,一个是扩容后位置不变的,一个是扩容后位置改变的
    2. 处理完成后将这两个链表一次性放置到原数组对应位置上(使用原子赋值操做,不会影响线程安全)

13. Service Mesh/Serverless是什么

本题主要考察面试者的技术视野,是否仅仅关注本身眼前的技术。这种就属于概念性的问题,能说多少说多少,没有标准答案,能体现出本身有了解过大体的概念便可。这两个问题自己没有太大关联,可是由于都属于这一类问题,不想再单独列出来,就直接放在一块儿了

  • Service Mesh,指服务网格,属于基础设施层,功能在于处理服务间通讯,是系统通讯的中间层,负责实现请求的可靠传递。Service Mesh通常由一系列轻量级的网络代理组成,和应用程序部署在一块儿,可是对应用程序透明(不可见)。能够解耦应用程序的重试、超时、监控、追踪,以及服务发现,让应用服务专一于业务逻辑
  • Serverless,指无服务架构,可让开发者不用考虑服务器的问题,将计算资源做为服务,而不是服务器。Serverless是一种构建和管理基于微服务架构的完整流程,容许开发者将应用以服务的级别来部署,而不是服务器级别。能够不用去关心服务器运行状态,不用考虑运营维护问题

14. 静态方法和单例模式有什么区别,咱们为何推荐使用单例模式

本题主要考察面试者是否对本身使用的工具备过思考,可以知道“为何用”,一个工程师至少要清楚本身使用工具的场景,而不能是稀里糊涂的“有就用”

  1. 单例模式契合面向对象的思想
  2. 单例类中的方法能够继承覆写
  3. 单例类能够被延迟实例化
  4. 单例类能够被用于多态,不须要关注全局的状态

15. 伪共享了解吗

本题考察的是面试者对线程安全(特指volatile部分)的掌握程度,若是认真看过JUC包下的源码,就必定会了解到伪共享的概念。不过本题属于加分项,即使不知道也没有太大影响

伪共享指的是两个volatile类型的数据在同一个缓存行中,因为volatile每次都会刷新缓存行,因此致使缓存行没有彻底发挥出做用,导致性能浪费

能够经过在对象或字段的先后加padding,也可使用@sun.misc.Contended注解(其原理是在对象或字段先后加上128位的padding)

16. SpringBoot是怎么启动的

本题主要考察对Springboot的了解程度,答题要点是设置监听器和加载上下文,若是这题没答上来或没答好面试官可能会问IoC和AOP原理相关的问题,因此至少有一个要很是熟悉

  • @SpringbootApplication复合了一些注解:
    • @SpringBootConfiguration:声明该类为配置类
    • @EnableAutoConfiguration:启用自动配置,原理是使用AutoConfigurationImportSelector类,将全部配置类加载到容器中,并扫描配置文件,将配置项经过反射实例化为配置类,汇总以后加载到容器中
    • @ComponentScan:自动扫描包下的bean
  • Springboot在启动时,经过SpringApplication的run方法启动容器。在run方法中,分为两步:
    1. 先构建SpringApplication对象,其中会设置成员变量和监听器,最终推断main方法所在的入口类
    1. 而后调用SpringApplication具体实例对象的run方法,会遍历并启动监听器,封装args参数为对象,初始化并加载应用上下文

17. 适配器模式的应用场景是什么,举几个具体应用的例子

本题主要考察对适配器这种设计模式的掌握程度,如今不少人为了突击面试,设计模式只看过单例和工厂两种,若是问到其余设计模式答不上来,会在面试官的心中大打折扣

应用场景:

  • 须要使用某个类,可是接口不符合须要
  • 须要将一些没有公共接口/父类的类关联起来,使其能够一块儿工做
  • 须要为一些类提供统一的输出接口

应用实例:

  • spring-aop:将不一样的通知类型适配到统一的适配器接口AdvisorAdapter中,能够经过具体的适配器类来获取对应通知的拦截器
  • spring-mvc:使用HandlerAdapter来适配具体的Controller,实现了DispatcherServlet和Controller之间的统一接口对接

18. CountDownLatch的await()方法有什么风险

本题主要考察面试者是否真正用过CountDownLatch,是否在使用时有考虑过风险。与此题相似的问题还有:ThreadLocal使用时须要注意什么,SimpleDateFormat在多线程下使用有什么风险等

若是执行countDown的线程发生异常,则await()方法会被阻塞。因此要设置超时时间,因此要使用await(timeout, unit)方法

19. 为何有些公司弃用zookeeper

本题主要考察对zookeeper的掌握程度,能说出一种工具的优势很容易,有时候编也能编个差很少,可是想说出来缺点就须要对它有至关的了解才行。若是是校招的话通常不会问这么深,回答不上来也不用太紧张,可是必定要勇于说出来本身的看法,即便是错的

客户端:

  • 服务端集群的地址列表是写死在客户端的,不支持动态变动
  • 不支持同机房优先策略
  • 没有针对服务端集群彻底不可用的容灾策略

服务端:

  • 写能力不足,不支持水平扩展
  • 监测手段单一,只有TCP的活性监测

20. Java中基本数据类型是对象吗

本题考察的是对Java语言的理解程度,这个问题几乎没见过有面试官问过,问题自己的价值也不是很大,若是答不上来也没有太大关系,不过确实能反应出面试者对语言的认识程度

JVM会把全部的基本数据类型看成对象处理,JVM有9种设定好的Class对象来对应基本数据类型void关键字,这些对象都是JVM建立的

除了基本类型以外,枚举也是一种类,注解属于一种特殊的接口,数组也是Object的子类,可是对程序员是透明的


  1. 勘误:使用openjdk6测试发现输出依然是true false,此题有待进一步研究 ↩︎

相关文章
相关标签/搜索