共计 7693 个字符,预计需要花费 20 分钟才能阅读完成。
近段时间在准备实习的面试,在网上看到一份面试题,就慢慢试着做,争取每天积累一点点。
暂时手头上的面试题只有一份,题量还是挺大的,有 208 题,所以可能讲的不是很详细,只是我自己帮助记忆的笔记,希望对你们有启发,同时有什么说的不准确的可以互相讨论一下。
现在每天给自己在面试题编写的任务是 4 题,有时候忙起来可能就没有时间写了,但是争取日更,即使当天没更也会在之后的更新补上。
-
JDK 和 JRE 区别
- JDK 全名为 Java development kit
- JRE 全名为 Java Runtime environment
- JDK 包括 JRE,编译器 javac,以及很多调试和分析工具,例如 jconsole 等等
- Java 程序运行环境必须有 JRE
-
== 和 equals 的区别
- 在基本数据类型对比中,== 用于对比两者是否相等,没有 equals 的适用
- equals 是 Object 类的实例方法,若子类没有重写 equals 方法,则跟 == 作用一致
- 在引用数据类型对比中,== 用于对比实例内存地址是否相同,若引用都指向同一对象,则返回 true
- 在引用数据类型对比中,euqals 的返回值取决于重写逻辑
-
两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗
- equals 用于对比对象间是否相等
- hasCode 则是给对象返回一个 hash code 值
- 在使用 Object 默认的 hasCode 以及 equals 时,equals 返回为 true
- 若 hasCode 或 equals 任一方法被重写,返回的结果取决于重写逻辑的实现
-
final 在 Java 中作用
- final 可以修饰类,方法,变量
- final 修饰类,则该类不能被继承,且类内所有方法自动指定为 final 方法
- final 修饰方法,则该方法不能被继承,类内 private 隐式指定为 final 方法
- final 修饰基本数据类型变量,则该变量需在定义时指定初始值,且后续该值不能被改变
- final 修改引用类型的变量,则该变量不能再指向其他对象。
- final 修饰变量,在编译时 JVM 已经将他作为常量,存放于常量池中
-
Java 中的 Math.round(-1.5)
- Java 中的 Math.round(-1.5) 等于 -1
- Java 中的 Math.round(-1.4) 等于 -1
- Java 中的 Math.round(-1.6) 等于 -2
-
String 属于基础的数据类型吗
- String 不属于基础数据类型,属于引用数据类型
- String 拥有很多方法对字符串进行处理,翻转裁切追加等等
-
Java 中操作字符串都有哪些类?它们之间有什么区别?
- StringBuilder 以及 StringBuffer
- StringBuffer 为线程安全的,性能较 StringBuilder 弱
- StringBuilder 为线程不安全的,但是性能比 StringBuffer 好
- 若无线程安全的考虑,通常使用 StringBuilder
-
String str=”i” 与 String str=new String(“i”) 一样吗
- 不一样
- 两者的引用都存放于栈中,但是前一引用指向常量池,后一引用指向堆中对象中,对象再指向常量池
-
如何将字符串反转
- 采用递归以及二分法进行字符串反转
- 调用 String 中的 reverse 方法进行反转
- 正序遍历字符串倒序拼接字符串
- 将字符串转换成字符数组,倒序遍历数组拼接
- 正序遍历 1 / 2 长度字符串,将开头以及对应结尾的字符对调
-
String 类的常用方法
-
字符类
* charAt(int),根据索引找到索引上字符 * indexOf, 寻找条件在当前字符串上的索引
-
字符串信息类
* length,字串长度 * isEmpty,判断字符串是否为空
-
字符串操作类
* trim,删除字符串中所有空格 * substring,截取一部分字符串 * toUpperCase,将字符串全变成大写 * spilt,根据条件切割字符串并返回数组 * concat,追加字符串
-
对比
* equals * compareTo
-
-
抽象类必须要有抽象方法吗
- 抽象类中可以不含有抽象方法,日常开发主要使用抽象类作为模板,若抽象类不含抽象方法,我觉得丧失了抽象类原有的功能
-
普通类和抽象类有哪些区别
- 普通类可以实例化,抽象类不可以
- 普通类不能有抽象方法,抽象类可以含有抽象方法
- 抽象类被继承时必须选择继承父类的一个构造方法
-
抽象类能使用 final 修饰吗?
- 抽象类不能用 final 修饰。
- final 修饰的类不能被继承,抽象类设计的初衷就是为了被继承
-
接口和抽象类有什么区别?
- 接口不能有抽象方法,抽象类可以
- 接口内方法只声明不实现,抽象类的方法可以有具体实现
- 接口内变量默认为 final static,抽象类变量跟普通类一致
- 接口方法默认是 public
- 普通类可以实现多个接口,只能继承一个抽象类
-
Java 中 IO 流分为几种?
- 操作对象来看,分为字节流,字符流
- 流的流向来看,分为输入流输出流
- 总体来说,流分为节点流和处理流,应用了装饰模式,用处理流包装节点流,达到代码通用性
-
BIO、NIO、AIO 有什么区别?
- BIO,从发起 I / O 请求开始到接收结果,线程都是阻塞的
- NIO,线程发起 I / O 请求后立刻返回,当接收数据时,I/ O 通知线程,线程阻塞获取结果
- AIO,线程发起 I / O 请求后立刻返回,I/ O 操作不阻塞线程,结果通过回调函数进行返回
-
File 的常用方法都有哪些?
-
获取文件名字及路径
* getName,获取文件名字 * getPath。获取文件当前路径 * getPath,获取文件绝对路径 * isAbsoulute,判断文件是否绝对路径
-
文件信息
* canRead/canWrite,是否可读 / 可写 * isFile,是否是文件 * isDirectory,是否是目录 * length,文件内容长度
-
文件操作
* createFile,新建一个文件 / 目录 * delete,删除当前文件 / 目录 * exists,判断文件 / 目录是否存在
-
-
Java 容器都有哪些?
- java 容器主要分两种,单一数据类型以及键值对:Collection 以及 map
- Collection 包括 List,Set,Queue,List 为有序列表,Set 为无序列表,Queue 为队列实现
- Map 子类以及接口底层实现不一样,但是高层使用是一样的
-
Collection 和 Collections 有什么区别?
- Collection 为 java 集合类,Collections 为 java 集合操作类
-
Collections 常用方法
* addAll * binarySearch,二分查找 * emptyList,返回一个有序空列表 * synchronizedXxx,将线程不安全的集合转换成线程安全的集合
- Collection 具有 Set,List,Queue 子接口,用于多数据的存储以及使用
-
List、Set、Map 之间的区别是什么?
- Set 为无序集合,List 为有序列表,Map 为键值对集合
- Set 的底层实现为:Map 的所有 value 置为 null 封装而成,Map 的 key 是唯一的,所以 Set 不允许重复元素
- Set 不允许重复元素,List 允许重复元素
- Set 和 List 只允许存储单一元素,Map 允许存储有映射关系的键值对
-
HashMap 和 Hashtable 有什么区别?
- HashMap 为线程不安全,Hashtable 线程安全
- HashMap 允许使用 null 作为 key 或 value,Hashtable 不允许
- Hashtable 使用 Enumeration 遍历,HashMap 没有专门的迭代器,但是可以通过遍历 key 的集合或者 entry 对,也可以使用 java8 的函数接口进行遍历
-
如何决定使用 HashMap 还是 TreeMap?
- HashMap 为无序集合,TreeMap 为有序集合
- HashMap 底层存储结构为数组,TreeMap 为红黑树
- 数据量大且需要按照 key 排序时,使用 TreeMap
- 数据量小且对顺序无要求时,使用 HashMap
- 若查找操作占大部分时,使用 HashMap,插入删除大部分时使用 TreeMap
-
说一下 HashMap 的实现原理?
- HashMap 底层封装了一个 Entry 数组,元素位置基于 Object 类的 hashCode 函数计算
- 当出现哈希冲突时,采用拉链法解决冲突
- 数组的初始大小由 capacity 决定,默认是 16
- 当数组达到一定限度时,触发到负载因子的极限,数组进行动态扩容,扩容后的大小为原大小的两倍
2019.4.24 更新
-
说一下 HashSet 的实现原理?
- HashSet 底层为 HashMap,方法几乎都是调用 HashMap 相关方法实现
-
ArrayList 和 LinkedList 的区别是什么?
- ArrayList 底层实现为数组,当数组元素个数达到数组长度时,数组将进行动态扩容
- LinkedList 底层实现为链表,原则上不存在元素个数饱和的情况
- ArrayList 常用于随机访问场景
- 在添加删除场景中,ArrayList 主要耗时为 System.arrayCopy,Linked
List 则是通过 for 循环寻找插入位置。* 数据量小于 30,两者没有明显差别,当数据量大于容量 1 /10 时,LinkedList 的效率没有 ArrayList 高
* 在元素个数大致相等的情况下,两者遍历的性能差不多
-
如何实现数组和 List 之间的转换?
-
List 转 Array
- 调用 List 成员方法 toArray
- for 循环生成 Array
-
Array 转 List
- 调用 Arrays 类方法 asList
- for 循环生成
-
-
ArrayList 和 Vector 的区别是什么?
- Vector 为 jdk1.0 的集合类,内部通过数组实现,支持 Enumeration 遍历
- ArrayList 为 1.2 的集合类,内部通过数组实现,支持 Iterator 遍历
- Vector 线程同步,ArrayList 线程不同步
- 内存不足时,Vector 默认扩展 1 倍,ArrayList 默认扩展 1.5 倍
-
Array 和 ArrayList 有何区别?
- Array 可以含有基本数据类型和引用类型,ArrayList 只能包括引用类型
- Array 的大小是固定的,ArrayList 大小可以动态增加
- ArrayList 对数据的处理方法比 Array 多,ArrayList 为 Array 的加强版
- Array 的元素数据类型一样,ArrayList 在未指定泛型的前提下数据类型可以多样
- 实际开发中 Array 不常用,主要用于确定元素个数的场景中。多用 ArrayList
2019.04.25 更新
-
在 Queue 中 poll() 和 remove() 有什么区别?
- 在队列不为空时,两者的作用都是返回队头元素
- 在队列为空时,使用 poll 方法会返回 null,使用 remove 则会抛出 NoSuchElementException 异常
-
哪些集合类是线程安全的?
- Hashtable,Vector,Stack
- 由 Collections 的 synchronizedXxx 方法包装的集合
-
java.util.concurrent 包中的集合
- ConcurrentHashMap
- CopyOnWriteArrayList/CopyOnWriteArraySet
-
迭代器 Iterator 是什么?
- Iterator 隐藏了 Collection 实现类的具体细节,提供很多对集合元素进行迭代的方法
-
Iterator 怎么使用?有什么特点?
- 使用集合类的成员方法获取 Iterator 实例
- hasNext, 检查是否具有下一迭代元素
- next,获取下一迭代元素
- forEachRemaining,java 8 新增的方法,利用函数式接口进行迭代
- remove,移除底层集合元素
2019.04.26 更新
-
Iterator 和 ListIterator 有什么区别?
-
相同
* 都是迭代器,都可以用于迭代 Collection 集合 * 都可以顺序向后遍历集合元素 * 都可以移除底层集合元素
-
不同
* ListIteaator 有 add 方法,可以添加元素到底层集合中,位置在迭代器当前位置之前 * ListIterator 可以向前遍历,Iterator 不能 * ListIterator 可以通过 nextIndex 以及 preIndex 定位索引位置,Iteratoor 不能 * ListIterator 可以通过 set 方法对元素进行修改
-
-
怎么确保一个集合不能被修改?
- 通过 Collections 工具类的静态方法 unmodifiableXxx 对可变集合进行封装
- 通过 Collections 的静态方法 emptyXxx 返回一个空的不可变集合
- 通过 Collections 静态方法 singletonXxx 返回带有特定对象的不可变集合
-
并行和并发有什么区别?
- 并行是指能同时处理多个任务的能力,属于计算机硬件处理范畴
- 并发是指多个任务被计算机交替执行,例如 Java 的多线程,属于计算机软件的范畴
-
线程和进程的区别?
- 进程是程序在计算机的一次执行活动,是操作系统分配资源的基本单位,可以单独执行
- 线程是进程的一个实体,是 CPU 调度和分派的基本单位,必须依附于进程执行
- 进程是计算机硬件范畴的概念,线程是计算机软件范畴的概念
- 一个进程至少由一个线程组成
2019.04.27 更新
-
守护线程是什么?
- 在 Java 中有两类线程,用户线程与守护线程
- 守护线程独立于控制终端·并且周期性执行某种任务或等待处理某些发生的事件
- 守护线程主要为其他线程运行提供便利服务,例如 GC
- 守护线程创建与用户线程大概一致,但要在线程开始之前通过成员方法 setDaemon 设置为守护线程
- 当所有非守护线程停止工作时,守护线程才会停止工作
-
创建线程有哪几种方式?
- 通过继承 Tread 并重写 run 方法创建
- 通过实现 Runnable 接口并重写 run 方法创建
- 通过实现 Callable 接口重写 call 方法,并使用 FutureTask 包装对象进行创建
-
说一下 runnable 和 callable 有什么区别?
- callable 有返回值,可以通过 Future 接口的 get 方法获取,runnable 没有返回值
- callable 执行会阻塞线程,runnable 不会
- callable 的执行通过 FutureTask 进行包装,runnable 的执行则通过 Thread
- callable 可以抛出异常,runnable 只能在内部进行处理
-
线程有哪些状态?
- 新建,就绪,运行,阻塞,死亡五种状态
- 当调用线程类的 start 方法时,线程进入就绪状态,等待获得 CPU 时间片
- 线程得到 CPU 时间片时进行运行状态
- 当调用 sleep 方法,调用阻塞式 I /O,试图获取同步监视器,suspend 被调用,等待 notify 时,进入阻塞状态
- 当被 notify,获取到资源或同步监视器时,进行就绪状态
- 当 run/call 方法执行完毕,抛出异常未处理或调用 stop 方法时,线程死亡
2019.04.28 更新
-
sleep() 和 wait() 有什么区别?
- sleep 属于线程类方法,wait 属于 Object 类的方法
- sleep 不会释放线程锁,wait 释放线程锁
-
notify() 和 notifyAll() 有什么区别?
- notify 和 notifyAll 都属于 Object 类的方法
- notify 只会随机选择某一 wait 线程唤醒,notifyAll 则会全部唤醒等待线程
-
线程的 run() 和 start() 有什么区别?
- run 定义线程执行的方法体,定义完成后线程处于新建状态
- start 用于线程的执行,调用后线程处于就绪状态
-
创建线程池有哪几种方式?
- 创建单线程的线程池:newSingleThreadExecutor
- 创建固定大小的线程池:newFixedThreadPool
- 创建带缓存的线程池:newCachedThreadPool
- 创建大小无限的线程池:newScheduledPool,用于定时或周期性执行任务
2019.04.29 更新
-
线程池都有哪些状态?
- running:线程池一旦创建,进入 running 状态,接受新任务并处理现有任务
- shutdown:调用线程池 shutdown 方法,不接受新任务,但能处理已有任务
- stop:调用线程池 shutdownNow 方法,不接受新任务,不处理现有任务,中断现有任务
- tidying:当线程池处于 stop 并且任务队列为空时,执行 terminated 方法
- terminated:线程池处于 tidying 状态并执行完 terminated 方法,线程池终止
-
线程池中 submit() 和 execute() 方法有什么区别?
- execute 提交一个 Runnable 对象
- submit 可以提交 Runnable 或者 Callable 对象
- submit 可以提交 Callable 对象后返回一个泛型对象
-
在 Java 程序中怎么保证多线程的运行安全?
- 通过设置符号位进行访问,但是资源浪费严重
- 通过 synchronized 代码同步块进行互斥资源的访问
- 通过锁机制的等待与唤醒控制资源的访问
- 通过阻塞队列控制互斥资源的数量进而控制资源的访问
-
多线程锁的升级原理是什么?
- 略
2019.05.02 更新
-
什么是死锁?
- 指两个或两个以上的进程在执行过程中, 因争夺资源而造成的一种互相等待的现象, 若无外在协调, 它们都将无法推进下去
-
怎么防止死锁?
-
预防死锁
- 破环互斥条件
- 破环部分分配条件
- 破环循环等待条件
- 破环不可抢占条件
-
避免死锁
- 在为申请者分配资源前检测系统状态
- 循环检测死锁是否产生
-
-
ThreadLocal 是什么?有哪些使用场景?
- 线程局部变量,为每一线程提供其副本,副本间独立
- 隔壁线程间对共享变量的竞争
- 使用场景:多线程中使用同一变量,且该变量没有线程冲突现象
-
说一下 Synchronized 底层实现原理?
- 暂未了解
-
synchronized 和 volatile 的区别是什么?
- synchronized 保证操作的内存可见性,volatile 保证变量的可见性
- synchronized 作用在变量,代码块,方法,类,volatile 作用在变量级别
- volatile 保证程序从主存读取变量的值,synchronized 锁定当前变量,甚至造成线程阻塞
- volatile 变量不会被编译器优化,synchronized 会被编译器优化
- volatile 只能保证变量修改可见性,不能保证原子性;synchronized 能保证变量修改可见性和原子性
-
synchronized 和 Lock 有什么区别?
- synchronized 是 java 关键字,lock 是 java 一个类
- synchronized 线程执行完成或者执行异常自动释放锁,Lock 必须显式释放锁
- synchronized 无法判断锁状态,Lock 可以
- synchronized 会组成线程阻塞,Lock 不会
- 参考:https://blog.csdn.net/u012403…
-
synchronized 和 ReentrantLock 区别是什么?
- 两者都是同一线程进入一次,锁计数器自增 1,计数器变成 0 释放锁
- synchronized 依赖 JVM 实现,synchronized 是 JDK 实现的
- synchronized 自动释放锁,synchronized 显式释放锁
- 锁的细粒度和灵活度:ReenTrantLock 优于 synchronized
- ReenTrantLock 可以指定公平或非公平锁,synchronized 为非公平锁
- ReenTrantLock 可以指定唤醒线程,synchronized 只能随机或全部唤醒线程
- 参考:https://blog.csdn.net/qq83864…
-
说一下 Atomic 的原理?
- 暂未了解