Java 面试常问问题及答案(非常详细)
一:java 基础
1.简述 string 对象,StringBuffer、StringBuilder 区分
string 是 final 的,内部用一个 final 类型的 char 数组存储数据,它的拼接效率比较低,实际上是通过建立一个 StringBuffer,让后台调用 append(),最后再将 StringBuffer toSting(),每次操作 Sting 都会重新建立新的对象来保存新的值.这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的。
StringBuffer 也是 final,线程安全的,中采用一个 char 数组来保存需要 append 的字符串,char 数组有一个初始大小,当 append 的字符串长度超过当前 char 数组容量时,则对 char 数组进行动态扩展,也即重新申请一段更大的内存空间,然后将当前 char 数组拷贝到新的位置,因为重新分配内存并拷贝的开销比较大,所以每次重新申请内存空间都是采用申请大于当前需要的内存空间的方式,这里是 2 倍。
StringBuilder,线程不安全。
2.多态的原理
多态就是:允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。
原理是 java 的后期绑定。
3.简要描述面向对象编程的思想
抽象:通过特定的实例抽取出共同的特征以后形成的概念的过程,它强调主要特征和忽略次要特征。
封装:把对象的属性和方法结合成一个独立的整体,隐藏实现细节,并提供对外访问的接口。
继承:从已知的一个类中派生出新的一个类,叫子类。子类实现了父类所有非私有化属性和方法,
并能根据自己的实际需求扩展出新的行为。
多态:多个不同的对象对同一消息作出响应,同一消息根据不同的对象而采用各种不同的行为方法。
4.反射的原理
java 虚拟机运行时内存有个叫方法区,主要作用是存储被装载的类的类型信息。每装载一个类的时候,java 就会创建一个该类的 Class 对象实例。我们就可以通过这个实例,来访问这个类的信息。
5.代理的作用和实现
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
java 的静态代理和动态代理(略)
6.hashcode 和 equals 的用法
Java 对于 eqauls 方法和 hashCode 方法是这样规定的:
如果两个对象相同,那么它们的 hashCode 值一定要相同;
如果两个对象的 hashCode 相同,它们并不一定相同(上面说的对象相同指的是用 eqauls 方法比较。)
一般在覆盖 equals()方法的同时也要覆盖 hashCode()方法,否则,就会违反 Object.hashCode 的通用约定,从而导致该类无法与所有基于散列值(hash)集合类(HashMap、HashSet 和 Hashtable)结合在一起正常运行。
7.set,map,list 的区别(尽量详细)
map:
hashmap:链地址法,大概思路:通过取 key 的 hashCode 值、高位运算、取模运算计算位置,插入位置是通过 hascode 和 eques 方法判断 key 是否一致
①.判断键值对数组 table[i]是否为空或为 null,否则执行 resize()进行扩容;
②.根据键值 key 计算 hash 值得到插入的数组索引 i,如果 table[i]==null,直接新建节点添加,转向⑥,如果 table[i]不为空,转向③;
③.判断 table[i]的首个元素是否和 key 一样,如果相同直接覆盖 value,否则转向④,这里的相同指的是 hashCode 以及 equals;
④.判断 table[i] 是否为 treeNode,即 table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤;
⑤.遍历 table[i],判断链表长度是否大于 8,大于 8 的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现 key 已经存在直接覆盖 value 即可;
⑥.插入成功后,判断实际存在的键值对数量 size 是否超多了最大容量 threshold,如果超过,进行扩容。
treemap:TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。如果使用排序的映射,建议使用 TreeMap。在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。
linkedHashMap:保存了记录的插入顺序,在用 Iterator 遍历 LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。
HashTable:因为内部是采用 synchronized 来保证线程安全的
CocurrentHashMap:利用锁分段技术增加了锁的数目,从而使争夺同一把锁的线程的数目得到控制。
set:
HashSet:内部 new 了一个 hashMap,添加时 key 放数据,value 放一个内部定义的 final 的 Object 对象
LinkedHashSet:内部 new 了一个 linkHashMap,添加时 key 放数据,value 放一个内部定义的 final 的 Object 对象,遍历时有序
TreeSet:内部 new 了一个 TreeMap,添加时 key 放数据,value 放一个内部定义的 final 的 Object 对象.
list:
arraylist 和 linkedList(略)
copywriteList:CopyOnWriteArrayList 适合使用在读操作远远大于写操作的场景