1. 为什么对象要重写hashcode和equals?
如果对象没有重写hashcode,会调用Object类默认的hashcode,即对象所在的内存地址,这会引起一个问题,在hashmap中的key需要先比较hashcode的,假设hashmap中存在一个{student(id=1):"你好"}的键值对,那想要再获取这个键值对的值,就无法实现了,新建的对象student即使id为1,也无法通过map.get(student);的方式获取。也就是说,没有重写hashcode,就只能put而不能get了,除非key对象的句柄可以拿到。
两个hashcode值相等,很可能它们是两个不同对象,要比较两个对象相等,必须重写equals。否则默认比较两个对象是否是一个对象。
2. try-catch放在循环内还是循环外
这取决于业务场景,若某业务场景要求计算出错后仍要将计算剩余数据时,try-catch放在循环内;若某业务场景要求一旦出错马上停止计算,try-catch放在循环外。
3. if和switch性能比较
条件分支越多,switch性能优势越明显,5个条件分支时,switch性能约为if的2倍多,15个条件分支时,switch性能约为if的4倍多。
使用switch时,若case连续(1,2,3,...),则会使用tableswitch,类似访问数组下标,只需要O(1)的时间,若case不连续(1,12,15,...),则会使用looksupswitch,采用分支比较或者使用二分法进行查询,需要O(logn)的时间。
4. hashmap的put方法执行过程
(1)获取key的hashcode值,并据此计算出数组下标;
(2)若当前数组为null,调用resize方法对数组进行初始化;
(3)调用equals比较key值,若有相同,则覆盖原来的value,否则挂在到链表或红黑树末尾;
(4)若链表长度超过8,则升级为红黑树;若红黑树个数小于6,则降级为链表;
(5)若当前hashmap的entry个数超过threshold,则调用resize进行扩容。
5. hashmap数组为2的次幂的两个好处
(1)(table.length-1)&hash便于快速寻址,即寻找数组下标;
(2)扩容时,有一半的元素在原位置,有一半的元素向后移动length格。
6. hashmap怎么存储null值?
放置在桶数组中下标为0的桶中
7. String类为什么设计为final类型?
(1)出于安全性的考虑,如数据校验后,突然改变,会影响系统的安全性;
(2)高性能,String不可变就有唯一的hash值;
(3)节约内存,String字符串可以复用。
8. String高性能策略
(1)善用intern方法,可以复用已有的字符串;
(2)避免使用str+="s"拼加字符串,而是使用线程不安全的StringBuilder或线程安全的StringBuffer的append方法;
(3)慎用split方法,因为底层用的是正则,这会导致性能不稳定,而是使用String.indexOf等策略进行切割。
9. 哪些方法不能被重写?
private、final、static之一修饰的方法
10.多态的实现步骤
(1)继承;(2)重写;(3)向上转型,即父类引用指向子类对象。
运行时决定执行哪个子类对象的方法。
11. 接口和抽象类的区别
(1)接口使用interface关键字,子类通过implements来实现接口,并且可以实现多个接口;抽象类使用abstract关键字,子类通过extends来继承抽象类,只能继承一个抽象类。
(2)抽象类可以拥有属性变量,而接口只能有static final修饰的变量。
(3)抽象类的方法可以用public/protected/private等修饰,接口只能是public,但抽象类的抽象方法只能是public。