JAVA 基础
Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。 Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等
常见问题
== 和 equals 的区别
== 解读:
基本类型:比较的是值是否相同; 引用类型:比较的是引用是否相同;
若指向同一个引用,== 为 true,而
new String()方法重新开辟了内存空间, == 结果为 false,而 equals 比较的是值,结果为 trueequals 解读:equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较
总结: == 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,String、Integer 等类重写了equals,把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗
不对,两个对象的 hashCode() 相同,equals() 不一定 true。代码解读:显然“通话”和“重地”的 hashCode() 相同,然而 equals()为 false,因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
1  | String str1 = “通话”;  | 
Java 中的 Math. round(-1. 5) 等于多少
等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。
final 在 Java 中有什么作用
- final 修饰的类叫最终类,该类不能被继承。
 - final 修饰的方法不能被重写。
 - final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
 
基础的数据类型
基础类型有 8 种:byte、boolean、char、short、int、float、long、double
 String 不属于基础类型, String 属于对象
Files的常用方法都有哪些?
1  | Files.exists():检测文件路径是否存在。  | 
字符串String
Java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,**StringBuffer 线程安全,而 StringBuilder 非线程安全**,但 StringBuilder 性能高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
String str=”i”与 String str=new String(“i”)一样吗?
不一样,因为内存的分配方式不一样。
String str = ”i” 的方式,Java 虚拟机会将其分配到常量池中;
String str = new String(“i”) 则会被分到堆内存中。
如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
1  | // stringBuffer reverse  | 
String 类的常用方法
1  | indexOf():返回指定字符的索引。  | 
抽象类问题
抽象类必须要有抽象方法吗?
不需要,抽象类不一定非要有抽象方法。
普通类和抽象类有哪些区别?
普通类不能包含抽象方法,抽象类可以包含抽象方法。抽象类不能直接实例化,普通类可以直接实例化。
抽象类能使用 final 修饰吗?
不能,定义抽象类就是让其他类继承的,定义为 final的类不能被继承,所以 final 不能修饰抽象类,编辑器也会提示错误信息:illegal combination of modifiers: 'abstract' and 'final
接口和抽象类有什么区别?
- 实现:抽象类的子类使用 
extends来继承;接口必须使用implements来实现接口。 - 构造函数:抽象类可以有构造函数;接口不能有。
 - 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
 - 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
 
Java中的IO
Java 中 IO 流分为几种?
- 按功能来分:输入流(input)、输出流(output)。
 - 按类型来分:字节流和字符流。字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
 
BIO、NIO、AIO 有什么区别?
- BIO:
Block IO,同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。 - NIO:
Non IO,同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过Channel(通道)通讯,实现了多路复用。 - AIO:
Asynchronous IO,是 NIO 的升级,也叫NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。 
Lambda表达式
Lambda表达式的语法
基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
Lambda表达式由三部分组成:
- paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
 - ->:可理解为“被用于”的意思
 - 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
 
优缺点:
- 优点:代码简洁,开发迅速、方便函数式编程、容易进行并行计算、Java 引入 Lambda,改善了集合操作
 - 缺点:代码可读性变差、在非并行计算中,很多计算未必有传统的 for 性能要高、不易调试
 
应用举例
1  | list.stream().filter(s -> s.length() > 3).forEach(System.out::println);  | 
容器
Java 容器都有哪些?
Java 容器分为 Collection 和 Map 两大类,其下又有很多子类,如下所示:
1  | Collection  | 
Collection 和 Collections 有什么区别
Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法:Collections. sort(list)。
List、Set、Map 之间的区别是什么?
List、Set、Map 的区别主要体现在两个方面:元素是否有序、是否允许元素重复。三者之间的区别,如下表:

