Questions 01 (Java SE问题总结)
Questions 01
一、Java SE问题总结
1. 接口和抽象类的区别?
-
定义抽象类的关键字是abstract class,而定义接口的关键字是interface。
-
继承抽象类的关键字是extends,而实现接口的关键字是implements。
-
继承抽象类支持单继承,而实现接口支持多实现。
-
抽象类中可以有构造方法,而接口中不可以有构造方法。
-
抽象类中可以有成员变量,而接口中只可以有常量。
-
抽象类中可以有成员方法,而接口中只可以有抽象方法。
-
抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写(Java8以前的版本)。
从Java8开始增加新特性,接口中允许出现非抽象方法和静态方法,但非抽象方法需要使用default关键字修饰。
从Java9开始增加新特性,接口中允许出现私有方法。
-
抽象类中抽象方法不可以省略public abstract, 接口中的抽象方法可以省略public abstract。
2. 反射是如何使用的?反射为很么慢?
-
反射的使用方法:
通过调用某些方法获取指定类型的Class对象,利用Class类中的方法可以获取这个类型的Constructor类、Field类、Method类对象/数组对象以及一些其他信息(获取所在的包信息、获取继承的父类信息、获取实现的所有接口、获取注解信息、获取泛型信息等)。
-
反射慢(性能开销)的原因:
-
getMethod等查找方法会返回对象的拷贝,占用堆空间,会对GC产生压力。
优化方式:使用工具类/中间件将getMethod方法的返回值缓存到内存的哈希表中,可以保证下次直接从缓存中取出而不是再次调用getMethod方法。
-
Method.invoke中传入的参数必须是对应类型的Object数组
invoke(Object obj, Object... args),会导致原始类型的拆箱和装箱(若构造方法的参数列表中有基本类型)。优化方式:配置
-Djava.lang.Integer.IntegerCache.high=128来扩大Integer缓存范围,减少包装类对象的频繁创建。 -
内联瓶颈:JVM对同一个调用点的profile记录是有限制的,导致后续方法无法被内联。
优化方式:增加
-XX:TyperProfileWidth(默认值只有2)大小来提高可以被内联的方法数目。
-
3. 什么是面向对象?面向对象和面向过程的区别?
- 面向对象是一种编程的范式和代码风格,它以类和对象作为组织代码的基本单元,使用封装、继承和多态的特性进行代码的设计和实现。实际开发时从对象入手,把需求相关的对象抽取出来,借助对象间的相互配合(如方法调用、共享变量)完成需求。
- 面向对象和面向过程的区别:
- 面向对象是以类和对象作为组织代码的基本单元,而面向过程是以过程(或方法)作为组织代码的基本单元。
- 面向过程程序处理流程是单一的一条主线,而面向对象程序的处理流程是错综复杂的网状结构。
4. HashMap的数据结构?put的过程?
-
HashMap的数据结构:哈希表

JDK8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间
将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树

-
HashMap中put方法的过程:
(JDK8之前)
-
使用元素的key调用hashCode方法获取对应的哈希码值,再由哈希算法计算在数组中的索引位置
-
若该位置没有元素,则将该键值对放入即可
-
若该位置有元素,则使用key与已有的元素依次比较哈希值,若哈希值不相同,则将该元素直接放入
- 若key与已有元素的哈希值相同,则使用key调用equals方法与已有的元素依次比较
- 若相等则将对应的value修改,否则将键值对直接放入
- 若key与已有元素的哈希值相同,则使用key调用equals方法与已有的元素依次比较
-
(JDK8之后)
- HashMap首先判断table是否为null或长度为0,是的话则进行扩容,然后根据key计算hashCode(),得到存储key-value对的位置索引
- 判断索引处是否为空,若为空,则直接插入到对应的数组中
- 否则,判断key是否已存在,如果已存在则直接覆盖
- 否则,判断里面是链表还是红黑树,若是红黑树,则插入到红黑树
- 若是链表,则遍历链表插入,JDK8是将元素插入到链表尾部
- 插入后,判断链表长度,若长度大于等于8,则将链表转为红黑树
- 若是链表,则遍历链表插入,JDK8是将元素插入到链表尾部
- 否则,判断里面是链表还是红黑树,若是红黑树,则插入到红黑树
- 否则,判断key是否已存在,如果已存在则直接覆盖
- 最后判断数组的size()是否大于等于阈值,是的话则进行扩容
- 判断索引处是否为空,若为空,则直接插入到对应的数组中
-

浙公网安备 33010602011771号