2024年Java实战面试题(北京)_java 5 年 面试-CSDN博客
一、redis基础类型:string(字符串)、hash(哈希)、list(列表)、set(集合)、sort set (有序集合)。
二、多线程有几种实现方式?
四种:①继承Thread类;②实现Runnable接口;③使用Callable和FutureTask实现有返回值的多线程;④使用ExecutorService和Executors工具类实现线程池(如果需要线程的返回值,需要在线程中实现Callable和Future接口)。
三、线程池有哪些?
六种常见线程池:FixedThreadPool(固定线程数的线程池)、CachedThreadPool(缓存线程池)、ScheduledThreadPool(定时线程池)、SingleThreadExecutor(单线程线程池)、SingleThreadScheduleExecutor(单线程线程池)、ForkJoinPool(分而治之)。
四、在Java中有哪些常见的队列?
ArrayList:ArrayList可以被用作队列。
LinkedList:LinkedList也可以用作队列。
ArrayBlockingQueue:ArrayBlockingQueue是一个有界阻塞队列。
LinkedBlockingQueue:LinkedBlockingQueue是一个可选有界或无界的阻塞队列。PriorityBlockingQueue:PriorityBlockingQueue是一个支持优先级的无界阻塞队列。ConcurrentLinkedQueue:ConcurrentLinkedQueue是一个非阻塞无界队列。
五、HashMap和HashTable区别?
1、继承的父类不同
Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
2、线程安全性不同
Hashtable 中的方法有Synchronize锁,而HashMap中的方法没有Synchronize锁,在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步,但使用HashMap时就必须要自己增加同步处理。
六、ConcurrentHashMap和HashMap的区别?
1、线程安全性:ConcurrentHashMap是线程安全的、HashMap非线程安全
2、锁的粒度:在并发环境虾HashMap需要使用外部锁。ConcurrentHashMap则使用的是分段锁
3、迭代的一致性:HashMap在迭代中对其进行修改,可能会导ConcurrentModificationException 异常或者遍历时丢失一些元素。ConcurrentHashMap允许在迭代的过程中进行修改,不会抛出 ConcurrentModificationException 异常。
4、初始化容量和负载因子的意义:
4.1、HashMap: 初始容量和负载因子用于控制 HashMap 的性能和空间占用。当元素数量达到容量乘以负载因子时,HashMap 会进行扩容。
4.2、ConcurrentHashMap: 初始容量和负载因子在 ConcurrentHashMap 中依然存在,但它们的含义稍有不同。由于 ConcurrentHashMap 的分段结构,不同的段会根据负载因子动态调整大小,而不是整个表进行扩容。
七、ConcurrentHashMap原理是什么?
1、volatile修饰的节点数组
//ConcurrentHashMap使用volatile修饰节点数组,保证其可见性,禁止指令重排。
transient volatile Node
2、ConcurrentHashMap的put()方法
//put()方法直接调用putVal()方法
public V put(K key, V value) {
return putVal(key, value, false);
}
putVal方法内容语言解析
做插入操作时,首先进入乐观锁,
然后,在乐观锁中判断容器是否初始化,
如果没初始化则初始化容器,
如果已经初始化,则判断该hash位置的节点是否为空,如果为空,则通过CAS操作进行插入。
如果该节点不为空,再判断容器是否在扩容中,如果在扩容,则帮助其扩容。
如果没有扩容,则进行最后一步,先加锁,然后找到hash值相同的那个节点(hash冲突),
循环判断这个节点上的链表,决定做覆盖操作还是插入操作。
循环结束,插入完毕。
3、ConcurrentHashMap的get()方法
//ConcurrentHashMap的get()方法是不加锁的,方法内部也没加锁。
public V get(Object key)
ConcurrentHashMap的get()方法是不加锁的,为什么可以不加锁?因为table有volatile关键字修饰,保证每次获取值都是最新的
八、线程生命周期?
new(初始化状态)、Runnable(就绪状态)、Running(运行状态)、Blocked(阻塞状态)、Terminated(终止状态)
九、JDK 和 JRE 有什么区别?
1、jdk和jre的区别为:JRE是java运行时环境而JDK是java开发工具包,JDK包含JRE,但是JRE可以独立安装。
2、JDK:java development kit (java开发工具),JDK 是用于开发 Java 程序的最小环境。
3、JRE:java runtime environment (java运行时环境),是提供给 Java 程序运行的最小环境
十、== 和 equals 的区别是什么?== 解读
"=="是判断两个变量或实例是不是指向同一个内存空间?
"equals"是判断两个变量或实例所指向的内存空间的值是不是相同。
==解读:==比较的是2个对象的地址,基本数据类型是直接保存在栈里面的,所以如果两个基本数据类型的值相同,则他们的栈的地址也相同。如果两个引用数据类型使用==比较,只要是两个分别new出来的对象,得到的结果就一定是false了。
十一、两个对象的 hashCode() 相同, 那么 equals() 也一定为 true吗?
不一定为true,哈希值是JDK根据对象的地址或者字符串或者数字(属性)算出来的int类型的数值,对象的地址一样String str1="通话",String str2="话通" 内存地址一样字符串长度一样hashcode一样,但是value对比的是值,所以不一定为true。
十二、final 在 Java 中有什么作用?
final可以用来修饰的结构:类、方法、变量
final用来修饰一个类:此类不能被其它类继承。
final用来修饰方法 :表明此方法不可以被重写
final用来修饰变量 ,此时变量就相当于常量
十三、Java 中的 Math. round(-1. 5) 等于多少?
Math.round(-1.5)的返回值是-1。四舍五入的原理是在参数上加0.5然后做向下取整。
十四、String 属于基础的数据类型吗?
String不是基本数据类型,是引用数据类型。
十五、Java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
拼接速度:StringBuilder>StringBuffer>String
线程方面:StringBuilder线程不安全、StringBuffer线程安全、
十六、String str="i"与 String str=new String("i")一样吗?(这道题考的原理是对Jvm对象一些存放位置的考察)
`String str="i";` 是一种简单的字符串字面量的创建方式,它使用字符串常量池中已经存在的 "i" 字符串。
而 `String str=new String("i");` 则是在堆上通过构造函数 new 一个新的 String 对象,这个新对象会在堆上分配一个新的内存地址。
十七、如何将字符串反转?
StringBuilder 或者StringBuffer的 reverse() 方法。
十八、String 类的常用方法都有那些?
equals:字符串是否相同、 equalsIgnoreCase:忽略大小写后字符串是否相同 、compareTo:根据字符串中每个字符的Unicode编码进行比较、 compareToIgnoreCase:根据字符串中每个字符的Unicode编码进行忽略大小写比较、 indexOf:目标字符或字符串在源字符串中位置下标、 lastIndexOf:目标字符或字符串在源字符串中最后一次出现的位置下标、 valueOf:其他类型转字符串 、charAt:获取指定下标位置的字符、 codePointAt:指定下标的字符的Unicode编码、 concat:追加字符串到当前字符串、 isEmpty:字符串长度是否为0、 contains:是否包含目标字符串 、startsWith:是否以目标字符串开头、 endsWith:是否以目标字符串结束、 format:格式化字符串、 getBytes:获取字符串的字节数组 、getChars:获取字符串的指定长度字符数组、 toCharArray:获取字符串的字符数组 、join:以某字符串,连接某字符串数组、 length:字符串字符数、 matches:字符串是否匹配正则表达式、 replace:字符串替换 、replaceAll:带正则字符串替换 、replaceFirst:替换第一个出现的目标字符串 、split:以某正则表达式分割字符串、 substring:截取字符串、 toLowerCase:字符串转小写 、toUpperCase:字符串转大写、 trim:去字符串首尾空格。
十九、抽象类必须要有抽象方法吗?
不需要,抽象类不一定非要有抽象方法
二十、普通类和抽象类有哪些区别?
抽象类需要abstract进行修饰
普通类可以实例化,抽象类不可以实例化
抽象方法只能定义在抽象类中,但是抽象类中可以有抽象方法和普通方法
二十一、抽象类能使用 final 修饰吗?
抽象类不能使用 final 修饰符,因为这两者的设计目的是相互矛盾的。抽象类是为了被继承和实现而存在的,使用 final 修饰符就不能被继承了。
二十二、接口和抽象类有什么区别?
声明方式不同:接口通过interface关键字声明;抽象类通过abstract声明。
修饰方式的不同:接口通常使用 public 修饰,也允许默认修饰符,只限本包访问。抽象类可以被 public、protected、default 修饰,但是不能被 private 和 final 修饰,抽象类可以有非抽象的方法。
变量的不同:接口中声明的变量全是静态常量;抽象类中可以有不同类型的变量。
实现的不同:类通过implements关键字来实现接口,一个类可以实现多个接口;类通过extends关键字来继承抽象类,一个类只能继承一个抽象类,因为抽象类首先是一个类。
方法是否需要实现: 抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类;接口里的接口方法如果不能被全部实现,那么该类也只能为抽象类。
二十三、Java 中 IO 流分为几种?
在Java中,IO流主要分为4种类型:字节流、字符流、字节缓冲流和字符缓冲流。
二十四、BIO、NIO、AIO 有什么区别?
BIO:Blocking IO,阻塞io,效率很低,因为经常被阻塞
NIO:New Non-Blocking:非阻塞IO(单线程模式)
AIO:异步IO
二十五、Files的常用方法都有哪些?
Files.exists() : 检测该路径文件是否存在
Files.createFile() : 创建文件
Files.createDirectory() : 创建目录
Files.copy() : 复制文件
Files.move() : 移动文件
Files.delete() : 删除文件
Files.size() : 查询文件个数
Files.read() : 读文件
Files.write() : 写文件
二十六、Java 容器都有哪些?
Collection:
list:
ArrayList:动态数组,可以根据需要自动扩展大小。
LinkedList:双向链表,可以高效地进行插入和删除操作。
Vector:动态数组,可以根据需要自动扩展大小。->Stack:栈,后进先出的数据结构。
Queue(队列,先进先出的数据结构):
LinkedList:双向链表,可以高效地进行插入和删除操作。
PriorityQueue:优先队列,根据元素的优先级进行排序。
set:
HashSet:无序集合,不允许重复元素。->LinkHashSet:实现的有序去重集合列表
TreeSet:有序集合,按照元素的自然顺序进行排序。
Map:
HashMap:无序键值对集合,根据键快速查找值。
TreeMap:有序键值对集合,根据键的自然顺序进行排序。
二十七、Collection 和 Collections 有什么区别?
collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,实现该接口的类主要有List和Set。
collections是针对集合类的一个包裹类,它提供了一系列静态方法实现对各种集合的搜索、排序以及线程安全化等操作。
二十八、List、Set、Map 之间的区别是什么?
List:有序、可重复。通过索引查找快,增删速度慢 (操作时后续的数据需要移动)。
Set:无序、不可重复的集合。
Map:键值对、键唯一、值不唯一。Map 集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对 map 集合遍历时先得到键的 set 集合,对 set 集合进行遍历,得到相应的值。
二十九、如何决定使用 HashMap 还是 TreeMap?
你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap。
三十、说一下 HashMap 的实现原理?
数组、链表、红黑树(jdk1.8)
三十一、说一下 HashSet 的实现原理?
HashSet的底层是使用一种称为哈希表的数据结构,值得一提的是,在Java中,HashSet内部是使用HashMap来存储元素的(将整个元素作为key)
三十二、ArrayList 和 LinkedList 的区别是什么?
数据结构不同:
ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)的数据结构。
效率不同:
当随机访问List(get和set操作)时,ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
当对数据进行增加和删除的操作(add和remove操作)时,LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
自由性不同:
ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;
而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
主要控件开销不同
ArrayList主要控件开销在于需要在List列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。
1、在后方插入时,ArrayList和LinkedList数据量小时速度相差无几,数据量大了之后ArrayList完胜;
2、在前方插入时,LinkedList速度完爆ArrayList,充分体现了其优势;
3、在随机插入时,LinkedList又被ArrayList完爆了(出来混迟早要还的)
4、在前方插入时,ArrayList可以使用后方插入,最后再使用Collections.reverse()方法反转,速度依然完爆LinkedList
三十三、如何实现数组和 List 之间的转换?
List
三十四、ArrayList 和 Vector 的区别是什么?
Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
三十五、Array 和 ArrayList 有何区别?