List、Set 和 Map 的初始容量和加载因子
| 初始容量 | 加载因子 | 扩容增量 | |
|---|---|---|---|
| ArrayList | 10 | 0.5 | 原容量的1.5倍 | 
| Vector | 10 | 1 | 原容量的2倍 | 
| HashSet | 16 | 0.75 | 原容量的2倍 | 
| HashMap | 16 | 0.75 | 原容量的2倍 | 
- 初始容量:这是集合在创建时分配的存储空间大小。初始容量越大,集合在创建时分配的内存空间就越大,但这并不意味着它不会进行扩容。初始容量只是集合在创建时的一个预设值。
 - 加载因子:这是触发集合扩容的比例。当集合中的元素数量超过当前容量的加载因子时,集合会自动进行扩容操作。加载因子越小,集合的内存利用率越高,但可能会导致更多的内存开销;加载因子越大,内存利用率低,但可以减少扩容次数。
 
HashMap
HashMap 和 Hashtable 有什么区别?
- 存储:
HashMap允许 key 和 value 为 null,而Hashtable不允许。 - 线程安全:
Hashtable是线程安全的,而HashMap是非线程安全的。 - 推荐使用:在 
Hashtable的类注释可以看到,Hashtable是保留类不建议使用,推荐在单线程环境下使用HashMap替代,如果需要多线程使用则用ConcurrentHashMap替代。 
HashMap 的实现原理?
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。
HashMap为什么线程不安全?
主要原因在于其内部结构的非原子性操作和缺乏同步机制,导致多线程并发操作时可能引发数据不一致、死循环、数据覆盖等问题。
如何决定使用 HashMap 还是 TreeMap?
对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但是如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。
HashSet 的实现原理?
HashSet 是基于 HashMap 实现的,HashSet 不允许重复的值。
HashSet 保证元素不重复是利用 HashMap 的 put 方法实现的,在存储之前先根据 key 的 hashCode 和 equals 判断是否已存在,如果存在就不在重复插入了,这样就保证了元素的不重复。
HashMap 和 ConcurrentHashMap 有什么区别?
ConcurrentHashMap的线程安全实现
- Java7:分段锁(Segment)。将数据分成多个段,每段独立加锁,不同段的操作可并发。
 - Java 8+:
CAS(无锁算法)+ synchronized(锁单个桶的头节点)。锁粒度更细,并发度更高。插入时,如果桶为空,用 CAS 添加;否则锁住头节点再操作。CAS(Compare And Swap(比较与交换))。读操作通常无锁(依赖 volatile 保证可见性)。 

List
ArrayList 和 LinkedList 的区别是什么?
- 数据结构实现:
ArrayList是动态数组的数据结构实现,而LinkedList是双向链表的数据结构实现。 - 随机访问效率:
ArrayList比LinkedList在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。 - 增加和删除效率:在非首尾的增加和删除操作,
LinkedList要比ArrayList效率要高,因为ArrayList增删操作要影响数组内的其他数据的下标。 
如何实现数组和 List 之间的转换?
- 数组转 List:使用 
Arrays. asList(array)进行转换。 - List 转数组:使用 List 自带的 
toArray()方法。 
ArrayList 和 Vector 的区别是什么?
- 线程安全:
Vector使用了Synchronized来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。 - **性能:
**ArrayList在性能方面要优于Vector。 - 扩容:
ArrayList 和 Vector都会根据实际需要动态调整容量,它们的初始容量都是10,不过Vector 扩容每次会增加 1 倍,而ArrayList 增加 50%。 
Array 和 ArrayList 有何区别?
Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
迭代器Iterator
迭代器 Iterator 是什么?
Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
Iterator 怎么使用?有什么特点?
Iterator 使用代码如下所示:
1  | List<string> list = new ArrayList<>();  | 
Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改时,就会抛出 ConcurrentModificationException 异常。
Iterator 和 ListIterator 有什么区别?
Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。ListIterator 从 Iterator 接口继承,添加了一些额外功能,如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
其他相关问题
在 Queue 中 poll()和 remove()有什么区别?
相同点:都是返回第一个元素,并在队列中删除返回的对象。
不同点:如果没有元素 poll() 会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。
哪些集合类是线程安全的?
Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap。
怎么确保一个集合不能被修改?
使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。
示例代码如下所示:
1  | List<string> list = new ArrayList<>();list. add("x”);  | 





