发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~

本人发现网上虽然有不少Java相关的面试题,但第一未必全,第二未必有答案,第三虽然有答案,但未必能在面试中说,所以在本文里,会不断收集各种面试题,并站在面试官的立场上,给出我自己的答案。

如果不背 Java面试题的答案,肯定面试会挂!

这套Java面试题大全,希望对大家有帮助哈~

博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的

1、Java 8 为什么要将永久代(PermGen)替换为元空间(MetaSpace)呢?

整个永久代有一个 JVM 本身设置固定大小上线,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,并且永远不会出现java.lang.OutOfMemoryError。你可以使用 -XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

2、如何自定义线程线程池?

先看ThreadPoolExecutor(线程池)这个类的构造参数

构造参数参数介绍:

corePoolSize 核心线程数量maximumPoolSize 最大线程数量keepAliveTime 线程保持时间,N个时间单位unit 时间单位(比如秒,分)workQueue 阻塞队列threadFactory 线程工厂handler 线程池拒绝策略
代码示例:
package com.lijie;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class Test001 {public static void main(String[] args) {//创建线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue < > (3));for (int i = 1; i <= 6; i++) {TaskThred t1 = new TaskThred("任务" + i);//executor.execute(t1);是执行线程方法executor.execute(t1);}//executor.shutdown()不再接受新的任务,并且等待之前提交的任务都执行完再关闭,阻塞队列中的任务不会再执行。executor.shutdown();}}class TaskThred implements Runnable {private String taskName;public TaskThred(String taskName) {this.taskName = taskName;}public void run() {System.out.println(Thread.currentThread().getName() + taskName);}}

3、类初始化的情况有哪些?

遇到 new、getstatic、putstatic 或 invokestatic 字节码指令时,还未初始化。典型场景包括 new 实例化对象、读取或设置静态字段、调用静态方法。

对类反射调用时,还未初始化。

初始化类时,父类还未初始化。

虚拟机启动时,会先初始化包含 main 方法的主类。

使用 JDK7 的动态语言支持时,如果 MethodHandle 实例的解析结果为指定类型的方法句柄且句柄对应的类还未初始化。

口定义了默认方法,如果接口的实现类初始化,接口要在其之前初始化。

其余所有引用类型的方式都不会触发初始化,称为被动引用。被动引用实例:① 子类使用父类的静态字段时,只有父类被初始化。② 通过数组定义使用类。③ 常量在编译期会存入调用类的常量池,不会初始化定义常量的类。

接口和类加载过程的区别:初始化类时如果父类没有初始化需要初始化父类,但接口初始化时不要求父接口初始化,只有在真正使用父接口时(如引用接口中定义的常量)才会初始化。

4、Java里有哪些引用类型?

1、 强引用 这种引用属于最普通最强硬的一种存在,只有在和 GC Roots 断绝关系时,才会被消灭掉。

2、 软引用 软引用用于维护一些可有可无的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。可以看到,这种特性非常适合用在缓存技术上。比如网页缓存、图片缓存等。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java 虚拟机就会把这个软引用加入到与之关联的引用队列中。

3、 弱引用 弱引用对象相比较软引用,要更加无用一些,它拥有更短的生命周期。当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。弱引用拥有更短的生命周期,在 Java 中,用 java.lang.ref.WeakReference 类来表示。它的应用场景和软引用类似,可以在一些对内存更加敏感的系统里采用。

4、 虚引用 这是一种形同虚设的引用,在现实场景中用的不是很多。虚引用必须和引用队列(ReferenceQueue)联合使用。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。实际上,虚引用的 get,总是返回 null。

5、JAVA8 与元数据

在 Java8 中, 永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入nativememory, 字符串池和类的静态变量放入 java 堆中, 这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

6、引用计数法

在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用, 即他们的引用计数都不为 0, 则说明对象不太可能再被用到,那么这个对象就是可回收对象。

7、String str=”aaa”,与String str=new String(“aaa”)一样吗?

1、 不一样的。因为内存分配的方式不一样。

2、 第一种,创建的”aaa”是常量,jvm都将其分配在常量池中。

3、 第二种创建的是一个对象,jvm将其值分配在堆内存中。

8、Xml的java解析有几种方式?

Java API解析xml主要有两种方式;

Dom解析:一次性加载整个文档,生成树形结构。在生成的文档对象中,可以对节点进行增删改查的操作。当xml文本当较小的时候,可以使用dom解析。

Sax解析:基于事件的解析方式,解析速度比较快,解析的文档大小理论上是没有限制的。

还有一些开源的技术可以解析xml,dom4j或者jdom。

9、为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用?

当一个线程需要调用对象的 wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的 notify()方法。同样的,当一个线程需要调用对象的 notify()方法时,它会释放这个对象的锁,以便其他在等待的线程就可以得到这个对象锁。由于所有的这些方法都需要线程持有对象的锁,这样就只能通过同步来实现,所以他们只能在同步方法或者同步块中被调用。

10、JVM新生代中为什么要分为Eden和Survivor?

如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,所以需要分为Eden和Survivor。Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。设置两个Survivor区最大的好处就是解决了碎片化,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)

11、你了解过哪些垃圾收集器?

年轻代 Serial 垃圾收集器(单线程,通常用在客户端应用上。因为客户端应用不会频繁创建很多对象,用户也不会感觉出明显的卡顿。相反,它使用的资源更少,也更轻量级。) ParNew 垃圾收集器(多线程,追求降低用户停顿时间,适合交互式应用。) Parallel Scavenge 垃圾收集器(追求 CPU 吞吐量,能够在较短时间内完成指定任务,适合没有交互的后台计算。)

老年代 Serial Old 垃圾收集器 Parallel Old垃圾收集器 CMS 垃圾收集器(以获取最短 GC 停顿时间为目标的收集器,它在垃圾收集时使得用户线程和 GC 线程能够并发执行,因此在垃圾收集过程中用户也不会感到明显的卡顿。)

12、你是如何调用 wait() 方法的?使用 if 块还是循环?为什么?

处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。

wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:

synchronized (monitor) { // 判断条件谓词是否得到满足 while(!locked) { // 等待唤醒 monitor.wait(); } // 处理其他的业务逻辑 }

13、Java 中,如何计算两个日期之间的差距?

程序

http://javarevisited.blogspot.sg/2015/07/how-to-find-number-of-days-between-two-dates-in-java.html

14、JVM 类加载机制

JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化。

加载

加载是类加载过程中的一个阶段, 这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对象, 作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个 Class 文件获取,这里既可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。

验证

这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

准备

准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:

实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080, 将 v 赋值为 8080 的 put static 指令是程序被编译后, 存放于类构造器方法之中。

但是注意如果声明为:

public static final int v = 8080;

在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

解析

解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的

public static int v = 8080;

实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080, 将 v 赋值为 8080 的 put static 指令是程序被编译后, 存放于类构造器方法之中。但是注意如果声明为:

在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

解析

解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的

public static final int v = 8080;

在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

解析

解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的:

1、 CONSTANT_Class_info

2、 CONSTANT_Field_info

3、 CONSTANT_Method_info

等类型的常量。

符号引用

符号引用与虚拟机实现的布局无关, 引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中。

直接引用

直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。

初始化

初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。

类构造器

初始化阶段是执行类构造器方法的过程。方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子方法执行之前,父类的方法已经执行完毕, 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。

注意以下几种情况不会执行类初始化:

1、 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。

2、 定义对象数组,不会触发该类的初始化。

3、 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。

4、 通过类名获取 Class 对象,不会触发类的初始化。

5、 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。

6、 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作。

15、Sql中delete与truncate的区别

DELETE:

选择性地删除数据,当删除整张表的数据时效率较低;只能删除整张表的数据,但是效率高于使用DELETE语句;不能选择性地删除。当truncate执行删除之后,自动生成的主键值重新从默认值开始。

16、poll() 方法和 remove() 方法的区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

17、一个线程运行时发生异常会怎样?

如果异常没有被捕获该线程将会停止执行。Thread.UncaughtExceptionHandler是用于处理未捕获异常造成线程突然中断情况的一个内嵌接口。当一个未捕获异常将造成线程中断的时候,JVM 会使用 Thread.getUncaughtExceptionHandler()来查询线程的 UncaughtExceptionHandler 并将线程和异常作为参数传递给 handler 的 uncaughtException()方法进行处理。

18、游标的创建步骤?

1、 定义游标

2、 打开游标

3、 操作游标数据

4、 关闭游标

19、MyBatis中使用#和$书写占位符有什么区别?

#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;

将传入的数据直接显示生成在SQL中。注意:使用将传入的数据直接显示生成在SQL中。注意:使用

占位符可能会导致SQL注射攻击,能用#的地方就不要使用,写orderby子句的时候应该用,写orderby子句的时候应该用

而不是#。、

20、一个类文件中能否有多个类?有什么要求?

可以。但是只能有一个public类,而且public修饰的类名与文件名必须一致

1、说一下Java对象的创建过程

1、 类加载检查:虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。2)分配内存:在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择那种分配方式由 Java 堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。选择以上2种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器的算法是"标记-清除",还是"标记-整理"(也称作"标记-压缩"),值得注意的是,复制算法内存也是规整的。

2、 在创建对象的时候有一个很重要的问题,就是线程安全,因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全:CAS+失败重试:CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。TLAB:为每一个线程预先在Eden区分配一块儿内存,JVM在给线程中的对象分配内存时,首先在TLAB分配,当对象大于TLAB中的剩余内存或TLAB的内存已用尽时,再采用上述的CAS进行内存分配

3、 初始化零值:内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

4、 设置对象头:初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是那个类的实例、如何才能找到类的元数据信息、对象的哈希吗、对象的 GC 分代年龄等信息。这些信息存放在对象头中。另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。

5、 执行 init 方法:在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始, 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

22、Java 中 LinkedHashMap 和 PriorityQueue 的区别是什么?

PriorityQueue 保证最高或者最低优先级的的元素总是在队列头部,但是 LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue 时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。

23、ThreadPoolExecutor饱和策略有哪些?

如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任时,ThreadPoolTaskExecutor 定义一些策略:

1、 ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。

2、 ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务。您不会任务请求。但是这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略。

3、 ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。

4、 ThreadPoolExecutor.DiscardOldestPolicy: 此策略将丢弃最早的未处理的任务请求。

24、可达性分析

为了解决引用计数法的循环引用问题, Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象, 不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

25、成员变量与局部变量的区别有那些?

1、 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;成员变量和局部变量都能被final所修饰;

2、 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存

3、 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。

4、 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。

26、HashMap 的长度为什么是2的幂次方

为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树中的算法。

这个算法应该如何设计呢?

我们首先可能会想到采用%取余的操作来实现。但是,重点来了:“取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。

那为什么是两次扰动呢?

这样就是加大哈希值低位的随机性,使得分布更均匀,从而提高对应数组存储下标位置的随机性&均匀性,最终减少Hash冲突,两次就够了,已经达到了高位低位同时参与运算的目的;

27、谈谈JVM中,对类加载器的认识

类加载器是JVM的组成部分之一。将字节码文件加载进JVM。

类加载分为四部分:

1、 BootStrapClassLoader,即跟类加载器,加载java运行时所需的类,如String,Integer等存在${java_home}/jre/lib/rt.jar包类的所有类。

2、 ExtensionClassLoader,扩展类加载器,加载一些扩展类,即${java_home}/jre/lib/ext/*.jar包

3、 AppClassLoader,系统加载类,加载自定义的类,级classpath下的所有类

4、 ClassLoader 抽象类加载器:用户自定义的类加载器,用户定义的类加载器都要继承次ClassLoader

5、 Jvm默认采用的是双亲委派类加载机制,即先加载父类在加载子类,对上面四个类加载器采用自顶向下加载

28、你对线程优先级的理解是什么?

1、 每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OS dependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。

2、 java的线程优先级调度会委托给操作系统去处理,所以与具体的操作系统优先级有关,如非特别需要,一般无需设置线程优先级。

29、构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载。

30、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?

1、 部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。

2、 如果对象的大小大于Eden的二分之一会直接分配在old,如果old也分配不下,会做一次majorGC,如果小于eden的一半但是没有足够的空间,就进行minorgc也就是新生代GC。

3、 minor gc后,survivor仍然放不下,则放到老年代

4、 动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代

31、64 位 JVM 中,int 的长度是多数?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。

32、线程的状态

![87_2.png][87_2.png]

1、 新建(new):新创建了一个线程对象。

2、 就绪(可运行状态)(runnable):线程对象创建后,当调用线程对象的 start()方法,该线程处于就绪状态,等待被线程调度选中,获取cpu的使用权。

3、 运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

4、 阻塞(block):处于运行状态中的线程由于某种原因,暂时放弃对 CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被 CPU 调用以进入到运行状态。

阻塞的情况分三种:

1、 等待阻塞:

运行状态中的线程执行 wait()方法,JVM会把该线程放入等待队列(waitting queue)中,使本线程进入到等待阻塞状态;

2、 同步阻塞:

线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用),,则JVM会把该线程放入锁池(lock pool)中,线程会进入同步阻塞状态;

3、 其他阻塞:

通过调用线程的 sleep()或 join()或发出了 I/O 请求时,线程会进入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入就绪状态。

4、 死亡(dead)(结束):

线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

33、计算机网络有几层?

1、 应用层

2、 表示层

3、 会话层

4、 传输层

5、 网络层

6、 数据链路层

7、 物理层

8、 (物理层是最底层,应用层是最高层)

34、模块化编程与热插拔

OSGi 旨在为实现 Java 程序的模块化编程提供基础条件,基于 OSGi 的程序很可能可以实现模块级的热插拔功能,当程序升级更新时,可以只停用、重新安装然后启动程序的其中一部分,这对企业级程序开发来说是非常具有诱惑力的特性。

OSGi 描绘了一个很美好的模块化开发目标,而且定义了实现这个目标的所需要服务与架构,同时也有成熟的框架进行实现支持。但并非所有的应用都适合采用 OSGi 作为基础架构,它在提供强大功能同时,也引入了额外的复杂度,因为它不遵守了类加载的双亲委托模型。

35、我们能自己写一个容器类,然后使用 for-each 循环码?

可以,你可以写一个自己的容器类。如果你想使用 Java 中增强的循环来遍历,你只需要实现 Iterable 接口。如果你实现 Collection 接口,默认就具有该属性。

36、单例防止反射漏洞攻击

private static boolean flag = false; private Singleton() { if (flag == false) { flag = !flag; } else { throw new RuntimeException("单例模式被侵犯!"); } } public static void main(String[] args) { }

37、工作中常用的 JVM 配置参数有哪些?

Java 8 为例

日志

1、 -XX:+PrintFlagsFinal,打印JVM所有参数的值

2、 -XX:+PrintGC,打印GC信息

3、 -XX:+PrintGCDetails,打印GC详细信息

4、 -XX:+PrintGCTimeStamps,打印GC的时间戳

5、 -Xloggc:filename,设置GC log文件的位置

6、 -XX:+PrintTenuringDistribution,查看熬过收集后剩余对象的年龄分布信息

内存设置

1、 -Xms,设置堆的初始化内存大小

2、 -Xmx,设置堆的最大内存

3、 -Xmn,设置新生代内存大小

4、 -Xss,设置线程栈大小

5、 -XX:NewRatio,新生代与老年代比值

6、 -XX:SurvivorRatio,新生代中Eden区与两个Survivor区的比值,默认为8,即Eden:Survivor:Survivor=8:1:1

7、 -XX:MaxTenuringThreshold,从年轻代到老年代,最大晋升年龄。CMS 下默认为 6,G1 下默认为 15

8、 -XX:MetaspaceSize,设置元空间的大小,第一次超过将触发 GC

9、 -XX:MaxMetaspaceSize,元空间最大值

10、 -XX:MaxDirectMemorySize,用于设置直接内存的最大值,限制通过 DirectByteBuffer 申请的内存

11、 -XX:ReservedCodeCacheSize,用于设置 JIT 编译后的代码存放区大小,如果观察到这个值有限制,可以适当调大,一般够用即可

设置垃圾收集相关

1、 -XX:+UseSerialGC,设置串行收集器

2、 -XX:+UseParallelGC,设置并行收集器

3、 -XX:+UseConcMarkSweepGC,使用CMS收集器

4、 -XX:ParallelGCThreads,设置Parallel GC的线程数

5、 -XX:MaxGCPauseMillis,GC最大暂停时间 ms

6、 -XX:+UseG1GC,使用G1垃圾收集器

CMS 垃圾回收器相关

1、 -XX:+UseCMSInitiatingOccupancyOnly

2、 -XX:CMSInitiatingOccupancyFraction,与前者配合使用,指定MajorGC的发生时机

3、 -XX:+ExplicitGCInvokesConcurrent,代码调用 System.gc() 开始并行 FullGC,建议加上这个参数

4、 -XX:+CMSScavengeBeforeRemark,表示开启或关闭在 CMS 重新标记阶段之前的清除(YGC)尝试,它可以降低 remark 时间,建议加上

5、 -XX:+ParallelRefProcEnabled,可以用来并行处理 Reference,以加快处理速度,缩短耗时

G1 垃圾回收器相关

1、 -XX:MaxGCPauseMillis,用于设置目标停顿时间,G1 会尽力达成

2、 -XX:G1HeapRegionSize,用于设置小堆区大小,建议保持默认

3、 -XX:InitiatingHeapOccupancyPercent,表示当整个堆内存使用达到一定比例(默认是 45%),并发标记阶段就会被启动

4、 -XX:ConcGCThreads,表示并发垃圾收集器使用的线程数量,默认值随 JVM 运行的平台不同而变动,不建议修改

参数查询官网地址:

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

建议面试时最好能记住 CMS 和 G1的参数,特点突出使用较多,被问的概率大

38、面向对象的特征有哪些方面?

面向对象的特征主要有以下几个方面:

1、 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

2、 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Java与模式》或《设计模式精解》中关于桥梁模式的部分)。

3、 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

4、 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的(就像电动剃须刀是A系统,它的供电系统是B系统,B系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A系统只会通过B类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1)、方法重写(子类继承父类并重写父类中已有的或抽象的方法);2)、对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

39、是否了解连接池,使用连接池有什么好处?

数据库连接是非常消耗资源的,影响到程序的性能指标。连接池是用来分配、管理、释放数据库连接的,可以使应用程序重复使用同一个数据库连接,而不是每次都创建一个新的数据库连接。通过释放空闲时间较长的数据库连接避免数据库因为创建太多的连接而造成的连接遗漏问题,提高了程序性能。

40、JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用

当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM主要动机在于可以指定最大堆大小,通过压缩OOP 可以节省一定的内存。通过-XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。

更多Java 面试题80道

01、创建socket通讯的步骤?

02、Java 中 sleep 方法和 wait 方法的区别?

03、程序计数器(线程私有)

04、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?

05、迭代器 Iterator 是什么?

06、线程的 sleep()方法和 yield()方法有什么区别?

07、Java 中能创建 volatile 数组吗?

08、java中equals方法的用法以及==的用法

09、如何创建一个json对象?

10、如何判断对象是否是垃圾?

11、抽象工厂模式和原型模式之间的区别?

12、在 Java 程序中怎么保证多线程的运行安全?

13、volatile 修饰符的有过什么实践?

14、Java中各种数据默认值

15、说说Java 垃圾回收机制

16、有没有可能两个不相等的对象有有相同的 hashcode?

17、synchronized 和 Lock 有什么区别?

18、什么是Vector

19、对象的访问定位有哪几种方式?

20、equals 和 == 的区别?#

21、什么是ThreadPoolExecutor?

22、invokedynamic 指令是干什么的?

23、synchronized、volatile、CAS 比较

24、Iterator 怎么使用?有什么特点?

25、被引用的对象就一定能存活吗?

26、列出一些你常见的运行时异常?

27、Servlet生命周期内调用的方法过程?

28、阐述静态变量和实例变量的区别。

29、类加载器双亲委派模型机制?

30、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

31、如何判断一个对象是否存活

32、Int与integer的区别

33、Servlet的生命周期?

34、怎么唤醒一个阻塞的线程

35、虚拟DOM的优劣如何?

36、双亲委派模型是什么?

37、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

38、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?

39、JVM 出现 fullGC 很频繁,怎么去线上排查问题

40、JVM 内存区域

41、Parallel Old 收集器(多线程标记整理算法)

42、对象分配内存是否线程安全?

43、当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

44、Serial 与 Parallel GC 之间的不同之处?

45、为什么线程通信的方法 wait(), notify()和 notifyAll()被定义在 Object 类里?

46、redux异步中间件之间的优劣?

47、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式?

48、Hibernate中Session的load和get方法的区别是什么?

49、说一下堆内存中对象的分配的基本策略

50、Java 中如何将字符串转换为整数?

51、讲讲什么情况下会出现内存溢出,内存泄漏?

52、乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

53、线程与进程的区别?

54、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?

55、用代码演示三种代理

56、stackoverflow错误,permgen space错误

57、分代收集算法

58、同步方法和同步块,哪个是更好的选择?

69、Java 中的编译期常量是什么?使用它又什么风险?

70、Java死锁以及如何避免?

71、日期和时间:

72、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

73、依赖注入和工程模式之间有什么不同?

74、Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)

75、如何修改tomcat的端口号?

76、Java有没有goto?

77、Java 内存分配与回收策率以及 Minor GC 和 Major GC

78、简述Hibernate常见优化策略。

79、Statement与preparedStatement区别

80、什么是DAO模式?

如果不背 Java面试题的答案,肯定面试会挂!

这套Java面试题大全,希望对大家有帮助哈~

博主已将以下这些面试题整理成了一个Java面试手册,是PDF版的

分类: 源码分享 标签: 暂无标签

评论

暂无评论数据

暂无评论数据

目录

目录