Java中级面试题及答案【最新版及答案,干货!!!这是中级的Java面试系列问题的第一部分。本部分讨论了可变参数、断言、垃圾回收、初始化器、令牌、日期、日历等Java核心问题。
Java中级面试总是程序员成功的第一个门槛。如果你想成功地面试,各种面试问题的洗礼是必不可少的。让我们来看看小编精心整理的一些java高级工程师面试题及答案。
如果不背 Java面试题的答案,面试肯定会挂!
这套Java希望对大家有所帮助。~
博主已经把以下面试题整理成一个Java面试手册,是的PDF版的
1.线程与过程的区别
流程是系统资源分配和调度的独立单位,线程是CPU基本单位的调度和分配
过程与线程的关系:
一个线程只能属于一个过程,一个过程可以有多个线程,但至少有一个线程。
资源分配给进程,同一进程的所有线程共享该进程的所有资源。
在执行过程中,线程需要协作同步。不同过程的线程应通过消息通信实现同步。
线程是指过程中的执行单元,也是过程中的可调度实体。
线程与过程的区别:
调度:线程作为调度和分配的基本单位,过程作为资源的基本单位。
并发性:不仅可以并发执行,还可以并发执行同一过程的多个线程。
拥有资源:流程是一个拥有资源的独立单位,线程没有系统资源,但可以访问流程资源。
系统费用:在创建或撤销过程中,系统明显大于创建或撤销线程时的费用,因为系统必须分配和回收资源。然而,过程中有独立的地址空间。过程崩溃后,在保护模式下不会影响其他过程,线程只是过程中不同的执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间。线程死亡意味着整个过程死亡。因此,多过程程序比多线程程序更强大,但在过程切换过程中,资源消耗更大,效率更差。
什么是战略模式?
定义了一系列算法 或 逻辑 或 具有相同意义的操作,包装每个算法、逻辑和操作,并相互替换。(实际上,战略模式Java中用非常非常广泛)
我觉得主要是为了 简化 if...else 复杂而难以维护。
3.什么是游标?
游标是sql查询结果集的指针select语句相关联。
游标关键字是cursor,主要包括游标结果集和游标位置两部分。
游标结果集:执行select句子后的查询结果
游标位置:指向游标结果集中记录的指针。
游标主要有两种状态:开关。
只有当游标处于打开状态时,才能集中操作结果的数据
当游标关闭后,查询结果集就不存在了
了解单例模式吗?给我解释一下实现单例模式的双重检验锁模式!
双锁机制的出现是为了解决前面的同步问题和性能问题。看看下面的代码。简单分析一下,多线程并行解决,不会重复new对象也实现了懒加载
public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { ///先判断对象是否已经实例,进入加锁代码前没有实例化 if (uniqueInstance == null) { //类对象加锁 synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
另外,要注意 uniqueInstance 采用 volatile 还需要修改关键字。
uniqueInstance 采用 volatile 还需要修改关键词, uniqueInstance = new Singleton(); 这个代码实际上分为三个步骤:
为 uniqueInstance 内存空间的分配
初始化 uniqueInstance
将 uniqueInstance 指向分配的内存地址
但是由于 JVM 具有指令重排的特点,执行顺序可能成为 1->3->2。在单线程环境中重新安排指令不会有问题,但在多线程环境中,一个线程获取还没有初始化的例子会导致。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不是空的,所以回来 uniqueInstance,但此时 uniqueInstance 尚未初始化。
使用 volatile 可以禁止 JVM 重排指令,确保在多线程环境下正常运行。
5、怎么获取 Java 程序使用的内存?堆叠使用的百分比?
可以通过 java.lang.Runtime 获取剩余内存、总内存和最大堆内存的方法。还可以通过这些方法获得堆内存的百分比和剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory()总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
6、在java中守护线程和本地线程的区别?
java有两种线程:守护线程(Daemon)和用户线程(User)。
任何线程都可以设置为保护线程和用户线程Thread.setDaemon(bool on);true将该线程设置为保护线程,否则为用户线程。Thread.setDaemon()必须在Thread.start()先调用,否则运行时会抛出异常。
:
唯一的区别是判断虚拟机(JVM)何时离开,Daemon如果所有服务于其他线程User Thread已经撤离,Daemon 没有可服务的线程,JVM撤离。也可以理解为守护线程是JVM自动创建的线程(但不一定),用户线程是程序创建的线程;例如JVM垃圾回收线程是一个保护线程。当所有线程都被疏散,不再产生垃圾时,保护线程自然无事可做。当垃圾回收线程是Java当虚拟机上只剩下线程时,Java自动离开虚拟机会。
:
Thread Dump打印的线程信息包含daemon字样线程为守护过程,可能包括:服务守护过程、编译守护过程、windows下的监听Ctrl break保护过程,Finalizer守护进程、引用处理守护进程、GC守护进程。
7.线程如何通信?
当线程间能够共享资源时,线程间通信是协调资源的重要手段。Object类中wait()\notify()\notifyAll()该方法可用于线程间通信资源锁的状态。
8.聚集索引和非聚集索引有什么区别?
所有的索引都是为了更快地检索数据,索引存放在索引页中,数据存放在数据页中,索引以B(balance)以树的形式储存
收集索引:收集索引用于确定数据表中的物理存储顺序。一个表最多有一个收集索引。收集索引的字段值不能尽可能修改,因为修改后数据表的物理顺序需要重写和排序。通常,关键是收集索引
非聚集索引:非聚集索引的关键是index,表中最多可以有249个非聚集索引,不会决定物理存储顺序。
9、说一下 ArrayList 的优缺点
ArrayList 数组实现底层是一种随机访问模式。ArrayList 实现了 RandomAccess 接口,所以搜索非常快。
ArrayList 在顺序添加一个元素的时候非常方便。
删除元素时,需要进行元素复制操作。假如要复制的元素很多,那么就会更耗费性能。
插入元素时,还需要做一次元素复制操作,缺点同上。
ArrayList 更适合顺序添加、随机访问的场景。
10、请解释StackOverflowError和OutOfMemeryError的区别?
通过之前的分析,我们可以发现,事实上,每个内存中都会有一些可变伸缩区。基本过程是:如果空间内存不足,则在可变范围内扩大内存空间。当一段时间后发现足够的内存时,内存空间就会缩小。
虽然java的版本是JDK1.8,但是java EE 的版本还是jdk1.7.永久存在于堆内存中
元空间在Jdk1.8后才有,器功能其实和永久代没有区别,唯一的区别在于永久代使用的是JVM的堆内存空间,元空间使用的是物理内存,所以元空间的大小受本地内存影响,一般默认在2M 左右。
Java -XX:MetaspaceSize=1m
11、请阐述Catalina的配置文件有哪些?
Catalina包含的配置文件有:
·policy
·properties
·properties
·xml
·xml
·Tomcat-users.xml
12、Java中有几种类型的流?
字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在http://java.io 包中还有许多其他的流,主要是为了提高性能和使用方便。关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。
面试题 - 编程实现文件拷贝。(这个题目在笔试的时候经常出现,下面的代码给出了两种实现方案)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public final class MyUtil {
private MyUtil() {
throw new AssertionError();
}
public static void fileCopy(String source, String target) throws IOException {
try (InputStream in = new FileInputStream(source)) {
try (OutputStream out = new FileOutputStream(target)) {
byte[] buffer = new byte[4096];
int bytesToRead;
while ((bytesToRead = in .read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
}
}
}
public static void fileCopyNIO(String source, String target) throws IOException {
try (FileInputStream in = new FileInputStream(source)) {
try (FileOutputStream out = new FileOutputStream(target)) {
FileChannel inChannel = in .getChannel();
FileChannel outChannel = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(4096);
while (inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
}
}
}
}
注意:上面用到Java 7的TWR,使用TWR后可以不用在finally中释放外部资源 ,从而让代码更加优雅。
13、当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?
不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。
14、什么是不可变对象(immutable object)?Java 中怎么创建一个不可变对象?
不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。详情参见答案,一步一步指导你在 Java 中创建一个不可变的类。
15、怎么利用 JUnit 来测试一个方法的异常?
http://javarevisited.blogspot.sg/2013/04/JUnit-tutorial-example-test-exception-thrown-by-java-method.html
16、两个相同的对象会有不同的的 hash code 吗?
不能,根据 hash code 的规定,这是不可能的。
17、如果你提交任务时,线程池队列已满,这时会发生什么
如果使用的是无界队列 LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为 LinkedBlockingQueue 可以近乎认为是一个无穷大的队列,可以无限存放任务
如果使用的是有界队列比如 ArrayBlockingQueue,任务首先会被添加到ArrayBlockingQueue 中,ArrayBlockingQueue 满了,会根据maximumPoolSize 的值增加线程数量,如果增加了线程数量还是处理不过来,ArrayBlockingQueue 继续满,那么则会使用拒绝策略RejectedExecutionHandler 处理满了的任务,默认是 AbortPolicy
18、GC日志的real、user、sys是什么意思?
real
实际花费的时间,指的是从开始到结束所花费的时间。比如进程在等待I/O完成,这个阻塞时间也会被计算在内。user
指的是进程在用户态(User Mode)所花费的时间,只统计本进程所使用的时间,是指多核。sys
指的是进程在核心态(Kernel Mode)花费的CPU时间量,指的是内核中的系统调用所花费的时间,只统计本进程所使用的时间。
这个是用来看日志用的,如果你不看日志,那不了解也无妨。不过,这三个参数的意义,在你能看到的地方,基本上都是一致的,比如操作系统。
19、解释 Java 堆空间及 GC?
当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个进程,回收无效对象的内存用于将来的分配。
20、类的实例化顺序
先静态、先父后子。
先静态:父静态 > 子静态
优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数
父类中的static代码块,当前类的static
顺序执行父类的普通代码块
父类的构造函数
子类普通代码块
子类(当前类)的构造函数,按顺序执行。
子类方法的执行,
21、Spring中自动装配的方式有哪些?
no:不进行自动装配,手动设置Bean的依赖关系。
byName:根据Bean的名字进行自动装配。
byType:根据Bean的类型进行自动装配。
constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
22、栈帧里面包含哪些东西?
局部变量表、操作数栈、动态连接、返回地址等
23、你是如何调用 wait() 方法的?使用 if 块还是循环?为什么?
处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。
wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:
synchronized (monitor) { // 判断条件谓词是否得到满足 while(!locked) { // 等待唤醒 monitor.wait(); } // 处理其他的业务逻辑 }
24、ArrayList与LinkedList有什么区别?
ArrayList与LinkedList都实现了List接口。
ArrayList是线性表,底层是使用数组实现的,它在尾端插入和访问数据时效率较高,
Linked是双向链表,他在中间插入或者头部插入时效率较高,在访问数据时效率较低
25、Super与this表示什么?
Super表示当前类的父类对象
This表示当前类的对象
26、简述Java的对象结构
Java对象由三个部分组成:对象头、实例数据、对齐填充。
对象头由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、线程持有的锁、偏向线程ID(一般占32/64 bit)。第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。
实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的)
对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐 )
27、Java 虚拟机栈的作用?
来描述 Java 方法的内存模型。每当有新线程创建时就会分配一个栈空间,线程结束后栈空间被回收,栈与线程拥有相同的生命周期。栈中元素用于支持虚拟机进行方法调用,每个方法在执行时都会创建一个栈帧存储方法的局部变量表、操作栈、动态链接和方法出口等信息。每个方法从调用到执行完成,就是栈帧从入栈到出栈的过程。
有两类异常:① 线程请求的栈深度大于虚拟机允许的深度抛出 StackOverflowError。② 如果 JVM 栈容量可以动态扩展,栈扩展无法申请足够内存抛出 OutOfMemoryError(HotSpot 不可动态扩展,不存在此问题)。
28、实际开发中应用场景哪里用到了模板方法
其实很多框架中都有用到了模板方法模式
数据库访问的封装、Junit单元测试、servlet中关于doGet/doPost方法的调用等等
29、import java和javax有什么区别
tech.souyunku.com/EasonJim/p/…
31、Spring中自动装配的方式有哪些?
no:不进行自动装配,手动设置Bean的依赖关系。
byName:根据Bean的名字进行自动装配。
byType:根据Bean的类型进行自动装配。
constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
32、栈帧里面包含哪些东西?
局部变量表、操作数栈、动态连接、返回地址等
33、你是如何调用 wait() 方法的?使用 if 块还是循环?为什么?
处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。
wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:
synchronized (monitor) { // 判断条件谓词是否得到满足 while(!locked) { // 等待唤醒 monitor.wait(); } // 处理其他的业务逻辑 }
34、ArrayList与LinkedList有什么区别?
ArrayList与LinkedList都实现了List接口。
ArrayList是线性表,底层是使用数组实现的,它在尾端插入和访问数据时效率较高,
Linked是双向链表,他在中间插入或者头部插入时效率较高,在访问数据时效率较低
35、Super与this表示什么?
Super表示当前类的父类对象
This表示当前类的对象
36、简述Java的对象结构
Java对象由三个部分组成:对象头、实例数据、对齐填充。
对象头由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、线程持有的锁、偏向线程ID(一般占32/64 bit)。第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。
实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的)
对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐 )
37、Java 虚拟机栈的作用?
来描述 Java 方法的内存模型。每当有新线程创建时就会分配一个栈空间,线程结束后栈空间被回收,栈与线程拥有相同的生命周期。栈中元素用于支持虚拟机进行方法调用,每个方法在执行时都会创建一个栈帧存储方法的局部变量表、操作栈、动态链接和方法出口等信息。每个方法从调用到执行完成,就是栈帧从入栈到出栈的过程。
有两类异常:① 线程请求的栈深度大于虚拟机允许的深度抛出 StackOverflowError。② 如果 JVM 栈容量可以动态扩展,栈扩展无法申请足够内存抛出 OutOfMemoryError(HotSpot 不可动态扩展,不存在此问题)。
38、实际开发中应用场景哪里用到了模板方法
其实很多框架中都有用到了模板方法模式
数据库访问的封装、Junit单元测试、servlet中关于doGet/doPost方法的调用等等
39、import java和javax有什么区别
tech.souyunku.com/EasonJim/p/…
40、构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。
更多Java 面试题80道
创建socket通讯的步骤?
Java 中 sleep 方法和 wait 方法的区别?
程序计数器(线程私有)
什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?
迭代器 Iterator 是什么?
线程的 sleep()方法和 yield()方法有什么区别?
Java 中能创建 volatile 数组吗?
java中equals方法的用法以及==的用法
如何创建一个json对象?
如何判断对象是否是垃圾?
抽象工厂模式和原型模式之间的区别?
在 Java 程序中怎么保证多线程的运行安全?
volatile 修饰符的有过什么实践?
Java中各种数据默认值
说说Java 垃圾回收机制
有没有可能两个不相等的对象有有相同的 hashcode?
synchronized 和 Lock 有什么区别?
什么是Vector
对象的访问定位有哪几种方式?
equals 和 == 的区别?#
什么是ThreadPoolExecutor?
invokedynamic 指令是干什么的?
synchronized、volatile、CAS 比较
Iterator 怎么使用?有什么特点?
被引用的对象就一定能存活吗?
列出一些你常见的运行时异常?
Servlet生命周期内调用的方法过程?
阐述静态变量和实例变量的区别。
类加载器双亲委派模型机制?
抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
如何判断一个对象是否存活
Int与integer的区别
Servlet的生命周期?
怎么唤醒一个阻塞的线程
虚拟DOM的优劣如何?
双亲委派模型是什么?
静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
JVM 出现 fullGC 很频繁,怎么去线上排查问题
JVM 内存区域
Parallel Old 收集器(多线程标记整理算法)
对象分配内存是否线程安全?
当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?
Serial 与 Parallel GC 之间的不同之处?
为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?
redux异步中间件之间的优劣?
类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?
Hibernate中Session的load和get方法的区别是什么?
说一下堆内存中对象的分配的基本策略
Java 中如何将字符串转换为整数?
讲讲什么情况下会出现内存溢出,内存泄漏?
乐观锁和悲观锁的理解及如何实现,有哪些实现方式?
线程与进程的区别?
Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?
用代码演示三种代理
stackoverflow错误,permgen space错误
分代收集算法
同步方法和同步块,哪个是更好的选择?
Java 中的编译期常量是什么?使用它又什么风险?
Java死锁以及如何避免?
日期和时间:
XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
依赖注入和工程模式之间有什么不同?
Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)
如何修改tomcat的端口号?
Java有没有goto?
Java 内存分配与回收策率以及 Minor GC 和 Major GC
简述Hibernate常见优化策略。
Statement与preparedStatement区别
什么是DAO模式?
如果不背 Java面试题的答案,肯定面试会挂!