- 1、String类能被继承么?
不能,因为String类被final修饰符修饰,final修饰的类不能被继承; - 2、String,Stringbuffer,StringBuilder的区别?
String 常量,位于字符串常量池中,不可变的对象
Stringbuffer 变量,线程安全,效率比较低
StringBuilder变量,线程不安全,效率比较高 - 3、ArrayList和LinkedList有什么区别
两者都是list集合的子集
arrayList是基于动态数组,而LinkedList是基于链表操作;
arrayList在查询效率方面更高,直接找到索引index返回,而LinkedList则需要进行for遍历查找
arrayList 一般认为插入和删除效率比较高一些,实际上插入位置位于容量1/10以下的时候,才会发生;LinkedList效率比较高的原因是直接for遍历到元素,插入或者删除,而arrayList则需要移动指针,将指针后的元素都向后推移 - 4、类的实例化顺序
父类的静态变量
父类的静态初始化代码块
子类的静态变量
子类的静态初始化代码块
子类main方法
父类的变量
父类的初始化代码块
父类的构造函数
子类的变量
子类的初始化代码块
子类类的构造函数
- 5、hashmap
基于Map接口实现,可以为null或者空值,非同步,不保证有序,也不保证顺序随时间而不发生变化,存储Entry(hask,key,value,next)对象
put实现原理:
1、对key的hashcode进行hash,再计算索引index
2、如果索引没有碰撞,那么直接放进bucket中
3、如果有冲突,则以链表的形式挂在buckets后,如果链表过长,则将链表转换为红黑树(jdk8之后默认为8)
4、如果节点已经存在,则把原来的值替换
5、如果bucket满了,则需要重新resize(factor默认是0.75)
get实现原理:
1、bucket里的第一个节点,直接命中
2、如果有冲突,则通过key.equals(k)查找对应的entry
3、如果是树,则通过key.equals(k)查找O(logn)
4、如果是链表,则通过key.equals(k)查找O(n)
key的hashcode进行hash(hashcode的高16位和低16位进行异或),
initialCapacity : 初始化容量16
table : Entry<K,V>[] table 是用来存储数据的数组
Entry<K,V> 是HashMap的一个内部类,链表结构
- 6 ConcurrentHashMap
ConcurrentHashMap 包括两个内部类,hashEntry和segment,hashEntry存储键值对,segment充当锁的作用。
并发性高的原因
1、是由自身特点决定的。当插入一个元素的时候,对hashcode进行hash,计算出索引,得到segment中桶的位置由于hashEntry链的final特性,只能在链头插入元素,不影响遍历;锁住的当前的segment,其他segment读写并不受影响
2、hashEntry的value是volatile变量,不同线程间可以正确的获得值
jdk
1.8 其中抛弃了原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。
hashcode 定位node,如果为空,cas尝试写入,不成功,自旋保证成功
如果都不满足,就synchronized 写入数据
- 7 抽象类和接口区别
- 抽象类的修饰符可以public protected default,接口的修饰符只能是public
- 抽象类强调的是继承,只声明不实现,是单继承,接口强调的实现,是抽象方法的集合,可以多实现。
- 抽象类可以有构造器,接口没有
- 抽象类中可以包含非抽象方法,也就是默认实现,而接口的子类实现必须实现所有的方法
类单继承,接口可以多继承,一个类可以实现多个接口
- 8 jvm
共享区域:堆(年轻代(eden s0 s1)和老年代)和方法区
方法区:存放已加载类信息、方法信息、常量池
- 9 栈内存溢出
递归太深、循环没有出口、静态变量过多、大量字符串拼接、数据未分页
内存溢出
Dump机制会帮助我们,可以通过加上VM参数-XX:+HeapDumpOnOutOfMemoryError让虚拟机在出现内存溢出异常时生成dump文件,然后通过外部工具(作者使用的是VisualVM)来具体分析异常的原因