文章目录
- 1、类和对象的区别?
- 2、讲讲 static 和 final 关键字?
- 3、Object 类下有哪些方法?
- 4、== 和 equals 方法的区别?
- 5、可变长度参数?
- 6、字符串“123”转为整型 123 的 API 是什么?反过来的 API 又是什么?
- 7、接口和抽象类的区别?什么时候用接口,什么时候用抽象类?接口之间可以继承吗?
- 8、BIO、NIO、AIO 区别有哪些?
- 9、重载和重写的区别?重写有没有什么限制?
- 14、HashMap 的底层结构?为什么线程不安全?1.7 之前的头插入法有什么问题?1.8 之后做了哪些优化或改变?为什么链表长度大于 8 时转为红黑树?红黑树节点添加过程?负载因子为什么是 0.75?扩容步骤?
- 15、HashMap 在使用时需要注意什么?说出四点
- 16、hash 方式和 hash 冲突的解决方式?
- 10、HashMap 和 HashTable 的区别?
- HashMap 和 HashSet 的区别?HashSet 是如何检查重复的?
- 11、HashMap 和 TreeMap 的区别?
- 12、Queue 和 Deque 的区别?
- 13、为什么建议使用 ArrayDeque 而不是 LinkedList?
- 13、ArrayList 和 LinkedList 的区别?两者哪个比较占内存?add 和 get 的时间复杂度?扩容原理?
- 17、ConcurrentHashMap 又是怎样实现线程安全的?
- 18、jdk8 的新特性?
- 19、说说匿名函数?Lambda 表达式的优缺点?
- 20、UML 类图的理解?画一个?
- 21、静态代理和动态代理的区别?动态代理有几种实现方式?(JDK提供的、CGLIB)
- 22、序列化和反序列化?
- 23、Java 高效拷贝数组?
1、类和对象的区别?
- 对象就是真实世界中的一个实体。
- 类就是某些具有共同特征的实体集合,是对所具有相同特征的实体对象的抽象。
- 在 Java 中,创建一个 class 就是创建了一个类,然后使用 new 关键字可以创建一个该类的实体。
2、讲讲 static 和 final 关键字?
- Java中的final和static关键字详解
- java中的Static、final、Static final各种用法
- 《Java核心技术卷1》中 P158 第5.1.7节说到,“将一个类声明为final,只有其中的方法自动称为final,而不包括域”。
- 而文章final修饰的类,其属性和方法默认是被final修饰的吗?中使用反射来获取 final 类中的方法和属性的修饰符,表明方法不是 final 修饰的?
- 我的理解:final 修饰的类,其不允许继承,那么其方法自然不可能再被子类重写,即方法是final的。但是final修饰的类,其属性肯定是可变的,因此“不包括域”。
3、Object 类下有哪些方法?
4、== 和 equals 方法的区别?
- == 对于基本数据类型,比较值是否相等;对于引用类型,比较内存地址是否相同。
- equals 方法是 Object 类的方法,默认情况下比较的也是内存地址是否相同,但是子类一般会重写该方法。
- == 和 equals 的区别(作者也总结了不少面试题,可以一看)
5、可变长度参数?
- 可变长度参数就是允许在调用方法时传入不定长度的参数,例如
method(String... args)
。 - 可变长度参数在编译后会被转变为一个数组。
- 可变长度参数只能作为方法的最后一个参数。
- 遇到方法的重载时,会优先匹配固定参数而不是可变长度参数。
6、字符串“123”转为整型 123 的 API 是什么?反过来的 API 又是什么?
Integer.parseInt("123")
String.valueOf(123)
- int Integer String之间的转换
7、接口和抽象类的区别?什么时候用接口,什么时候用抽象类?接口之间可以继承吗?
- 接口和抽象类的区别
- 接口之间可以继承,并且可以多继承
- 使用方面:接口主要是对行为进行约束,是对行为的一种抽象。而抽象类是对事物的抽象,包含属性和行为的抽象。我们在选择时候可以根据这点来确定。如飞机和鸟,它没有共同属性,但是他们有共同的行为——飞,这个时候我们可以用接口。而民用飞机、战斗机等他们都是飞机一种,这个时候我们可以将飞机座位一个抽象类。
-
8、BIO、NIO、AIO 区别有哪些?
9、重载和重写的区别?重写有没有什么限制?
- Java 重写(Override)与重载(Overload)
- 关于方法返回值不同不会构成方法的重载,《深入理解Java虚拟机》中这样说:“在Java语言中,要重载(Overload)一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不同的特征签名。特征签名是指一个方法中各个参数在常量池中的字段符号引用的集合,也**正是因为返回值不会包含在特征签名之中,所以Java语言里面是无法仅仅依靠返回值的不同来对一个已有方法进行重载的。**但是在Class文件格式之中,特征签名的范围明显要更大一些,只要描述符不是完全一致的两个方法就可以共存。也就是说,如果两个方法有相同的名称和特征签名,但返回值不同,那么也是可以合法共存于同一个Class文件中的。”
- 在《Java虚拟机规范》第2版的4.4.4节及《Java语言规范》第3版的8.4.2节中分别都定义了字节码层面的方法特征签名以及Java代码层面的方法特征签名,Java代码的方法特征签名只包括方法名称、参数顺序及参数类型,而字节码的特征签名还包括方法返回值以及受查异常表。
14、HashMap 的底层结构?为什么线程不安全?1.7 之前的头插入法有什么问题?1.8 之后做了哪些优化或改变?为什么链表长度大于 8 时转为红黑树?红黑树节点添加过程?负载因子为什么是 0.75?扩容步骤?
底层数据结构:
- 1.8之前,数组+链表
- 1.8之后,数组+链表+红黑树
为什么线程不安全?
JDK1.7及之前的头节点插入法的问题:
- 并发情况下可能会造成死链(死循环)。(参考为什么HashMap线程不安全?)
JDK 1.8 对 HashMap 做了哪些优化?
- HashMap:Java1.8中做了哪些优化
- 数据结构方面
- 往链表中插入节点的方式
- hash 函数
- 扩容时计算元素下标位置的算法
为什么链表长度大于8时转为红黑树?
- 红黑树:红黑树与平衡二叉树的区别?
- 转为红黑树主要是为了提高查找效率。
红黑树中添加节点的过程?
负载因子为什么是0.75?
- 负载因子表示一个散列表的空间的使用程度,阈值 = 容量 × 负载因子,当元素数量超过阈值就会触发扩容。
- 所以负载因子越大则散列表的装填程度越高,也就是能容纳更多的元素,元素多了,链表大了,所以此时索引效率就会降低。反之,负载因子越小则链表中的数据量就越稀疏,此时会对空间造成烂费,但是此时索引效率高。
- 为什么默认是0.75?
- 此时空间利用率较高,并且能避免很多哈希冲突。
- 并且参考 jdk 文档,负载因子取 0.75 时,桶中链表的长度超过 8 的概率已经很小了,即查询效率不会受到太大影响。
15、HashMap 在使用时需要注意什么?说出四点
- 扩容是很耗时的操作,为了减少扩容次数,在知道要存放多少元素的前提下最好指定 HashMap 的链表初始大小。
- HashMap 是线程不安全的,在多线程的情况下最好使用 ConcurrentHashMap 代替。
- 尽量使用不可变类型作为 key。(在HashMap中将可变对象用作Key,需要注意什么?)
- 作为 key 的对象,一定要重写 hashcode 方法和 equals 方法。(为何重写equals方法就得重写hashCode方法)
16、hash 方式和 hash 冲突的解决方式?
-
HashMap 中的 hash 方法
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
- hashCode 右移16位,与自己本身做异或操作(相同为0,不同为1)。就是为了混合哈希值的高位和地位,增加低位的随机性。并且混合后的值也变相保持了高位的特征。使得计算出来的hash 比较均匀,不容易出现冲突。
哈希冲突的解决方式:
10、HashMap 和 HashTable 的区别?
HashMap 和 HashSet 的区别?HashSet 是如何检查重复的?
- JavaGuide —— HashMap 和 HashSet
- HashSet 中 维护了一个 HashMap 属性,很多操作都是借助 HashMap 实现的。例如 add(E e) 方法,即向 map 中加入一个以 e 为键、虚拟 Object 对象为值的键值对。
11、HashMap 和 TreeMap 的区别?
- 深入理解HashMap和TreeMap的区别
- TreeMap 可以实现对键值对按照键值排序;
- TreeMap 底层是红黑树,在添加,查找,删除等方法上面的速度不如 HashMap;
- TreeMap 只保存要保持的节点,所以占用的空间比较小。
- TreeMap 在添加和删除节点的时候会进行重排序,会对性能有所影响。
12、Queue 和 Deque 的区别?
13、为什么建议使用 ArrayDeque 而不是 LinkedList?
13、ArrayList 和 LinkedList 的区别?两者哪个比较占内存?add 和 get 的时间复杂度?扩容原理?
- ArrayList 和 LinkedList 的区别
- ArrayList源码解析&扩容机制
- LinkedList 比较占内存,因为每个节点不仅要存储数据,还要保存指向前驱节点和后继节点的指针。
- add 方法的时间复杂度:如果在末尾插入,ArrayList 和 LinkedList 都是 O(1);在中间某处插入,都是 O(n)。
- get 方法的时间复杂度:LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。
17、ConcurrentHashMap 又是怎样实现线程安全的?
18、jdk8 的新特性?
- JavaGuide —— Java8 新特性实战
- 新 Interface 的方法可以用 default 或 static 修饰,这样就可以有方法体,实现类也不必重写此方法。
- 函数式接口:只包含一个抽象方法的接口。提供函数式编程,Lambda 表达式就可以看作是一个函数式接口的实例。
- Lambda 表达式。
- Stream API。
19、说说匿名函数?Lambda 表达式的优缺点?
- 匿名函数就是 Lambda 表达式。
- java 8 lambda 表达式的优缺点总结
- 优点:代码简洁,减少匿名内部类的创建,节省资源。使用时不用去记忆所使用的接口和抽象方法。
- 缺点:可读性差一些,不利于调试,不利于后期维护,需要熟悉 lambda 表达式和抽象方法中参数的类型。
20、UML 类图的理解?画一个?
21、静态代理和动态代理的区别?动态代理有几种实现方式?(JDK提供的、CGLIB)
22、序列化和反序列化?
概念:
- 序列化: 将数据结构或对象转换成二进制字节流的过程
- 反序列化:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程
- 类需要实现 java.io.serializable 接口
- 序列化时,只对对象的状态进行保存,而不管对象的方法
实际开发中使用场景:
SerialVersionUID 的作用:
- 用来表明类的不同版本间的兼容性,建议显示的定义为静态常量。
- 如果没有显示定义,那么该值是 Java 运行时根据类的内部细节自动生成的。若类的实例变量或某些地方改变了,SerialVersionUID 就可能发生改变,会导致不能反序列化。
transient 和 static 修饰的属性不会被序列化
- “不会被序列化” —— 意思是对象的该属性状态不会被保存,但能够访问到该属性。
- 静态成员变量能不能被序列化????
- Java序列化与反序列化中,你可能会忽略的细节知识点