JavaSE基础及面试

JavaSE整理总结

结构:

问题(问题关键字)

回答

问题关键字可以取消,以后目录和题目结构要认真组织。

Java的知识体系包含哪些内容?

拓展

拓展

如何打开远程桌面连接?

通过“运行”对话框打开

  • 按下Windows键+R,打开“运行”对话框。
  • 输入“mstsc”并按回车,这将打开远程桌面连接窗口。

VisualStudio中的多行注释快捷键是什么?

ctrl+shift+/

二进制

-1的原码、补码、反码分别是什么?

-1的原码是:10000000 00000000 00000000 00000001

-1的补码是:11111111 11111111 11111111 11111111

-1的反码是:11111111 11111111 11111111 11111110

补码和反码之间的关系是什么?

补码 = 反码 + 1

数据单位

1B是多少b?1KB是多少B?1MB是多少KB?1GB是多少MB?1TB是多少GB?1M是多少?

1B=8b

1KB=1024B

1MB=1024KB

1GB=1024MB

1TB=1024GB

1M是1024KB,其实就是1MB。

字符编码

ASCII可以用来存储汉字吗?

ASCII不能用来存储汉字,因为ASCII使用1个字节来存储字符,

而这也导致它的存储范围小,所以汉字这种字符数量较多的语言,是无法存储在ASCII中的。

A的ASCII码是多少?a的ASCII码是多少?0的ASCII码是多少?

A的ASCII码是65;

a的ASCII码是多少97;

0的ASCII码是48。

ASCII使用几个字节来存储字符?ANSI使用几个字节来存储字符?Unicode使用几个字节来存储字符?

ASCII使用1个字节。

ANSI和Unicode都使用2个字节。

UTF-8和Unicode是什么关系???

Unicode是一种字符编码标准,而UTF-8是Unicode的一种具体编码方式。

Unicode是字符的抽象集合,定义了字符的唯一代码点,但它并不规定这些字符应该如何存储或传输。

UTF-8是Unicode的一种实现方式,它规定了如何将Unicode字符(即代码点)转换为字节序列。

可以把Unicode看作是一本全球通用的字符书籍,而UTF-8是这本书的印刷方式之一,

或者Unicode作为汉语,UTF-8作为字典。

它告诉计算机如何把这些字符的数字标识符编码成实际的字节数据。

ISO-8859-1可以用来表示汉字吗???

不可以,ISO-8859-1也叫西欧字符集。

IDEA快捷键

主方法的快捷键是什么?

psvm + Enter

单行注释的快捷键是什么?

ctrl + /

多行注释的快捷键是什么?

ctrl +shift+/

文档注释的快捷键是什么?

/** + enter

打印输出语句的快捷键是什么?

sout

删除一行的快捷键是什么?

ctrl + y

复制一行的快捷键是什么?

ctrl + d

代码格式化的快捷键是什么?

ctrl +alt +L

重命名的快捷键是什么?

shift + f6

多行输入的快捷键是什么?

alt +鼠标左键

上下移动的快捷键是什么?

shift + alt + 方向上下键

自动生成变量名的快捷键是什么?

ctrl + alt + v

JavaSE基础

Java

为什么说 Java 语言“编译与解释并存”?

高级编程语言按照程序的执行方式分为两种:

编译型:编译型语言open in new window 会通过编译器open in new window将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。

解释型:解释型语言open in new window会通过解释器open in new window一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。

而Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class 文件),这种字节码必须由 Java 解释器来解释执行。

Java和C++有什么区别?

  1. 都是面向对象的语言,都支持封装、继承和多态
  2. Java不提供指针来直接访问内存,程序内存更加安全
  3. Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是 接口可以多继承。
  4. Java有自动内存管理机制,不需要程序员手动释放无用内存。

Java语言采用何种编码方案?有何特点?

Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一 个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

JDK

Oracle JDK 和 OpenJDK 有什么区别?

Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一 次;
OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是 OpenJDK的一个实现,并不是完全开源的;
Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎 相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企 业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳 定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程 序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的 性能;
Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过 更新到最新版本获得支持来获取最新版本;
Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。

JDK、JRE、JVM分别是什么?三者之间的关系是什么?

JDK,全拼Java Development Kit,Java开发工具包

JRE,全拼Java Runtime Enviroment,Java运行环境

JVM,全拼Java Virtual Machine,Java虚拟机,真正运行Java程序的地方。

JDK中包含JRE;JRE中包含JVM。如果只需要运行Java程序,则JRE就可以满足条件。

面向对象

面向对象的三大特征分别是什么?

封装、继承、多态。

面向对象五大基本原则是什么?

单一职责原则SRP(Single Responsibility Principle);

开放封闭原则OCP(Open-Close Principle);

里式替换原则LSP(the Liskov Substitution Principle LSP);

依赖倒置原则DIP(the Dependency Inversion Principle DIP);

接口分离原则ISP(the Interface Segregation Principle ISP)。

什么是单一职责原则?

单一职责原则SRP(Single Responsibility Principle):

类的功能要单一。

什么是开放封闭原则?

开放封闭原则OCP(Open-Close Principle):

一个模块对于拓展是开放的,对于修改是封闭的。

什么是里式替换原则?

里式替换原则LSP(the Liskov Substitution Principle LSP):

子类可以替换父类出现在父类能够出现的任何地方。

什么是依赖倒置原则?

依赖倒置原则DIP(the Dependency Inversion Principle DIP):

高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

什么是接口分离原则?

接口分离原则ISP(the Interface Segregation Principle ISP):

设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。

什么是继承、封装、多态?

封装: 使用private关键字,让对象私有,防止无关的程序去使用。

继承: 继承某个类,使子类可以使用父类的属性和方法。关键字是extends。

多态: 同一个行为,不同的子类具有不同的表现形式。父类的引用变量指向子类对象,可以使用父类类型的引用来调用子类对象中重写的方法。编译期是父类类型,运行期是子类类型。

多态有什么好处?

简化代码的同时,提高代码的维护性和扩展性。

封装是如何体现安全性的?

封装利用private修饰符实现属性私有化,

提供gettersetter方法以便调用者使用。

利用访问权限修饰符来隐藏类中的某些信息,并提供方法供外部调用者使用。

接口之间的继承和类之间的继承有什么区别?

Java不支持类的多继承,但是接口之间可以多继承。

Java数据操作

数据结构

valueOf()的参数是什么?返回值是什么?

将String字符串解析为Integer类型。

parseInt()的参数是什么?返回值是什么?

将String字符串解析为int类型。

intValue()的参数是什么?返回值是什么?

将Integer类型转换为int类型。

什么是自动类型转换和强制类型转换?

小容量类型转为大容量类型会进行自动类型转换,大容量类型转为小容量类型时,需要进行强制类型转换。

强制类型转换可能会出现什么问题?

大容量类型转为小容量类型,存在溢出或精度降低,可能会造成数据丢失。

当数组需要扩容时,如何处理?

因为数组的长度是固定的,创建时必须指明长度,需要扩容时,只能用新数组代替。

Array.toString()方法的参数是什么?返回值是什么?

Array.toString()的参数是我们希望打印的数组,

没有返回值。

常见的数据结构有哪些?

数组、链表、队列、栈

FILO和FIFO分别指的是哪一种数据结构?

FILO是栈,FIFO是队列。

Java数据类型

基本数据类型有几种?分别是什么?

四类八种。

四类:整型、浮点型、布尔型、字符型。

八种:byte、short、int、lang、float、double、char、boolean。

引用数据类型有几种?分别是什么?

接口、对象、数组。

数组本质上是对象。

浮点数的默认类型是什么?整数的默认类型是什么?

浮点数默认为double类型,整数默认为int类型。

使用long、double、float类型的数据时,需要注意什么?

要在数据末尾加上L、D、d、f、F符号。

long的范围是?short的范围是?int的范围是?byte的范围是?

long:-2^63 ~ 2^63;

short:-2^15 ~ 2^15;

int:-2^31 ~ 2^31;

byte:-2^7 ~ 2^7

boolean的范围是?boolean在数组中的默认类型是什么?

true,false

boolean在数组中的默认类型是false。

int类型数据在数组中的默认类型是什么?double类型数据在数组中的默认类型是什么?

0

0.0

数组

数组是基本数据类型还是引用类型?

数组本质是一个对象,不是基本数据类型。

数组的三种声明方式分别是什么?

int[] a = new int[5];

int[] b=new int[]{1,2,3,4,5,6,7};

int[] c={1,2,3,4};

数组的存储空间有什么特点?

数组中每个元素空间是连续的。

数组的下标从几开始?(数组)

从0开始,所以数组的最大索引=数组长度-1

数组和链表哪一个查询效率更高?哪一个插入效率更高?

数组的查询效率更高,链表插入效率更高。

如何反转数组的顺序?

可以使用循环遍历数组,定义两个指针在数组的两端,交换它们的值,逐步向中间靠拢,即可实现数组的反转。

如何从一个数组中删除指定的元素?

答:可以使用两个指针,一个指向当前元素,一个指向新数组的位置,遍历数组,将不等于指定元素的元素复制到新数组,然后将新数组的长度作为结果返回。

如何找到数组中的第K个最大元素?

答:可以使用快速选择算法,类似于快速排序的思想,通过不断地划分数组,直到找到第K个最大元素。

如何判断一个数组是否为循环数组?

答:可以遍历数组,对于每一个元素,计算其下一个位置的索引,判断元素是否符合循环的条件。

如何合并两个有序数组?

答:可以使用双指针法,分别从两个数组的开头开始遍历,根据大小关系依次放入新的数组中。

如何找到数组中的三个数,使其和最接近给定的目标值?

答:可以先对数组进行排序,然后使用双指针法,在排序后的数组中遍历,计算三个数的和与目标值的差的绝对值,找到最接近的组合。

如何统计数组中出现次数超过一半的元素?

答:可以使用摩尔投票算法,遍历数组,如果当前计数为0,则将当前元素设为候选元素,否则如果当前元素与候选元素相等,则计数加1,否则计数减1。

如何找到数组中的众数(出现次数最多的元素)?

答:可以使用哈希表来统计每个元素出现的次数,然后遍历哈希表找到出现次数最多的元素。

包装类

什么是自动装箱和自动拆箱??

Integer i = 10;

int i = new Integer(10)

所有包装类的父类是哪个类?

所有包装类的父类都是Number类。

八种基本数据类型对应的包装类型分别是什么?

int的包装类型是Integer类;

long的包装类型是Long类;

boolean的包装类型是Boolean类;

byte的包装类型是Byte类;

short的包装类型是Short类;

float的包装类型是Float类;

double的包装类型是Double类;

char的包装类型是Character类;

如何将字符串转换为对应的包装类?

可以使用包装类的valueOf()方法将字符串转换为对应的包装类,例如:String str = "10"; Integer obj = Integer.valueOf(str);

如何将包装类转换为对应的字符串?

可以使用包装类的toString()方法将包装类转换为对应的字符串,例如:Integer obj = new Integer(10); String str = obj.toString();

如何比较两个包装类的值是否相等?

可以使用equals()方法或==操作符来比较两个包装类的值是否相等,例如:Integer obj1 = new Integer(10); Integer obj2 = new Integer(10); boolean isEqual = obj1.equals(obj2) 或者 obj1 == obj2;

自动拆箱和自动装箱是什么意思?

自动拆箱是指将包装类的对象自动转换为基本类型的过程,例如:Integer obj = new Integer(10); int num = obj; 自动装箱是指将基本类型自动转换为包装类的对象,例如:int num = 10; Integer obj = num;

包装类和基本类型在内存中的存储位置有什么区别?

基本类型的变量存储在栈内存中,而包装类对象存储在堆内存中。d

包装类的缓存是什么意思?

在范围较小的数值范围中,Java的包装类会使用缓存来提高性能,例如Integer类会缓存-128至127之间的整数对象。

在使用包装类时如何避免空指针异常?

可以使用包装类的valueOf()方法,该方法如果传入的字符串为null,则会返回null值。例如:String str = null; Integer obj = Integer.valueOf(str);

String赋值给包装类对象时会发生什么?

当将一个String类型的值赋给包装类对象时,会自动调用包装类的valueOf()方法将字符串转换为包装类对象。

包装类有哪些方法可以将字符串转换为对应的基本类型?

包装类提供了许多方法将字符串转换为对应的基本类型,例如:Boolean类的parseBoolean()、Byte类的parseByte()、Integer类的parseInt()等。

包装类的valueOf()方法和xxxValue()方法有什么区别?

valueOf()方法将基本类型或字符串转换为包装类对象,xxxValue()方法将包装类对象转换为对应的基本类型。

包装类对象如何比较大小?

可以使用包装类的compareTo()方法来比较大小,或者将包装类对象转换为基本类型后再进行比较。

包装类的作用是什么?

包装类的主要作用是将基本类型转换为对象,以便于在需要使用对象的场景中对数据进行操作,同时也提供了一些常用的方法和功能。

如何判断一个变量的类型是否是包装类?

可以使用instanceof关键字来判断一个变量的类型是否是包装类,例如:if (obj instanceof Integer) { // do something }

int、Integer、String之间是如何相互转换的?

intInteger:自动装箱,或使用Integer类的静态方法valueOf

Integerint:自动拆箱,或使用Integer对象的intValue方法。

intString:使用String类的静态方法valueOf

Stringint:使用Integer类的静态方法parseInt。(需要注意的是,如果字符串内容不是有效的整数表示,Integer.parseInt会抛出NumberFormatException。)

IntegerString:直接使用toString方法。

StringInteger:使用Integer类的静态方法valueOf

运算符

算数运算符有哪些?

逻辑运算符有哪些?

常用的逻辑运算符有六种:短路与&&、短路或||、逻辑与&、逻辑或|、逻辑非!、逻辑异或^

位运算符有哪些?

常用的位运算符有六种: &与、|或、^异或、~取反、>>右移、>>>无符号右移。

关系运算有哪些?

赋值运算符有哪些?

短路或与逻辑或的区别是什么?

使用短路或进行运算时,结果一旦确定,就会直接返回,不会再向后计算结果。

0^0的结果是什么?

结果是0。

0^1的结果是什么?

结果是1。

当异或运算(XOR)中,两个对应的位相同时,结果为多少?

两个对应的位相同时,结果为0。

Java虚拟机

拓展

成员变量、局部变量、类变量存储在内存的什么地方?

首先要明确,三者存储在不同的内存位置:

成员变量存储在对象的堆内存中,每个对象都有一份独立的成员变量副本。

局部变量存储在虚拟机栈内存中,方法执行时会在虚拟机栈上创建对应的局部变量空间,方法执行结束后会自动释放。

类变量(静态变量)存储在**方法区(也称为永久代或元数据区)**中,它属于类的属性,在 JVM 加载类的过程中被初始化,整个程序运行期间只有一份。

JVM

JDK8的内存结构是什么样的?

JDK8的内存结构包括程序计数器、虚拟机栈、本地方法栈、堆内存、方法区、运行时常量池、直接内存七部分。

1.程序计数器(Program Counter Register):记录当前线程执行的字节码指令地址。

2.虚拟机栈(VM Stack):存储方法调用的栈帧,包括局部变量表、操作数栈等信息。

3.本地方法栈(Native Method Stack):为虚拟机执行本地方法服务。

4.堆内存(Heap):存放对象实例,被所有线程共享。

5.方法区(Method Area):存储已加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

6.运行时常量池(Runtime Constant Pool):存放编译器生成的各种字面量和符号引用。

7.直接内存(Direct Memory):与堆内存不同,直接内存通过 Native 函数库直接分配内存,不受 Java 堆大小的限制。

虚拟机栈的作用是什么?

每个线程都有自己的虚拟机栈,虚拟机栈的生命周期与线程相同,其内部保存栈帧(StackFrame)。栈帧对应每次Java方法的调用。JVM对Java栈的操作,就是对栈帧的压栈和出栈。

堆的作用是什么?

堆也叫Heap,用于存放Java对象实例,它是JVM内存模型中最大的一块,被所有线程共享,在JVM启动时创建。

程序计数器的作用是什么?

程序计数器也叫PC,每个线程都有自己的程序计数器(一个线程同时只有一个方法在执行),PC会存储当前线程正在执行的Java方法的JVM指令地址。

线程之间的方法区是共享的还是私有的?

所有线程共享同一个方法区。

方法区是什么?

方法区也叫MethodArea,所有线程共享一个方法区,存储已加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

运行时常量池的作用是什么?

存放编译器生成的各种字面量和符号引用。

本地方法栈的作用是什么?

本地方法栈用于支持对本地方法的调用,每个线程都会创建自己的本地方法栈。

JVM在哪些情况下会退出?

当程序正常运行结束后,JVM会退出。

当程序出现异常,但是没有捕获异常时,JVM会退出。

当程序调用System.out()的时候,JVM会退出。

当强制杀死进程的时候,JVM会退出。

垃圾回收

JVM中的垃圾收集器(GC)有哪些?

JVM中的垃圾收集器主要包括7种,即Serial,Serial Old,ParNew,Parallel Scavenge,Parallel Old以及CMS,G1收集器。

什么是垃圾回收机制?

垃圾回收(Garbage Collection)是JVM垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。

仅仅回收无引用对象所实际占用的空间,有对象引用的不回收。

GC如何判断对象回收的时机?

早期是引用计数法,现在常用的是可达性分析算法。

GC的早期策略,是通过引用计数法判断对象回收的时机。

在对象中添加一个引用计数器,每当有一个地方 引用它时,计数器值就加一;

当引用失效时,计数器值就减一;

计数器为零的对象就是不可能再被使用的对象。

引用计数算法(Reference Counting)虽然占用了一些额外的内存空间来进行计数,但它的原理简单,判定效率也很高,在大多数情况下它都是一个不错的算法。

但是引用计数器法的缺点也很明显:无法有效识别循环引用。

当前主流的内存管理子系统,都是通过可达性分析(Reachability Analysis)算法来判定对象是否存活的。

可达性分析算法的基本思路,是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

其中,GC Roots包括以下几种:

虚拟机栈(栈帧中的局部变量表)中引用的对象;

方法区中类静态属性引用的对象;

方法区中常量引用的对象;

本地方法栈中Native方法引用的对象;

常见的垃圾回收算法有哪些?

常见的垃圾回收算法有标记-清除算法、标记-复制算法、标记-整理算法。

什么是标记-清除算法?

标记-清除算法:

算法分为“标记”和“清除”两个阶段:

首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象;

也可以反过来,标记存活的对象,统一回收所有未被标记的对象。

标记过程就是判定对象是否属于垃圾的过程。

标记-清除算法的缺点是什么?

标记-清除算法的缺点主要有两个:

a、执行效率不稳定:当Java堆中包含大量对象,且其中大部分需要被回收时,必须进行大量标记和清除的动作,导致标记和清除两个动作的消耗随对象数量增长而增长。
b、内存空间的碎片化问题。标记、清除之后会产生大量不连续的内存碎片,空间碎片太多,可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的、连续的、内存而不得不提前触发另一次垃圾收集动作。

标记-清除算法和标记-整理算法有什么区别?

前者是非移动式的,后者是移动式的。

什么是标记复制算法?

标记-复制算法:

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

什么是标记-整理算法?

标记-整理算法:

标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。

标记-清除算法与标记-整理算法的本质差异在于前者是一种非移动式的回收算法,而后者是移动式的。

Java语法

类的结构由哪些部分组成?

变量、方法、构造方法、块、内部类

构造方法可以重载吗?

构造方法可以重载,但是不能重写。

构造方法在什么时候调用?

构造方法在使用new关键字实例化对象时自动调用。

当我们定义了一个有参的构造方法,Java还会默认提供无参的构造方法吗?

不会

接口

接口相关的关键字有哪些?

接口相关的关键字有两个:interface和implements。

一个类可以实现多少个接口?一个接口可以继承多少个父接口?

一个类可以实现多个接口。

接口可以多继承,所以一个接口可以继承多个父接口。

Java8中的接口与之前有什么不同?

Java8中,接口中引入了默认方法和静态方法。

1.默认方法(Default Methods)

默认方法允许在接口中提供实现。这意味着当一个类实现该接口时,如果它没有实现某个方法,那么它会继承接口中提供的默认实现。

2.静态方法(Static Methods)

静态方法可以直接在接口中定义,并且它们不能被实现类直接调用,只能通过接口名来调用。

public interface MyInterface {
    // 默认方法
    default void defaultMethod() {
        System.out.println("This is a default method.");
    }

    // 抽象方法
    void abstractMethod();
}

public class MyClass implements MyInterface {
    @Override
    public void abstractMethod() {
        System.out.println("Implementation of abstract method.");
    }

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.abstractMethod();
        myClass.defaultMethod(); // 调用默认方法
    }
}
public interface MyInterface {
    // 静态方法
    static void staticMethod() {
        System.out.println("This is a static method.");
    }

    // 抽象方法
    void abstractMethod();
}

public class MyClass implements MyInterface {
    @Override
    public void abstractMethod() {
        System.out.println("Implementation of abstract method.");
    }

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.abstractMethod();
        MyInterface.staticMethod(); // 通过接口名调用静态方法
    }
}

可以使用实现类直接调用接口中的静态方法吗?

不可以,接口中的静态方法必须通过接口名来调用。

抽象类

抽象类的关键字是什么?

抽象类的关键字是abstract。

抽象类有什么特性?

抽象类不能用来创建对象。子类继承抽象类后,必须实现其中所有抽象方法。

抽象方法有什么特性?

抽象方法只有声明,没有方法体。

抽象类中一定要有抽象方法吗?

注意,抽象类可以没有抽象方法,但有抽象方法,则一定是抽象类。

接口和抽象类有什么区别?

接口是没有构造方法的,而抽象类有自己的构造方法;

接口中只能有抽象方法(Java8有了变化),但是抽象类中可以有抽象方法和普通方法;

接口中的成员变量均是常量(省略了public static final),抽象类中的成员变量可以是常量,也可以是变量。

内部类

内部类有多少种?(内部类)

四种:成员内部类、局部内部类、静态内部类、匿名内部类。

局部内部类不要用。

静态内部类能访问外部类的非静态变量吗?(内部类)

不可以

非静态内部类能访问外部类的静态变量吗?(内部类)

可以

如何创建一个静态内部类?

静态内部类的创建不需要依赖外部类的创建,

静态内部类能使用外部类的非静态成员变量和方法吗?

不能使用外部类的非static成员变量和方法。

final、finally、finalize

final修饰的变量有什么特性?final修饰的方法有什么特性?final修饰的类有什么特性?

final变量是不可变的常量,一旦创建,则不可修改。

如果是引用类型的变量,则不能再指向另一个对象。

注意:不能再指向另一个对象,指的是地址不可改变,并不是不能修改对象中的属性。

final修饰的方法不能被子类重写。

final修饰的类不能被继承,其中所有方法也默认被final修饰。

final可以修饰构造方法吗?

final不能修饰构造方法。

finally有什么特性?

finally一般用于try-catch-finally中,用来释放资源、关闭连接如JDBC连接、文件对象等。

什么情况下,finally中的代码不会执行?

注意:如果执行System.exit(1);,finally中的代码也可能不会被执行。

finally块中的return语句会如何影响方法的返回值?

如果在finally块中使用了return语句,会覆盖在try块中使用的return语句,即以finally块中的return值为准。(真的假的,还能覆盖返回值?)

finalize是什么?

finalize是java.lang.Object中的一个方法,现在已经不推荐使用。

它用于保证对象在被垃圾回收之前,完成特定资源的回收。

static

如何访问静态变量?

使用类名.的方式访问静态变量和静态方法。

static代码块有什么作用?

因为当JVM加载类时,static代码块会且只会被执行一次。

所以static代码块可用于优化程序性能。

实例代码块是在什么阶段执行?

实例代码块在每次创建对象时,自动执行。

static方法中可以使用this和super的关键字吗?

static方法中不能使用this和super关键字。

父类代码块和子类代码块中的执行顺序是什么?

父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法。

重写

重写的条件有哪些?

参数一致:方法名、参数列表、返回值类型必须全部一致。

访问权限:子类方法的访问权限不能小于父类的对应方法。

@Override注解:可以不用添加,但最好添加。

有哪些方法不能重写?

在Java中,静态方法和构造方法不能重写。

泛型

泛型相关的字母有哪些?(泛型)

泛型相关的字母包括T、K、V、E。

访问权限修饰符

default和protected有什么区别?

在不同包的子类中,可以访问protected修饰的变量,但是不能修饰default修饰的变量。

不同包的其他类能访问到本类中,访问权限修饰符为缺省的元素吗?

不能

同包中的其他类能访问到本类中,访问权限修饰符为缺省的元素吗?

不同包的其他类能访问本类中,访问权限修饰符为private元素吗?

不能

访问权限修饰符private、缺省、protected、public之间的权限排列关系从大到小是什么?

public→protected→缺省→private

不同包的其他类能够访问到本类中,访问权限修饰符为protected元素吗?

不能

不同包的子类能够访问到本类中,访问权限修饰符为protected元素吗?

this

this的用法有哪些?

this的用法在java中大体可以分为3种:

  1. 普通的直接引用,this相当于是指向当前对象本身;
  2. 形参与成员名字重名,用this来区分;
  3. 引用本类的构造函数。

使用this引用本类的构造函数时,需要注意什么?

使用this引用本类的构造函数时,需要把这代码放在构造函数的第一条位置。

super

super的用法有哪些?

  1. 普通的直接引用与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。

  2. 子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

  3. 引用父类构造函数

super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。

this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

反射

反射

什么是反射?

反射:在运行过程中,通过程序都能获取类的属性和方法,以及动态调用其方法和动态获取信息。

反射机制的优缺点是什么?

优点是可以在运行时动态地加载和使用类,增加了代码的灵活性;

缺点是性能消耗大,代码可读性较差,不易于维护。

如何通过反射创建对象?

可以使用Class对象的newInstance()方法或Constructor类的newInstance()方法来创建对象。

如何通过反射调用方法?

可以使用Method类的invoke()方法来调用方法,传入要调用的对象和方法的参数。

如何通过反射获取类的属性?

可以使用Class对象的getField()方法或getDeclaredField()方法来获取类的公有或私有属性。

如何通过反射设置类的属性?

可以使用Field类的set()方法来设置属性的值,传入要设置的对象和属性的新值。

如何通过反射获取类的构造方法?

可以使用Class对象的getConstructor()方法或getDeclaredConstructor()方法来获取类的公有或私有构造方法。

如何通过反射调用类的构造方法创建对象?

可以使用Constructor类的newInstance()方法来调用构造方法创建对象,传入构造方法的参数。

如何通过反射获取类的注解?

可以使用Class对象的getAnnotation()方法来获取类的注解。

如何通过反射处理泛型?

Java中的泛型是在编译期进行类型擦除的,通过反射可以获取泛型的实际类型参数。

如何通过反射操作数组?

可以使用Array类的newInstance()方法创建数组,使用Array类的get()方法和set()方法来访问和修改数组元素。

如何通过反射设置访问权限?

可以使用AccessibleObject类的setAccessible()方法来设置为true,允许访问私有成员。

反射机制在框架开发中有何应用?

反射机制在框架开发中可以实现灵活的配置、插件式开发、AOP等功能实现。

如何通过反射获取类的父类和接口?

可以使用Class对象的getSuperclass()方法获取父类,使用getInterfaces()方法获取接口数组。

如何判断一个类是否包含某个方法?

可以使用Class对象的getMethods()方法获取类的所有方法,再逐个比较方法名。

如何获取某个方法的参数类型?

可以使用Method类的getParameterTypes()方法获取方法的参数类型数组。

反射机制是线程安全的吗?

不是,反射机制的各个方法都是非线程安全的,必须注意在多线程环境下的使用。

获取Class对象

字节码对象(Class对象)是什么时候创建的?

当类加载器(ClassLoader)将class文件加载进内存中时,会为每个类都创建一个对应的字节码对象。

如何获取Class的对象?

一共有三种方法可以获取Class的对象:

  1. 使用类名.class
  2. 通过对象调用getClass()
  3. 使用类的全限定类名和forName()方法

如何通过类名获取Class的对象?

//1:使用类名.class
Class<String> stringClass = String.class;

如何通过对象调用getClass()类获取Class的对象?

//2:通过对象调用 getClass();
String str = "abc";
Class<? extends String> aClass = str.getClass();

如何使用类的全限定类名获取Class的对象?

//3:使用类的全限定类名 java.lang.String
Class<?> aClass1 = Class.forName("java.lang.String");

在三种获取Class对象的方法中,最常用的是哪一种?

最常用的是第三种方法。

即:利用Class.forName()方法和类的全限定类名来获得Class的对象。

包装类型提供的TYPE常量有什么作用?

TYPE代表了对应包装类型的 Class 对象。

如:

Integer.TYPE:代表 int 类型的 Class 对象。

Double.TYPE:代表 double 类型的 Class 对象。

如何获得基本数据类型字节码对象?

JVM已经提前内置好了基本数据类型的字节码对象,

我们可以通过Class class= int.class;来获得基本数据类型的字节码对象。

int.classInteger.TYPE有什么区别?

如何获得包装类型的字节码对象?

包装类型中提供了常量TYPE,它代表了对应包装类型的字节码对象。

Class<Integer> type = Integer.TYPE;

反射创建对象

如何使用反射创建对象?

使用反射创建对象需要三个步骤:

1.获取类的字节码对象(即Class实例)。

如:Class.forName()

2.获取构造器对象。

如:getConstructor()

3.通过构造器对象创建指定类的对象。

如:newInstance()

注意:如果构造器是私有的,还需要设置可访问。

即:constructor.setAccessible(true);

Class<?> aClass = Class.forName("cn.ConstructorNewObject.Person");
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();

出现此类报错(cn.sycoder.ConstructorNewObject.Person with modifiers "private")的原因是什么?如何解决?

出现cn.sycoder.ConstructorNewObject.Person with modifiers "private"报错的原因在于:我们使用了私有的构造器,但同时没有设置可访问。

解决办法:添加设置可访问的代码:constructor.setAccessible(true);

newInstance()的参数是什么?返回值是什么?

newInstance()没有参数,

返回值是指定的类实例。

这是我们利用反射创建指定类的实例的重要方法。

Constructor

以下四种方法

getConstructor()

getConstructors()

getDeclaredConstructor()

getDeclaredConstructors()

的参数是什么?返回值是什么?

四种方法的参数都是指定类的class实例,

它们的区别在于返回值的不同,

它们都会返回指定类的构造器,但是

含Declared表示可以返回类的私有方法,

含Constructor表示返回单个构造器对象,所以返回值为单个构造器对象,

含Constructors表示返回多个构造器对象,所以返回值为构造器对象组成的数组。

//获取构造器对象
public Constructor<T> getConstructor(Class<?>... parameterTypes);
//获取全部构造器对象
public Constructor<?>[] getConstructors();
//获取全部构造器包括私有
public Constructor<?>[] getDeclaredConstructors();

如何获得指定Class实例(如User类的Class实例userClass)的全部非私有构造器?

利用getConstructors()方法。

Constructor<?>[] constructors = userClass.getConstructors();

如何获得指定Class实例(如User类的Class实例userClass)的全部构造器?

利用getDeclaredConstructors()方法。

Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();

如何获得指定Class实例(如User类的Class实例userClass)的某个私有构造器?

利用getDeclaredConstructor()方法。

Constructor<?> constructor = userClass.getDeclaredConstructor();

如何获得指定Class实例(如User类的Class实例userClass)的某个非私有构造器?

利用getConstructor()方法。

Constructor<?> constructor = userClass.getConstructor();

反射操作方法

如何使用反射操作实例方法?

首先,我们需要用反射创建对象。

1.获取字节码对象。

如:Class.forName()

2.获取构造器对象。

如:getConstructor()

3.使用构造器对象获得实例。

如:newInstance()

4.通过实例获得方法对象。

如:getMethod()

5.利用反射调用方法。

如:invoke()

具体流程如下:

Class<?> aClass = Class.forName("cn.sycoder.MethedDemo.MethodDemo");
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();
Method eat = aClass.getMethod("eat");
Object invoke = eat.invoke(o);

如何使用反射操作静态方法?

因为静态方法不属于对象,而属于类本身,所以不需要通过构造器对象获得实例,可以直接调用getMethod()方法来获得指定的静态方法,且我们使用invoke()方法时,不需要对象作为参数。

Method getName = aClass.getMethod("getName", String.class);
Object object = getName.invoke(null, "上云");
System.out.println(object);

getMethod()的参数是什么?

以上方获取静态方法的代码为例:

getName()表示该方法的方法名;

String.class表示对应的class类。

反射操作字段

如何利用反射操作字段?

Class<?> aClass = Class.forName("cn.sycoder.FiledDemo.FiledDemo");
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();
Field age = aClass.getDeclaredField("age");
age.setAccessible(true);

age.set(o,19);

Object o1 = age.get(o);
System.out.println(o1);

类加载器加载 Properties

如何使用绝对路径加载 Properties?

//使用绝对路径
Properties properties = new Properties();
FileInputStream in = new FileInputStream(path);
properties.load(in);
System.out.println(properties);

如何使用相对路径(从根目录开始)加载 Properties?

Properties properties = new Properties();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream(path);
properties.load(resourceAsStream);
System.out.println(properties);

如何使用相对路径(相对于我们使用的类的文件夹开始)加载 Properties?

Properties properties = new Properties();
InputStream inputStream = Test.class.getResourceAsStream(path);
properties.load(inputStream);
System.out.println(properties);

异常

异常体系

Java中的异常是如何划分的?Java中的异常体系是什么样的?

最顶层是Throwable类,它是所有异常的根类,它的两个子类是Exception和Error。

而Java中的异常主要分为:CheckedException、UncheckedExcepion、Error三类。

受检异常是?

受检异常(Checked Exception):

继承自Exception类,编译器强制要求必须处理的异常,可以使用try-catch块捕获或者在方法上使用throws关键字声明抛出。

非受检异常是?

非受检异常(Unchecked Exception):

非受检异常包括运行时异常(RuntimeException)及其子类,通常由程序错误导致,不需要显式捕获或声明抛出,可以选择性地处理,编译器不会强制要求处理这些异常。

错误是?

错误(Error):

错误是Java中所有异常和错误的超类Throwable的另一个子类(与Exception并列)。通常由严重的系统问题导致,无法恢复或处理。

RuntimeExceptionException是什么关系?

RuntimeExceptionUncheckedException的子类。而?????

被抛出(throw)或捕获(catch)的前提条件是什么?

被抛出(throw)或捕获(catch)的前提条件是:该对象必须是Throwable类或其子类的实例。

在catch块中如何处理多个异常?

可以使用多个catch块来处理不同的异常类型,或者使用一个catch块来处理多个异常类型,使用多个“|”分隔异常类型。

throw和throws有什么区别?

throw关键字用于主动抛出一个异常对象,可以在任何地方使用。

throws关键字用于在方法上声明可能抛出的异常类型,告诉调用者需要处理这些异常。

如何实现一个自定义异常类?

可以通过继承Exception或者RuntimeException类来创建自定义异常类,并添加相应的构造方法和其他属性。

Java中的异常处理机制是什么?

Java的异常处理机制使用try-catch-finally语句块来处理异常。try块用于包裹可能抛出异常的代码,catch块用于捕获和处理异常,finally块用于定义无论是否异常都需要执行的代码。

描述一下try-catch-finally语句块的执行流程

当try块中的代码出现异常时,会立即跳转到对应的catch块进行处理。如果发现catch块中可以处理该异常,会执行相应的代码,然后继续执行finally块中的代码;如果没有匹配的catch块,当前方法会立即结束,异常会被抛给上一级调用者或者由虚拟机处理。不论是否发生异常,finally块中的代码总会被执行。

异常处理有哪些原则?

异常处理的原则主要有三个:

  1. 仅捕获那些你能处理的异常;
  2. 尽量不要捕获太宽泛的异常类型;
  3. 使用合适的日志记录异常。

checkedExceptionuncheckedException

常见的受检异常(CheckedException)有哪些?

IOException :在文件操作中可能会发生的输入/输出异常。

SQLException:在数据库操作中可能会发生的SQL异常。

ClassNotFoundException:在动态加载类时,找不到指定的类。

常见的非受检异常(UncheckedException)有哪些?

NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException、ArithmeticException、ClassCastException。

NullPointerException:空指针异常,当尝试访问空引用对象时抛出。

ArrayIndexOutOfBoundsException:数组索引越界异常,数组下标越界时抛出。

IllegalArgumentException:非法参数异常,当方法接收到非法参数时抛出。

ArithmeticException:算术异常,当发生除零或溢出等算术错误时抛出。

ClassCastException:类转换异常,当尝试将对象强制转换为不兼容类型时抛出。

不需要显式的捕获或声明抛出的是checkedException还是uncheckedException

在Java中,不需要显式捕获或声明抛出的异常是uncheckedException

必须显式的捕获或声明抛出的是checkedException还是uncheckedException

必须显式的捕获或声明抛出的是checkedException

编译器强制要求必须处理的异常是checkedException还是uncheckedException

必须处理的异常是checkedException,如果不显式的捕获或声明抛出,编译将无法通过。

RuntimeException可以选择捕获或声明抛出吗?

可以,RuntimeException即UncheckedException,一般不强制要求,但也可以声明抛出或捕获处理。

NullPointerException属于checkedException还是uncheckedException

空指针异常属于uncheckedException,因为空指针异常不需要显式的捕获或声明抛出。

IOException属于checkedException还是uncheckedException

IOException属于checkedException,因为如果不显式的捕获或声明抛出IOException,编译将无法通过。

FileNotFoundException属于checkedException还是uncheckedException

FileNotFoundException属于checkedException,因为如果不显式的捕获或声明抛出FileNotFoundException,编译将无法通过。

ClassNotFoundException属于checkedException还是uncheckedException

ClassNotFoundException属于uncheckedException,因为ClassNotFoundException不需要显式的捕获或声明抛出。

NumberFormatException属于checkedException还是uncheckedException

NumberFormatException属于uncheckedException,因为NumberFormatException不需要显式的捕获或声明抛出。

NoSuchMethodException属于checkedException还是uncheckedException

NoSuchMethodException属于uncheckedException,因为NoSuchMethodException不需要显式的捕获或声明抛出。

ArrayOutOfBoundsException属于checkedException还是uncheckedException?

ArrayOutOfBoundsException属于uncheckedException,因为ArrayOutOfBoundsException不需要显式的捕获或声明抛出。

ClassCastException属于checkedException还是uncheckedException?

ClassCastException属于uncheckedException,因为ClassCastException不需要显式的捕获或声明抛出。

SQLException属于checkedException还是uncheckedException?

SQLException属于checkedException

ArithmeticException属于checkedException还是uncheckedException

ArithmeticException属于uncheckedException

Error

常见的Error有哪些?

OutOfMemoryError:内存溢出错误,当尝试使用更多内存超出JVM可分配的限制时抛出。

StackOverflowError:栈溢出错误,当方法调用的堆栈太深而导致栈溢出时抛出。

VirtualMachineError:虚拟机错误

NoSuchMethodError:当尝试调用不存在的方法时抛出。

一般哪些情况下会出现StackOverflowError的问题?

  1. 方法的无限递归调用

  2. 方法调用链过长

  3. 对象循环引用

一般哪些情况下会出现OutOfMemoryError的问题?

  1. 创建的对象过多,超出堆内存的限制

  2. 创建的线程过多

  3. 加载的class文件过多

断言

什么是断言(assertion)和断言异常?

断言用于在程序中进行验证和调试,通常用于在开发过程中检查程序的正确性。断言异常是一种特殊的异常,如java.lang.AssertionError,用于表示断言失败。

集合

Java集合体系

Java的集合体系是什么?重点

Map接口和Collection接口是所有集合框架的父接口。

Collection接口的子接口包括:Queue接口、Set接口和List接口。

Map接口的实现类主要有:HashMap、TreeMap、Hashtable、 ConcurrentHashMap以及Properties等。

Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等。

List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等。

Map、List和Set的区别是什么?重点

Map:

  1. 键值对集合,存储键、值和之间的映射。
  2. Key无序,唯一;
  3. value不要求有序,允许重复。

List:

  1. 有序(元素存入集合的顺序和取出的顺序一致)容器,元素都有索引
  2. 元素可以重复,
  3. 可以插入多个null元素。

Set:

  1. 无序(存入和取出顺序有可能不一致)容器,
  2. 不可以存储重复元素,
  3. 只允许存入一个null元素,必须保证元素唯一性。

List接口常用的实现类有?

List接口常用的实现类有 ArrayList、LinkedList 和 Vector。

Set接口常用的实现类有?

Set接口常用实现类有 HashSet、 LinkedHashSet 以及 TreeSet。

Map接口的常用实现类有?

Map接口的常用实现类有HashMap、TreeMap、HashTable、LinkedHashMap、 ConcurrentHashMap。

哪些集合类是线程安全的?

  1. Vector
  2. Stack
  3. Hashtable
  4. Enumeration

List

get()的参数是什么?返回值是什么?

set()的参数是什么?返回值是什么?

remove()的参数是什么?返回值是什么?

subList()的参数是什么?返回值是什么?

Collection

size()的参数是什么?返回值是什么?

isEmpty()的参数是什么?返回值是什么?

contains()的参数是什么?返回值是什么?

是否包含某一个元素

iterator()的参数是什么?返回值是什么?

toArray()的参数是什么?返回值是什么?

add()的参数是什么?返回值是什么?

remove()的参数是什么?返回值是什么?

containsAll()的参数是什么?返回值是什么?

是否包含另一个集合

addAll()的参数是什么?返回值是什么?

clear()的参数是什么?返回值是什么?

hashCode()的参数是什么?返回值是什么?

Map

Properties类实现的是Map接口还是List接口?

Map接口

ArrayList

ArrayList的底层数据结构是?(重点)

ArrayList的底层数据结构是Object数组。

JDK1.8中,ArrayList的初始化机制和扩容机制是什么?

在JDK1.8中,ArrayList的初始化机制属于懒加载机制:一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组
当当前元素数量超过数组长度时,会创建一个新的更大长度的数组,并将原有元素复制到新数组中
扩容长度为原来的1.5倍

Vector和ArrayList的区别是什么?

Vector 使用了 Synchronized 来实现线程同步,是线程安全的。但也因此,ArrayList 在性能方面要优于 Vector。

ArrayList 和 Vector 都会动态调整容量:

Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。

ArrayList的扩容机制是什么?

ArrayList 扩容每次会增加 50%。

ArrayList相比LinkedList的优势是什么?劣势是什么?

ArrayList的随机查询效率高于LinkedList,因为ArrayList中的元素是有序的,可以直接按照索引进行查询;而LinkedList需要根据指针一个一个检索。

但是ArrayList的随机插入和删除效率较低,因为每次进行插入和删除操作时,都需要根据顺序对元素进行调整,而LinkedList可以直接对指针进行操作,从而高效率的完成插入和删除操作。

LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

ArrayList类的扩容机制是什么?

1.5倍扩容。

ArrayList类的初始化机制是什么?

如果创建的对象为空数组,则只有第一次调用add方法时,才会真正初始化。

Vector

Vector的底层数据结构是?

Vector的底层数据结构和ArrayList相同,也是Object数组。

为什么Vector类是线程安全的?

因为Vector类中,所有方法都用synchronized关键字修饰。

Vector的扩容机制是什么?

2倍扩容。

LinkedList

LinkedList的底层数据结构是?

LinkedList的底层数据结构是双向循环链表。

LinkedList是线程安全的吗?

不是。

HashMap

HashMap 的长度有什么特点??重点

HashMap的长度一般都是2的幂次方。

HashMap的默认初始化长度为多少?

16。

什么是哈希冲突?重点

当两个不同的输入值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)。

HashMap的初始化机制和扩容机制是什么?重点

HashMap 默认的初始化大小为16,之后每次扩充,容量都变为原来的2倍。

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

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

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

HashMap中是如何存储数据的?

HashMap类:以键值形式存储数据。

HashMap中的键可以重复吗??

HashMap中的键不能重复。

HashMap中的键和值可以为NULL吗?

可以,可以有多个为NULL的值,但是HashMap中只能有一个键为NULL。

HashMap的底层结构是什么样的?

HashMap底层使用哈希数组+链表/红黑树的结构,

哈希数组的默认长度为16。

当链表长度为8且哈希数组的长度大于64时,链表会自动转换为红黑树。

HashMap的扩容机制是什么?什么是链化?什么是树化?

扩容时机和负载因子有关。

当HashMap中的元素数量超过负载因子(0.75)与数组长度的乘积时,HashMap会重新调整数组大小,并将原有元素重新分布到新的数组中。

链化:

向HashMap中插入新元素时,如果该位置已经存在元素(也就是发生哈希冲突),则以链表的形式存储这两个元素。

树化:

当链表长度为8,数组长度>=64时,HashMap会将链表转换为红黑树,以提高查询效率,并且还会在树上节点小于6时再次链化成为链表

HashMap中,链表的树化是不可逆的吗?

在HashMap中,链表的树化并不是不可逆的,当红黑树中的节点小于6时,HashMap会重新将链表转化为红黑树。

HashMap中的key的hashCode和equals的作用是什么?

HashMap中,key的hashCode用于确定key在数组中的存储位置,equals用于判断两个key是否相等。

hashCode和equals保证了HashMap可以根据key准确地找到对应的value。

put()的参数是什么?返回值是什么?

添加键值对

remove()的参数是什么?返回值是什么?

删除对应的键值对,返回其中的值

clear()的参数是什么?返回值是什么?

清空容器

isEmpty()的参数是什么?返回值是什么?

判断容器是否为空

containsKey()的参数是什么?返回值是什么?

判断是否包含对应的键

containsValue()的参数是什么?返回值是什么?

判断是否包含对应的值

get()的参数是什么?返回值是什么?

根据键获得对应的值

size()的参数是什么?返回值是什么?

统计键值对数目

ConcurrentHashMap

HashMap和ConcurrentHashMap有什么区别?

ConcurrentHashMap是线程安全的,而HashMap线程不安全。

HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。

ConcurrentHashMap是如何实现线程安全的?

ConcurrentHashMap通过分段锁技术实现线程安全。

什么是分段锁技术?为什么分段锁技术的并发性能更高?

分段锁技术将整个Hash桶进行了分段segment,每个segment上都有对应的锁。

增加了锁的粒度,提高了并发性能。

HashSet

HashSet的底层数据结构是?

HashSet的底层数据结构是基于 HashMap 实现的,底层采用 HashMap 来保存元素。

HashSet的值存放于HashMap的key上,HashMap的value统一为PRESENT。

HashSet添加元素时,如何判断元素是否重复?

HashSet会通过hashCode方法来判断,

首先通过hashCode方法来计算元素的哈希值,

注意:哈希值不同的元素一定不同,但是哈希值相同的元素也不一定相同。

当哈希值相同时,HashSet才会进一步调用equals方法进行进一步判断。

LinkedHashSet

LinkedHashSet是?

LinkedHashSet 是HashSet的子类,并实现了Set接口。迭代时会按照元素的插入顺序进行。

LinkedHashSet存储的是唯一的元素,这些元素没有键和值的区分,只是简单地存储在集合中。

LinkedHashSet内部实际上是通过LinkedHashMap来实现的,其中元素作为LinkedHashMap的键,而值则使用一个统一的对象(通常是PRESENT常量)来填充。

LinkedHashMap

LinkedHashMap是?

LinkedHashMap是HashMap的子类,除了具有HashMap的所有特性外,还维护了一个双向链表来记录元素的插入顺序或访问顺序。

默认情况下,LinkedHashMap按照元素的插入顺序进行迭代。但可以通过构造函数参数来指定是否按访问顺序(最近访问的元素会移到链表的末尾)进行迭代。

HashTable

HashTable的底层数据结构是?

数组+链表

HashTable是如何实现线程安全的?

使用synchronized关键字。

HashMap和HashTable有什么区别?

HashMap 是非线程安全的,而 HashTable 是线程安全的。

HashMap 允许键和值都可以为 null,而 HashTable 不允许。

HashMap 是通过 Iterator 进行迭代,而 HashTable 是通过 Enumeration 进行迭代。

HashMap 是 JDK 1.2 引入的新集合类,而 HashTable 是早期的集合类,现在通常建议使用 HashMap 替代 HashTable

TreeSet

向TreeSet中添加元素前,需要进行什么准备?为什么?

向TreeSet中添加元素前,必须先实现Comparable接口,重写compareTo方法。

因为TreeSet会对存储的元素进行排序,需要指定排序规则。

TreeMap

TreeMap的底层原理是什么?

TreeMap是基于红黑树实现的有序映射数据结构。

什么是自然排序和定制排序?

自然排序:根据元素的自然顺序进行排序,例如数字的升序、字符串的字典序等。

定制排序:根据用户定义的Comparator进行排序。

Stack

Stack是线程安全的吗?

Stackl继承于Vector,所以Stack也是线程安全的。

push()的参数是什么?返回值是什么?(Stack类)

pop()的参数是什么?返回值是什么?(Stack类)

peek()的参数是什么?返回值是什么?(Stack类)

查看栈顶元素。

Queue

BlockingQueue是?

BlockingQueue接口是Java集合框架的一部分,来自java.util.concurrent包,主要用于实现生产者-消费者模式。我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。

BlockingQueue的实现类有?

Java提供了集中 BlockingQueue的实现,如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等。

Queue 中 poll()和 remove()有什么区别?

相同点:都返回第一个元素,并在队列中删除返回的对象。

不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出NoSuchElementException 。

Collections工具类

Collections.synchronizedList(new ArrayList())的作用是什么?

获取线程安全的集合

Collections.synchronizedCollection(Collection)的作用是什么?

获取线程安全的集合

多线程场景下如何使用 ArrayList?

ArrayList 不是线程安全的,如果遇到多线程场景,需要通过 Collections 的 synchronizedList方法将其转换成线程安全的容器后再使用。

1	List<String> synchronizedList = Collections.synchronizedList(list);
2	synchronizedList.add("aaa");
3	synchronizedList.add("bbb");
4
5	for (int i = 0; i < synchronizedList.size(); i++) {
6	System.out.println(synchronizedList.get(i));
7	}

常用类

Object

Object类有什么特性?(Object类)

Object类是所有类的父类。

toString()的参数是什么?返回值是什么?(Object类)

getClass()的参数是什么?返回值是什么?(Object类)

获取类的字节码对象。

hashCode()的参数是什么?返回值是什么?(Object类)

finalize()的参数是什么?返回值是什么?(Object类)

当对象不被引用时,gc会不定时调用此方法回收该对象。

equals()的参数是什么?返回值是什么?(Object类)

String

String 属于基础数据类型吗?

当然不是,String属于引用数据类型。

第⼀次执行String str = new String(“abc”)创建了几个对象,为什么?

第一次执行 String str = new String(“abc”) 创建了两个对象:
一个是 “abc” 字符串常量,它存在于字符串常量池中。
另一个是 new String(“abc”) 创建的新的字符串对象,它存在于堆内存中。

String类的常用方法有哪些?

String类的常用方法包括length(),charAt(),concat(),substring(),indexOf(),equals(),compareTo()等。

final为String带来了哪些影响?为什么要这样设定?

因为String被final修饰,所以String是最终类,不可以被继承,不可以修改,线程安全,对String的任何修改操作都会产生新的String对象。所以修改String对象时,必须通过重新初始化的方式来完成。

主要是为了提高字符串的安全性和线程安全性。

String常量池是什么?

String常量池是一个特殊的内存区域,用于存储字符串常量,避免重复创建相同的字符串对象。

length()

charAt()

indexOf()

contains()

lastIndexOf()

substring()

toUpperCase( )/ toLowerCase( )

concat(String str)

split()

replace(char old,char new)

replace(String old,String new)

replaceAll(String regex, String replacement)

replaceFirst(String regex, String replacement)

trim()

charAt()的参数是什么?返回值是什么?

concat()的参数是什么?返回值是什么?

contains()的参数是什么?返回值是什么?

split()参数是什么?返回值是什么?

replace()有几个参数?分别是什么?

subString()有几个参数?分别是什么意义?

trim()有几个参数?分别是什么意义?

如何判断一个字符串是否以特定的前缀或后缀开头或结尾?

可以使用startsWith()判断字符串是否以特定的前缀开头,使用endsWith()判断字符串是否以特定的后缀结尾。

如何将字符串拆分成数组或将数组拼接成字符串?

可以使用split()方法将字符串拆分成数组,使用join()方法将数组拼接成字符串。

如何去除字符串中的空格或特定的字符?

可以使用trim()方法去除字符串中的前后空格,使用replace()方法替换指定的字符。

如何判断一个字符串是否包含另一个字符串?

可以使用contains()方法来判断一个字符串是否包含另一个字符串,例如:String str = "Hello World"; str.contains("Hello")。

如何将基本类型转换为对应的字符串表示?

可以使用valueOf()方法将基本类型转换为对应的字符串表示,例如:String num = String.valueOf(10);

如何将字符串转换为对应的基本类型?

可以使用parseXXX()方法将字符串转换为对应的基本类型,例如:int num = Integer.parseInt("10");

如何反转一个字符串?

可以使用StringBuilder/StringBuffer的reverse()方法来反转一个字符串,例如:StringBuilder sb = new StringBuilder("Hello"); sb.reverse();

String类中的+操作符和concat()方法有何区别?

String类中的+操作符底层实际上使用了StringBuilder/StringBuffer的append()方法来进行字符串拼接;而concat()方法直接将字符串拼接。

如何截取字符串的子串?

可以使用substring()方法来截取字符串的子串,指定起始下标和结束下标,例如:String str = "Hello World"; str.substring(6, 11);

如何将字符串转换为字符数组?

可以使用toCharArray()方法将字符串转换为字符数组,例如:String str = "Hello"; char[] charArray = str.toCharArray();

如何将字符数组转换为字符串?

可以使用String的构造方法或valueOf()方法将字符数组转换为字符串,例如:char[] charArray = {'H', 'e', 'l', 'l', 'o'}; String str = new String(charArray);

String对象的内存分配是放在栈上还是堆上?

String对象的引用放在栈上,而String对象本身存储在堆上。

如何将一个字符串转换为整数类型(int)?

可以使用Integer.parseInt()方法将字符串转换为整数类型,例如:String str = "123"; int num = Integer.parseInt(str);

如何将一个整数类型(int)转换为字符串?

可以使用String.valueOf()方法或者将整数类型与空字符串相加(+" ")来将整数类型转换为字符串,例如:int num = 123; String str = String.valueOf(num); 或者 String str = num + "";

如何判断一个字符串是否为空或者只包含空格?

可以使用isEmpty()方法或者trim()方法来判断一个字符串是否为空,例如:String str = ""; boolean isEmpty = str.isEmpty(); 或者 String str = " "; boolean isBlank = str.trim().isEmpty();

如何将一个字符串中的字符按照指定的分隔符拆分成数组?

可以使用split()方法来将一个字符串按照指定的分隔符拆分成数组,例如:String str = "Hello,World"; String[] arr = str.split(",");

如何将字符串中的字符全部替换为指定字符?

可以使用replace()方法来将字符串中的字符全部替换为指定字符,例如:String str = "Hello World"; String newStr = str.replace('o', '*');

如何将指定的字符插入到字符串指定的位置?

可以使用substring()方法和concat()方法来将指定的字符插入到字符串指定的位置,例如:String str = "Hello"; String newStr = str.substring(0, 2).concat("XX").concat(str.substring(2));

如何将字符串转换为大写或小写,并忽略字符串中的特殊字符?

可以使用toLowerCase()方法或toUpperCase()方法将字符串转换为大写或小写,并使用replaceAll()方法去除特殊字符,例如:String str = "Hello,@World!"; String lowerCase = str.replaceAll("[a-zA-Z0-9]", "").toLowerCase();

如何获取字符串中指定字符的索引位置?

可以使用indexOf()方法或lastIndexOf()方法来获取字符串中指定字符的索引位置,例如:String str = "Hello"; int index = str.indexOf('o');

如何将多个字符串拼接成一个字符串?

可以使用StringBuilder/StringBuffer的append()方法进行字符串拼接,例如:StringBuilder sb = new StringBuilder(); sb.append("Hello").append("World");

如何判断两个字符串是否相等,忽略大小写?

可以使用equalsIgnoreCase()方法来判断两个字符串是否相等,忽略大小写,例如:String str1 = "Hello"; String str2 = "hello"; boolean isEqual = str1.equalsIgnoreCase(str2);

StringBuilder和StringBuffer

StringBuilder类有什么特性?(StringBuilder类)

final修饰,不可以被继承。

StringBuilder对象底层使用char[],所以可以修改内容且不会产生新的对象。

StringBuilder对象的默认长度为16。

append()的参数是什么?返回值是什么?(StringBuilder类)

StringBuffer类有什么特性?

StringBuffer中的所有方法都有synchronized关键字修饰,所以相比StringBuilder类是线程安全的。

但是性能低。

为什么StringBuilder比StringBuffer常用?StringBuffer和StringBuilder的区别是什么?

StringBuilder比StringBuffer常用是因为StringBuilder性能更高。

两者性能差异的原因也是它们之间最大的区别之处:

因为StringBuffer中的所有方法都使用synchronized修饰,所以StringBuffer线程安全但性能低;

而StringBuilder线程不安全但是性能高。

StringBuilder的扩容规则是什么?

StringBuffer的扩容规则是什么?

StringBuilder、StringBuffer、String三者之间的执行速度由快到慢是什么排序?

StringBuilder>StringBuffer>String。

如何将String类型的字符串转换为StringBuffer或StringBuilder类型?

可以使用StringBuffer或StringBuilder的构造方法将String类型的字符串转换为StringBuffer或StringBuilder类型,例如:StringBuffer sb = new StringBuffer("Hello"); 或者 StringBuilder sb = new StringBuilder("Hello");

如何在Java中连接多个String字符串或StringBuilder字符串?

可以使用"+"运算符进行字符串的连接,或使用StringBuilder的append()方法进行字符串的连接。

StringBuffer和StringBuilder的常用方法有哪些?

StringBuffer和StringBuilder具有相似的方法,包括append()、insert()、delete()、replace()、reverse()等方法。

BigInteger

BigInteger类有什么特性?

专用于大数据运算。

BigDecimal

Random

nextInt()

nextLong()

nextBoolean()

Math

Java 中的Math.round(-1.5)等于多少?

round方法的原则:同时向正无穷方向取舍。

所以Math.round(-1.5)的结果是-1。

abs()绝对值

sqrt()平方

pow()

max/min()

random()

round()

floor/ceil()

Collections

Collection和Collections的区别是什么?

Collection 是 Java 集合框架中集合类的根接口。

Collections 是一个工具类,其中提供了各种静态方法,包含对集合进行排序、查找、同步等操作的方法。

Collections不是集合类,而是一组操作集合的工具方法。

ThreadPoolExecutor

Date

Java 8中新增的日期和时间API是哪个包?

Java 8中的日期和时间API位于java.time包中

Java中处理日期和时间的类有哪些?

Java中处理日期和时间的类主要有java.util.Date、java.util.Calendar、java.time.LocalDate、java.time.LocalDateTime等。

如何获取当前的日期和时间?

可以使用java.util.Date类的无参构造方法得到当前的日期和时间,或者使用java.time.LocalDateTime的now()方法。

如何格式化日期和时间?

可以使用java.text.SimpleDateFormat类来格式化日期和时间,通过指定格式的字符串将日期和时间转换为指定格式。

如何在Java中表示一个特定的日期?

可以使用java.util.Calendar类或java.time.LocalDate类来表示一个特定的日期。

如何计算两个日期之间的天数差距?

可以使用java.util.Calendar类或java.time.LocalDate类的方法来计算两个日期之间的天数差距,然后进行相减运算。

如何将日期转换为字符串?

可以使用java.util.Date类的toString()方法将日期对象转换为字符串,或者使用java.text.SimpleDateFormat类进行自定义格式的转换。

如何将字符串转换为日期?

可以使用java.text.SimpleDateFormat类的parse()方法将字符串转换为日期对象,需要指定匹配的日期格式。

如何在Java中进行日期的加减操作?

可以使用java.util.Calendar类或java.time.LocalDateTime类的add()方法进行日期的加减操作。

Java中日期和时间的处理在多线程环境下是否安全?

java.util.Date类和java.util.Calendar类在多线程环境下是不安全的,可以使用java.time包中的类来实现线程安全的日期和时间处理。

Java 8引入了新的日期和时间API的主要目的是什么?

Java 8引入的新的日期和时间API主要是为了解决旧的API在设计上的问题和局限性,并提供更加方便和可靠的日期和时间处理方式。

Java中如何比较两个日期是否相等?

可以使用java.util.Date类的equals()方法或者java.time.LocalDate类的isEqual()方法来判断两个日期是否相等。

Java中如何获取某个日期的年、月、日等具体信息?

可以使用java.util.Calendar类或java.time.LocalDate类的get()方法来获取某个日期的年、月、日、星期等具体信息。

Java中如何判断某个日期是星期几?

可以使用java.util.Calendar类或java.time.LocalDate类的get()方法来获取某个日期的星期几,返回值为0表示星期日,1表示星期一,依此类推。

Java中如何计算某个日期是一年中的第几天?

可以使用java.util.Calendar类或java.time.LocalDate类的get()方法来获取某个日期在年份中的天数。

Java中如何获取某个日期的下一天或上一天?

可以使用java.util.Calendar类或java.time.LocalDate类的add()方法来进行日期的加减操作,从而得到下一天或上一天的日期。

Java中如何计算两个日期之间的小时差、分钟差等时间差?

可以使用java.util.Calendar类或java.time.LocalDateTime类的方法来计算两个日期之间的小时差、分钟差等时间差。

Java中如何判断某个日期是在另一个日期之前还是之后?

可以使用java.util.Date类的before()和after()方法,或者使用java.time.LocalDate类的isBefore()和isAfter()方法来判断日期的先后关系。

Java中如何将日期设置为零点或午夜?

可以使用java.util.Calendar类或java.time.LocalDateTime类的set()方法来将日期设置为零点或午夜。

Java 8中引入的日期和时间API有什么优势?

Java 8中引入的日期和时间API(java.time包)在设计上更加简洁、易用,提供了更多的功能,同时支持线程安全。

Java中如何计算某个日期的下一个月的同一天?

可以使用java.util.Calendar类或java.time.LocalDate类的方法来计算某个日期的下一个月的同一天,需要处理月份溢出的情况。

Java 8中新增的日期和时间API有哪些常用的类?

常用的类有LocalDate、LocalTime、LocalDateTime、Duration等。

Files

Files的常用方法都有哪些?

Files.exists():检测文件路径是否存在。

Files.createFile():创建文件。

Files.createDirectory():创建文件夹。

Files.delete():删除一个文件或目录。

Files.copy():复制文件。

Files.move():移动文件。

Files.size():查看文件个数。

Files.read():读取文件。

Files.write():写入文件。

IO流

IO流

IO流相关的类在java的哪个包中?

IO流相关的类在java.io.*中。

常见的IO流有哪些?

常见的IO流:InputStream、OutputStream、Reader、Writer等。

其中常见的实现类有FileInputStream、FileOutputStream、BufferedReader、BufferedWriter。

IO流按照流向应该分为:输入流和输出流。

IO流按照数据单位应该分为:字节流和字符流。

序列化和反序列化相关IO流:ObjectOutputStream,ObjectInputStream。

四大基本流指的是什么?

四大基本流:字节输入流、字节输出流、字符输入流、字符输出流。

如果我们在使用了IO流之后,没有关闭资源,会产生什么后果?

如果不关闭资源,磁盘文件会被占用,不能删除,也不能修改,造成资源的浪费。

FileNotFoundException属于checkedException还是uncheckedExceptino?

因为FileNotFoundException需要显式捕获或声明抛出,所以它属于checkedException

IOexception属于checkedException还是uncheckedException?

因为IOexception需要显式捕获或声明抛出,所以它属于checkedException

使用缓冲区有什么意义?

缓冲区可以提高CPU的使用率,同时方便回滚写入的数据。

操作系统使用什么标志来代表磁盘文件结尾?

操作系统使用-1来作为磁盘文件结尾的标志。

当我们使用try-catch语句时,IO流的创建和初始化应该放在什么位置?

应该放在try关键字后的括号中。

NIO和普通的IO有什么不同?

大概有三处不同:

Channels Buffer(通道和缓冲区):NIO使用通道和缓冲区,性能更快

异步:线程从通道读数据到缓冲区的时候,线程还可以做其他的事情。

Selectors(选择器):选择器可以监听多个通道事件。

BIO是什么?

BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

NIO是什么?

NIO (New I/O):NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的 N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发

AIO是什么?

AIO (Asynchronous I/O):AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。

NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过
Channel(通道)通讯,实现了多路复用。

AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO
,异步 IO 的操作基于事件和回调机制。

序列化及反序列化

什么是反序列化?什么是序列化?

将文件转化为java对象,即反序列化;将java对象转化为文件,即序列化。

序列化及反序列化的必须条件是什么?

必须实现序列化接口Serializable。

将文件转化为java对象所需要的IO流是哪一个?

ObjectInputStream可以将文件转化为java对象,即反序列化。

序列化所需要的IO流是哪一个?

ObjectOutputStream可以将java对象转化为文件,即序列化。

class invalid for deserialization的问题是什么原因造成的?

出现class invalid for deserialization,是因为对没有实现序列化接口的对象进行了序列化操作。

File

File类可以表示目录吗?

File既可以表示具体的文件,也可以表示目录。

exists()的参数是什么?返回值是什么?

isFile()的参数是什么?返回值是什么?

isDirectory()的参数是什么?返回值是什么?

getName()的参数是什么?返回值是什么?

length()的参数是什么?返回值是什么?

获得文件长度(字节数)

createNewFile()的参数是什么?返回值是什么?

delete()的参数是什么?返回值是什么?

删除文件(该文件必须为空文件)

renameTo()的参数是什么?返回值是什么?

list()的参数是什么?返回值是什么?

listFiles()的参数是什么?返回值是什么?

mkdir()/mkdirs()的参数是什么?返回值是什么?

getAbsolutePath()的参数是什么?返回值是什么?

获取绝对路径

getParentFile()的参数是什么?返回值是什么?

Windows中,使用什么符号作为文件路径分隔符?

Windows中,使用\作为文件路径分隔符。

Java中,使用什么符号作为文件路径分隔符?

Java中,java中使用\\作为文件路径分隔符。

Unix中,使用什么符号作为文件路径分隔符?

Unix中,使用/作为文件路径分隔符。

字符流

字符流可以用于读取二进制文件、图片、音频、视频等文件吗?

不可以,字符流只能用于读取文本文件。

转换流

InputStreamReader的作用是什么?

InputStreamReader的作用是将输入的字节流转换为字符流。

OutputStreamWriter的作用是什么?

OutputStreamWriter的作用是将输出的字节流转换为字符流。

缓冲流

缓冲流的作用是什么?

提升IO的性能。

常见的缓冲流有哪些?

BufferedOutputStream、BufferedInputStream、BufferedReader、BufferedWriter。

合并流

SequenceInputStream的作用是什么?

SequenceInputStream是合并流,它可以把多个输入流合并成一个流对象。

打印流

打印流可能是输入流吗?

不可以,打印流一定是输出流。

常见的打印流有哪些?

常见的打印流有:PrintStream、PrintWriter。

常见的数据流有哪些?

常见的数据流有:DataInputStream、DataOutputStream。

线程

线程

操作系统中,资源分配的最小单位是什么?

操作系统中,资源分配的最小单位是进程。

进程中最小的执行单元是什么?

进程中最小的执行单元是线程。

Java程序中,最少有多少个线程?

Java程序中最少有两个线程,分别是:主线程和GC垃圾回收线程。

进程和线程的关系是什么?

一个进程可以包含多个线程,而每个进程至少包含一个线程。同一进程中的不同线程之间共享内存资源。

每个进程在内存中,都有一块独立的内存空间,一个应用程序可以同时启用多个进程,而每个进程至少有一个线程。

线程是进程中的执行任务单元,一个进程中可以有多个线程,线程之间栈空间独立,堆内存共享。

如何创建线程?

创建线程的方式有三种:

一、继承Thread类。

二、实现Runnable接口

三、使用匿名内部类来创建线程

第二种方式比较常用。

如何启动线程?

实现线程的方式不同时,启动线程的方法也不同,不过一般都是通过start()方法来启动线程。

线程的实现方式有多少种?

多线程的实现方式一共有三种:

1.继承Thread类

2.实现Runnable接口

3.使用匿名内部类来创建线程

注意:不论是哪种实现方式,都需要重写run()方法。

使用继承Thread类的方法实现多线程时,如何启动线程?

注意:启动线程时,并不是直接调用run()方法,而是调用start()方法来启动线程。

//继承Thread类并重写run方法
public class MusicDemo extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("听音乐:"+i);
        }
    }
}
//调用 start 方法启动线程
MusicDemo musicDemo = new MusicDemo();
musicDemo.start();

使用实现Runnable接口的方式实现多线程时,如何启动线程?与使用继承Thread类启动线程有什么共同点和区别?

它们的共同点在于,两者都并非直接调用run方法,而都是通过start()方法启动线程。

但是两者的区别也非常明显:实现Runnable接口的方式启动线程时,需要通过自身对象来创建Thread对象,即:先创建自身对象,然后将自身对象作为参数传给Thread的构造器,创建Thread对象,最后再通过Thread对象调用start方法来启动线程。

//实现Runnable接口并重写run方法
public class PlayGame implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("打游戏:" + i);
        }
    }
}
//先创建对象
//再创建Thread对象(将对象作为参数传给Thread的构造器)
//使用Thread对象来调用start()方法
PlayGame playGame = new PlayGame();
Thread thread = new Thread(playGame);
thread.start();

如何使用匿名内部类来创建线程?什么时候可以使用这种方式?

使用匿名内部类创建线程的方式并不常用,它只适用于只使用一次的方式。

//使用匿名内部类来创建线程
new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("统计人头数:" + i);
                }
            }
        }).start();

多线程同步

并行和并发有什么区别?

并行:指在同一时刻,系统同时执行多个任务,利用多个处理单元或核心来实现真正的并行性。

并发:指在同一时间段内,系统同时管理多个任务,但不一定同时执行它们。

两者的区别在于:并行拥有多个处理单元,是真正的同时执行,但并发只有一个处理单元,是虚假的同时执行。

多线程的情况下,是如何决定运行哪个线程的?

多线程具体运行哪个线程,取决于CPU的调度。

JVM采用抢占式的调度方式,没有采用分时的概念,即:谁抢到谁执行。

为什么不要使用同步锁来修饰run方法?

因为当我们使用同步锁来修饰run方法时,必须在某一个线程执行完毕之后,其它线程才可以执行。

同步代码块,同步方法,同步锁如何选用?

同步锁是最推荐和最常用的,但当我们使用synchronized时,尽量减少锁的作用域。

锁机制如何使用?

Lock lock = new ReentrantLock();
//上锁
lock.lock();
        if (num > 0) {
            System.out.println(Thread.currentThread().getName() + "吃了编号为:" + num-- + "的香蕉");
        }
//解锁
lock.unlock();

什么是死锁?

死锁(Deadlock)是指在多进程或多线程系统中,每个进程或线程都持有某种资源,同时又在等待其他进程或线程持有的资源,从而导致所有相关进程或线程都无法继续执行的一种状态。

除非外部干预(如手动终止进程或重启系统),否则这种状态会永久性地阻塞系统。

线程调度

什么是线程合并?

线程合并也叫联合线程。

线程合并是指将几个并行的线程合并为单个线程执行的过程。这种机制通常应用在一个线程必须等待另一个线程执行完毕后才能继续执行的场景中。通常通过调用线程的join()方法来实现。

注意:操作线程先执行完之后,等待线程才执行。

join方法的返回值是什么?参数是什么?属于静态方法还是非静态方法?

join()方法是线程类中的一个非静态方法,它主要有以下几种形式:

  1. void join():等待该线程终止。调用此方法的线程将被阻塞,直到目标线程执行完毕。
  2. void join(long millis):等待该线程终止,但最长等待时间为指定的毫秒数。如果目标线程在指定的时间内终止,则调用线程将继续执行;如果目标线程在指定的时间内仍未终止,则调用线程将不再等待,继续执行自己的任务。这里的参数millis表示等待的时间,单位为毫秒。
  3. void join(long millis, int nanos):等待该线程终止,但最长等待时间为指定的毫秒数和纳秒数之和。这个方法提供了更精确的等待时间控制。其中,millis表示毫秒数,nanos表示纳秒数,等待的总时间为nanos+millis

高优先级的线程,一定早于低优先级的线程执行吗?

不一定,优先级的高低只影响线程获取执行机会的概率高低,但概率和执行顺序没有关系,主要取决于CPU的调度。

即:高优先级的线程有更大的概率获得CPU的资源。

yield方法和sleep方法有什么区别?

共同点:

yield方法和sleep方法都用于线程的让位,都能使当前处于运行状态的线程暂时放弃 cpu ,把机会给其它线程。

区别:

yield方法:作用是提示CPU调度器,当前的线程愿意让出CPU资源,但是具体要不要让出资源,取决于CPU调度器。

sleep让位时,不会考虑其它线程的优先级;yield只会让位给相同或更高优先级的线程。

调用sleep方法后,线程进入计时等待状态;调用yield方法后,线程进入就绪状态。

notify()方法和notifyAll()方法有什么区别?

notify()方法只会唤醒等待队列中的一个线程,而notifyAll()方法会唤醒等待队列中的所有线程。

在多线程环境下,如何保证两个线程交替执行?

可以使用wait()方法和notify()方法结合使用,让线程在合适的时机等待并唤醒。

守护线程

什么是守护线程?守护线程有什么特点?

守护线程即Daemon Thread,用于为其它线程提供服务或执行后台任务。

守护线程的特点:

1.后台运行:守护线程通常在后台运行,如监控资源、执行定时任务、垃圾回收等。

2.生命周期:守护线程的生命周期依赖于非守护线程。当所有的非守护线程都结束时,JVM会自动退出,此时守护线程也会随之结束,无需手动停止。

3.优先级:守护线程的优先级较低,如果系统资源紧张,守护线程可能得不到及时的调度。

垃圾回收线程就是一个典型的守护线程,它负责在后台清理不再使用的内存对象。

如何创建守护线程?

守护线程的创建和普通线程的相同,但需要添加一行设置代码:daemonThread.setDaemon(true);

Thread daemonThread = new Thread(() -> {
    // 守护线程的任务代码
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start(); // 启动线程

守护线程的常用场景有哪些?

守护线程的常用场景主要有五个:

1.垃圾回收

2.日志记录

3.心跳机制(心跳机制用于监控系统组件是否正常工作。)

4.定时任务调度(定时清理、数据同步)

5.后台计算(一些耗时的计算或者需要持续运行的后台计算也适合使用守护线程。)

线程通信

wait()、notify()、notifyAll()三个方法有什么区别?

wait():执行该方法的线程对象要释放同步锁,JVM 会把该线程放到等待池里面,等待其它的线程唤醒它

notify():执行该方法的线程唤醒在等待池中的线程,把线程转到锁池中去等待。

notifyAll():执行该方法的线程,唤醒在等待池中的所有线程,把这些线程转移到锁池中去等待。

为什么Lock机制不能调用wait和notify方法?

因为Lock 机制根本没有同步锁,也没有获取和释放锁的逻辑。在Lock机制中调用wait和notify方法会报错。

await()、singnal()、signalAll()和wait()、notify()、notifyAll()三个方法有什么区别?

前者来自于Condition接口,后者来自于Object类。

两者在功能上没有区别。

Thread类

run()的参数是什么?返回值是什么?

start()的参数是什么?返回值是什么?

启动线程。

currentThread()的参数是什么?返回值是什么

setName()的参数是什么?返回值是什么?

为线程设置名字。

getState()的参数是什么?返回值是什么?

getPriority()/setPriority()的参数是什么?返回值是什么?

获取/设置线程优先级。

sleep()的参数是什么?返回值是什么?

指定线程休眠时间。

join()的参数是什么?返回值是什么?

yield()的参数是什么?返回值是什么?

退回CPU,重新回到等待队列。

ReentrantLock

ReentrantLock与synchronized有什么区别?

ReentrantLock本质是一个类,只能修饰代码块。

而synchronized本质是一个关键字,既可以修饰代码块,也可以修饰方法。当方法或代码块出现异常时,会自动释放锁。

线程生命周期

线程的生命周期分为哪几个阶段?

线程的生命周期分为NEW(新建)、BLOCKED(阻塞)、RUNNABLE(可运行、就绪)、WAITING(等待)、TIMED_WAITING(计时等待)、TERMINATED(停止)六个阶段。

具体如下:

使用new 创建线程对象时,只分配了空间,为NEW阶段;

使用了 start 之后,为RUNNABLE阶段,此时有两种状态:ready和running。前者表示准备就绪,等待CPU的调度,后者表示获取到了CPU的调度;

运行中的线程,因为某些原因,放弃了 cpu 暂停运行,为BLOCKED阶段;

运行中的线程调用了 wait() 方法后,当前线程就会被JVM放在对象等待池中,为WAITING状态;

线程运行过程中,调用了wait(long)、sleep(long)等方法,此时 JVM会把当前线程存在对象等待池中,为TIMED_WAITING阶段;

正常的执行完线程或出现异常时,为TERMINATED状态。

线程组

线程组的作用是什么?

线程组(Thread Group)用于对线程进行集中管理,用户创建线程对象时,可以通过构造器指定所属的线程组。

ThreadGroup groups = new ThreadGroup("商品上架线程组");
ThreadGroup groups1 = new ThreadGroup("fihfiwehuif");
GoodsThread a = new GoodsThread(groups, "A");
a.start();
new GoodsThread(groups,"B").start();
new GoodsThread(groups1,"C").start();
new GoodsThread("efwefewfewfe").start();

public GoodsThread(ThreadGroup group, String name) {
   super(group,name);
}

A线程中创建B线程时,B线程和A线程的线程组有什么关系?

A线程中创建B线程,B线程默认加入A线程的线程组 。

未设置线程组的线程,其默认属于哪个线程组?

未设置线程组的线程,默认都属于main 线程的线程组。

线程池拒绝策略

线程池的拒绝策略有哪些?

常见的线程池拒绝策略有四种:

AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。

CallerRunsPolicy:由调用线程执行该任务,即主线程会执行被拒绝的任务。

DiscardPolicy:直接丢弃任务,不做任何处理。

DiscardOldestPolicy:丢弃最早进入工作队列的任务,然后尝试再次提交当前任务。

正则表达式、枚举、注解、Lambda表达式

正则表达式

x匹配什么?

匹配x

\\匹配什么?

代表反斜线\

[abc]匹配什么?

匹配a或b或c

[^abc]匹配什么?

除abc

\w匹配什么?

字母、数字或下划线

\d匹配什么?

数字0~9

a{5}匹配什么?

a出现5次

a{n,m}匹配什么?

a至少出现n次,不超过m次

枚举

枚举有什么特性?

final修饰,不可被继承;

构造器私有,所以枚举类对外不能创建对象;

第一行默认是用于罗列枚举对象的名称的。

什么是枚举类?

枚举类是一种特殊的类,用于定义一组常量。

如何定义一个枚举类?

可以使用enum关键字定义一个枚举类。

枚举类的常量有什么特点?

枚举类的常量是唯一的、有限的且已命名的,不能再次赋值。

枚举类的常量可以有自己的属性和方法吗?

是的,枚举类的常量可以有自己的属性和方法。

如何访问枚举类中的常量?

可以使用枚举类名和常量名来访问枚举类中的常量。

注解

Java内置的常用注解有哪些?

使用在代码上的注解:

@Override:检查方法是否被重写

@Deprecated:标记过时

@SuppressWarnings:忽略注解中声明的警告

元注解(DIV):

@Documented:标记这个注解是否包含在用户文档中

@Retention:标记注解保存的时间(三种参数:SOURCE表示源代码、CLASS表示字节码、RUNTME表示运行时)

@Target:标记注解的使用目标(三种参数:METHOD表示方法、FIELD表示属性、TYPE表示常量)

@Inherited:标记注解是继承哪个注解类(默认是没有继承的)

如何编写自定义注解?

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "MyAnnotation";
}

@MyAnnotation("eat1")
public void eat(){
//s
}

什么是注解?

注解是一种特殊的标记,在编程中用来提供额外的信息给编译器、解释器或其他编程工具。

Java中的注解有什么作用?

Java中的注解可以用于描述类、方法、字段等元素的属性、行为和约束,为编写优雅、可读性高的代码提供支持。

如何定义一个注解?

可以使用@interface关键字定义一个注解,注解的成员变量可以用来存储元数据。

注解可以用在哪些地方?

注解可以用在类、方法、字段、参数等地方。

如何使用Java中的内置注解?

可以直接在使用的地方加上相应的注解,如@Override、@Deprecated等。

如何使用自定义注解?

需要在注解上添加元注解@Retention(RetentionPolicy.RUNTIME),然后可以在目标元素上使用该注解。

注解的生命周期有几种?

注解的生命周期有3种:源码级别(SOURCE)、编译期级别(CLASS)和运行时级别(RUNTIME)。

如何通过反射获取注解信息?

可以使用Class对象的getAnnotation()或getAnnotations()方法来获取指定注解或所有注解。

注解的元数据可以用来做什么?

注解的元数据可以用来配置程序的行为、生成文档、进行代码分析等。

如何在注解中定义成员变量?

可以在注解中定义成员变量,并使用默认值为其指定初始值。

注解的成员变量可以是什么类型?

注解的成员变量可以是基本类型、字符串、枚举、注解、Class对象以及它们的数组。

如何为注解的成员变量指定值?

可以使用注解时的"key=value"格式为注解的成员变量指定值。

如何在程序中处理注解?

可以使用反射来处理注解,读取注解的元数据并进行相应的处理。

在注解中可以继承其他注解吗?

在Java中,注解不能继承其他注解。

注解的声明周期可以通过什么设置?

可以通过@Retention元注解来设置注解的声明周期。

如何在运行时获取注解的元数据?

需要使用反射来获取注解的元数据,通过Class对象或其他反射API来操作。

注解与反射机制有何关系?

注解和反射机制是密切相关的,通过反射可以获取注解的元数据,并根据注解来进行相应的操作。

注解在框架开发中有何应用?

注解在框架开发中可以用于配置文件的映射、依赖注入、AOP等方面,提供更灵活和轻量级的开发方式。

如何定义一个注解的元注解?

可以使用@interface关键字来定义一个注解的元注解。

你在项目中用过哪些常见的注解?

常见的注解有:@Override、@Deprecated、@SuppressWarnings、@Autowired等。

Lambda表达式

什么是Lambda表达式?

Lambda表达式允许一个函数作为方法参数传递到方法中去。

(parm)->expression;
或
(parm)->{expression;}

什么是函数式接口?

函数式接口是只有一个抽象方法的接口,可以使用Lambda表达式来实现该接口。

什么是Lambda表达式?

Lambda表达式是一种匿名函数,是Java 8引入的一项重要特性,可以简化函数式编程和并发编程。

Lambda表达式有哪些优点?

Lambda表达式可以使代码更为简洁、可读性更高,同时也提供了更好的并发编程支持。

如何定义一个Lambda表达式?

Lambda表达式由参数列表、箭头符号和函数体组成,例如:(参数列表) -> {函数体}。

JavaWeb

网络编程

拓展

192.168.2.12是ipv4还是ipv6?ipv4和ipv6的区别是什么?

ipv4和ipv6都是互联网协议(Internet Protocol) 。

ipv4和ipv6的区别在于:

  • IPv4使用32位地址,通常表示为四个十进制数(例如:192.168.1.1),每个数在0到255之间。
  • IPv6使用128位地址,通常表示为八组十六进制数(例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334),每组由四个十六进制数字组成。

所以192.168.2.12是ipv4。

如何查看本机的IP地址?

进入CMD命令行界面,使用ipconfig命令

URI 与 URL有什么区别?

URI:统一资源标识符,是用来标识某一个互联网资源名称的字符串。

URL:统一资源定位符,是互联网的标准资源地址。

http://www.baidu.com/hello.htmlhttp://ip:80/home/index.png哪一个是URL,哪一个URI?

URL的结构为:主机名,端口,标识符,具体路径。

URI的结构为:主机名,端口,标识符,相对URI。

所以,http://www.baidu.com/hello.html是URI,http://ip:80/home/index.png是URL。

http和https有什么区别?

http:超文本传输协议。

https:使用安全的套接字传输的超文本协议。

另外,http是免费的,但是https是收费的。

什么是套接字Socket?

套接字是一种抽象的数据结构,它充当了网络应用程序和网络协议之间的接口。

通过套接字,程序能够在网络中发送和接收数据,实现不同主机或不同进程之间的通信。

套接字通常位于操作系统的网络协议栈和应用程序之间,作为一个桥梁,使得应用程序可以通过标准的编程接口与网络协议进行通信。

套接字的工作原理:

  1. 客户端和服务器各自创建一个套接字,用于通信。
  2. 服务器将套接字绑定到一个特定的IP地址和端口,然后等待客户端的连接请求。
  3. 客户端发起连接请求,服务器接受连接。
  4. 双方通过套接字发送和接收数据。
  5. 通信结束后,双方关闭套接字以释放资源。

网络通信的三要素是什么?

网络通信的三要素是:IP、端口、通信协议。

端口的范围是0~65535,但其中0~1024都被系统保留使用了。

网络模型

常见的网络模型有哪些?

常见的网络模型有OSI参考模型和五层协议的体系结构模型两种。

OSI参考模型分为哪几层?

OSI参考模型分为七层:应用层、表示层、会话层、运输层、网络层、数据链路层、物理层。

五层协议的体系结构分为哪几层?

五层协议的体系结构分为:应用层、运输层、网络层、数据链路层、物理层。

传输层的协议有哪些?

传输层的协议主要有TCP、UDP两种。

TCP协议与UDP协议

什么是TCP协议?为什么TCP协议比UDP协议更可靠?

TCP协议也就是Transmission Control Protocol (传输控制协议)。

相比于UDP协议,TCP协议通过三次握手和四次挥手建立了稳定的连接,而UDP协议是无连接的数据传输服务,所以,TCP协议更可靠。

什么是三次握手和四次挥手?

什么是UDP协议?

UDP协议也就是User Datagram Protocol(用户数据协议)。

UDP协议的优点和缺点是什么?

UDP协议的优点在于不需要双方建立连接,因此传输速度很快。

但也因为没有建立连接,所以UDP协议的安全性较低。

UDP和TCP哪一个更适合用来传输大量数据,哪一个更适合用来传输少量数据?

TCP适合传输大量数据,UDP适合传输少量数据。

因为TCP的传输是基于稳定的连接,而建立连接也有一定的开销,如果用TCP传输少量数据,会导致建立连接的开销过高。

而UDP是不可靠的传输,传输大量数据时,会导致很多数据丢失。

如何使用Java代码实现一个简单的TCP传输?

public class Client {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9999);
        InputStream in = socket.getInputStream();
        Scanner scanner = new Scanner(in);
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }

        scanner.close();
        socket.close();
    }
}
public class Server {

    public static void main(String[] args) throws IOException {
        //创建服务端,指定端口为9999
        ServerSocket socket = new ServerSocket(9999);

        System.out.println("服务端准备就绪");
        //获取客户端的连接请求,阻塞的。
        Socket accept = socket.accept();
        System.out.println("获取到客户端的连接:"+accept.getInetAddress());
        PrintStream printStream = new PrintStream(accept.getOutputStream());
        printStream.print("你好,这里是服务端,感谢你的连接");
        printStream.close();

        socket.close();
    }
}

如何使用Java代码实现一个简单的UDP传输?

public class Send {

    public static void main(String[] args) throws IOException {
        String data = "我是发送者";
        //创建发送端对象
        DatagramSocket datagramSocket = new DatagramSocket(10010);
        //发送数据
        DatagramPacket packet = new DatagramPacket(data.getBytes(),//发送的数据
                data.getBytes().length,//发送多长
                InetAddress.getLocalHost(),//目标发送地址
                110);//发送的端口

        datagramSocket.send(packet);
        datagramSocket.close();
    }
}

public class Receive {

    public static void main(String[] args) throws IOException {
        //创建接收对象
        DatagramSocket datagramPacket = new DatagramSocket(10010);
        byte[] buffer = new byte[1024];
        //接收数据
        DatagramPacket packet = new DatagramPacket(buffer, 1024);
        datagramPacket.receive(packet);
        String string = new String(buffer, 0, packet.getLength());
        System.out.println(string);

        datagramPacket.close();
    }
}

Tomcat

安装 tomcat 成功后,如要修改 tomcat 端口,要修改的文件是哪个?

tomcat/conf/server.xml

tomcat/bin/startup.bat文件的作用是什么?

它是用来启动 Tomcat的脚本文件

需要在 JSP 页面中引入 java.util.*包,需要用到的指令是什么?

<%@page import="java.util.*" %>

用于创建将参数化的 SQL 语句发送到数据库的对象方法是什么?

prepareStatement(String sql)

executeQuery(String sql)方法可以执行 update 语句吗?

不可以,executeQuery(String sql)只能用来执行select语句。

设计模式

生产者与消费者模式

面试测试

强、软、弱、幻象引用

不同的引用类型 主要体现对象不同的可达性状态和对垃圾收集的影响。
强引用 StrongReference 只要还有强引用指向一个对象,那么该对象就不会被垃圾收集器回收。
软引用 SoftReference 只有当JVM认为内存不足时,才会试图回收软引用的对象。
确保在抛出OutOfMemoryError之前,清理软引用的对象。
弱引用 WeakReference 仅提供一种访问在弱引用状态下对象的途径。
幻象引用 仅提供了一种确保对象被finalize之后,做某些事情的机制。
Java的不同可达性级别 reachability level
强可达 Strongly Reachable 一个对象可以有一个或多个线程可以不通过各种引用访问到的情况。
软可达 Softly Reachable
弱可达 Weakly Reachable
幻象可达 Phantom Reachable
不可达 unreachable

模拟面试

说说你对Java的GC回收机制的理解。

垃圾回收(Garbage Collection)是JVM垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。

仅仅回收无引用对象所实际占用的空间,有对象引用的不回收。

GC的早期策略,是通过引用计数法判断对象回收的时机。

在对象中添加一个引用计数器,每当有一个地方 引用它时,计数器值就加一;

当引用失效时,计数器值就减一;

计数器为零的对象就是不可能再被使用的对象。

引用计数算法(Reference Counting)虽然占用了一些额外的内存空间来进行计数,但它的原理简单,判定效率也很高,在大多数情况下它都是一个不错的算法。

当前主流的内存管理子系统,都是通过可达性分析(Reachability Analysis)算法来判定对象是否存活的。

可达性分析算法的基本思路,是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

谈谈常用的垃圾回收算法。

Java8有哪些新特性?

Java8有很多新特性,其中最重要的两个是:Lambda表达式和接口可以提供默认方法和静态方法。

Exception和Error有什么区别?

谈谈浅拷贝和深拷贝。

浅拷贝: 基础数据类型复制值,引用类型复制引用地址,修改一个对象的值,另一个对象也随之改变。

深拷贝: 基础数据类型复制值,引用类型在新的内存空间复制值,新老对象不共享内存,修改一个值,不影响另一个。

谈谈final、finally、finalize有什么不同?

String、StringBuilder、StringBffer有什么不同?

int和Integer有什么区别?

Vector、ArrayList、LinkedList有什么区别?

HashTable、HashMap、TreeMap有什么区别?

谈谈ConCurrentHashMap

谈谈接口和抽象类有什么区别?

如何用最有效率的方法计算 2 乘以 8?

2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次 方)。

float f=3.4;是否正确?

不正确。

3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失。

因此需要强制类型转换float f =(float)3.4;

谈谈你知道的设计模式?

谈谈JVM内存区域的划分?

什么是 JDK、JRE 和 JVM?

& 和 && 的区别 ?

谈谈成员变量和局部变量的区别

谈谈static和final

什么是面向对象?

谈谈overload和override。

谈谈throw和throws的区别。

说出常见的五种异常。

谈谈Collection和Collections的区别。

多线程的实现方式有哪些?

谈谈线程的生命周期。

谈谈TreeSet和HashSet的区别。

String abc = new String(“abc”)有几个对象?

谈谈map的两种遍历方式。

什么是反射?

线程和进程有什么区别?线程的生命周期有哪些?

你对线程调度有何理解?线程相关的常用方法有哪些?至少说出三个常用的方法。

throw和throws的有什么区别?

谈谈对序列化和反序列化的认识。

如何实现一个自定义异常类?

说出几种常见的Error。

介绍封装、继承、多态。

java7和java8中HashMap的区别有哪些?

JDK1.7中使用数组+链表的结构实现HashMap,而JDK1.8中引入了红黑树的概念,使用数组+链表/红黑树的结构实现HashMap。这是为了解决JDK1.7中当链表过长时导致查询性能下降的问题。

下面代码运行结果是什么?为什么?

@Test
 public void test2() {
 String s1 = "hello";
 String s2 = "world";
 String s3 = "hello" + "world";
 String s4 = s1 + "world";
 String s5 = s1 + s2;
 String s6 = (s1 + s2).intern();
 System.out.println(s3 == s4);
 System.out.println(s3 == s5);
 System.out.println(s4 == s5);
 System.out.println(s3 == s6);
 }

待整理

  1. 问:什么是面向对象编程? 答:面向对象编程是一种程序设计思想,通过将问题抽象成对象,通过对象之间的交互和数据封装来实现程序逻辑。
  2. 问:Java中的类和对象有什么区别? 答:类是描述对象的模板,对象是类的实例。类定义了对象的属性和行为,而对象则具体地拥有这些属性和行为。
  3. 问:什么是封装?为什么要使用封装? 答:封装是将数据和方法包装在类中,并限制对数据的直接访问。封装可以隐藏内部细节,提供对外部的安全接口,并实现代码的重用和维护。
  4. 问:什么是继承?有什么作用? 答:继承是指子类继承父类的属性和方法。继承可以实现代码的重用,提高代码的可维护性和可扩展性。
  5. 问:Java是否支持多继承? 答:Java不支持多继承,一个类只能继承一个父类。但是Java支持接口的多实现,实现了多继承的效果。
  6. 问:什么是多态?如何实现多态? 答:多态是同一类型的对象在不同情况下表现出不同的行为。多态可以通过继承和接口的方式实现。
  7. 问:什么是抽象类?有什么作用? 答:抽象类是不能被实例化的,它只能被继承。抽象类可以包含抽象方法和具体方法的定义,用于作为其他类的父类。
  8. 问:什么是接口?有什么作用? 答:接口是一组抽象方法的集合。接口定义了对象应该具备的行为,类可以实现(implements)接口来达到多继承的效果。
  9. 问:Java中的构造方法有什么作用? 答:构造方法是用于在创建对象时初始化对象的状态。它的名称与类名相同,没有返回类型。
  10. 问:什么是重载和重写? 答:重载(Overload)是指在同一个类中定义多个方法,它们具有相同的名称但参数列表不同;重写(Override)是指子类覆盖父类的方法,方法名和参数列表必须相同,可以有不同的实现。
  11. 问:什么是静态方法和静态变量? 答:静态方法和静态变量属于类级别,而不是对象级别。它们可以在类被加载时直接调用,无需创建对象。
  12. 问:Java中如何实现数据的隐藏和封装? 答:Java中通过访问控制修饰符(private、protected、public)来限制对类的属性和方法的访问。
  13. 问:什么是内部类?有什么作用? 答:内部类是定义在其他类内部的类。它可以访问外部类的成员,并提供了更好的封装性和代码组织性。
  14. 问:什么是匿名类? 答:匿名类是没有名字的内部类,它通常用于直接创建对象并重写父类或接口的方法。
  15. 问:什么是单继承和多实现? 答:Java中一个类只能继承一个父类,这称为单继承;但是一个类可以实现多个接口,称为多实现。
  16. 问:Java中如何防止继承? 答:通过将类声明为final,可以防止其他类继承该类。
  17. 问:什么是对象的浅拷贝和深拷贝? 答:浅拷贝是指复制对象时,简单地复制对象的引用;深拷贝是指复制对象时,复制对象的所有引用和对象本身。
  18. 问:什么是重写equals()和hashCode()方法的作用? 答:重写equals()方法可以定制对象之间的相等比较逻辑;重写hashCode()方法可以保证对象在哈希表中的正确存储和查找。
  19. 问:什么是枚举类? 答:枚举类是一种特殊的类,它限制对象的个数,并提供了更好的类型安全和代码可读性。
  20. 问:super关键字和this关键字有何区别? 答:super关键字用于访问父类的成员(属性和方法),this关键字用于访问当前对象的成员。

数组

问:什么是数组? 答:数组是一种存储多个相同类型数据的数据结构,可以通过索引访问和修改数组中的元素。

问:如何声明和初始化数组?

答:可以使用以下方式声明和初始化数组:

声明数组:int[] array;
初始化数组:array = new int[5]; 或者 int[] array = {1, 2, 3, 4, 5};

问:如何获取数组的长度?

答:可以使用数组的属性获取数组的长度,例如:

问:如何访问数组中的元素?

答:可以使用索引来访问数组中的元素,索引从0开始,例如:

问:数组有没有固定大小?

答:是的,数组在创建时需要指定大小,且大小不可变。

问:如何遍历数组?

答:可以使用循环结构来遍历数组,例如:

for (int i = 0; i &lt; array.length; i++) {
    // 使用array[i]访问元素
}

问:数组是否可以存储不同类型的元素? 答:不可以,数组只能存储相同类型的元素。

问:如何查找数组中的最大值和最小值? 答:可以使用循环遍历数组,记录最大值和最小值,例如:

int max = array[0];
int min = array[0];
for (int i = 1; i &lt; array.length; i++) {
    if (array[i] &gt; max) {
        max = array[i];
    }
    if (array[i] &lt; min) {
        min = array[i];
    }
}

问:如何对数组进行排序? 答:可以使用类的方法对数组进行排序,例如:

问:如何判断两个数组是否相等? 答:可以使用类的方法来判断两个数组是否相等

例如:

问:如何复制数组? 答:可以使用类的方法或类的方法来复制数组,例如:

int[] newArray = Arrays.copyOf(array, array.length);

// 或者使用System.arraycopy()
int[] newArray = new int[array.length];
System.arraycopy(array, 0, newArray, 0, array.length);

‍问:如何在数组中查找指定元素的索引?

答:可以使用循环遍历数组,查找指定元素的索引,例如:

int target = 5;
int index = -1;
for (int i = 0; i &lt; array.length; i++) {
    if (array[i] == target) {
        index = i;
        break;
    }
}

问:数组有没有动态调整大小的方法? 答:数组的大小在创建时就已经确定,不能动态调整大小。如果需要动态调整大小,可以使用等动态数组。

问:如何将数组转换为字符串输出? 答:可以使用类的方法将数组转换为字符串,例如:

问:数组和集合有何区别? 答:数组是一种固定大小的数据结构,而集合是动态大小的数据结构。数组可以存储基本数据类型和对象,而集合只能存储对象。

问:数组和链表有何区别? 答:数组是连续的内存空间,访问元素的速度快,但插入和删除元素的效率较低。链表是非连续的内存空间,插入和删除元素的效率较高,但访问元素的速度较慢。

问:如何在数组中添加和删除元素? 答:数组的大小不可变,无法直接添加和删除元素。但可以通过创建一个新的数组,将原数组中的元素复制到新数组中,来实现添加和删除操作。

问:如何统计数组中某个元素出现的次数?

答:可以使用循环遍历数组,对比每个元素是否等于目标元素,统计出现的次数,例如:

int target = 5;
int count = 0;
for (int i = 0; i &lt; array.length; i++) {
    if (array[i] == target) {
        count++;
    }
}

多线程的好处有哪些?

多线程的好处:

可以提高 CPU 的利用率。在多线程程序中,一个线程必须等待的时候,CPU 可 以运行其它的线程而不是等待,这样就大大提高了程序的效率。也就是说允许单 个程序创建多个并行执行的线程来完成各自的任务。

多线程的劣势有哪些?

多线程的劣势:

线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;

多线程需要协调和管理,所以需要 CPU 时间跟踪线程;

线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题。

线程和进程的区别?什么是线程?什么是进程?

进程 :

一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

线程:

进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。

进程之间的存储空间是独立的,同一进程中的线程的存储空间是共享的。

字节流和字符流有什么区别?

字节流是万能流,可以处理任意文件,但是字符流只能处理文本文件。

什么是反射?

反射就是在程序运行期间,动态的获取类中成员信息(构造方法、成员变量、成员方法)的过程。

Map的两种遍历方式分别是?

两种方法都来自Map接口。

1.keySet方法:

第一步:用keySet方法将map容器中的key取出,保存到set容器中;

第二步:遍历set容器,通过Map中的get方法遍历。

2.entrySet方法:

第一步:将map容器中的key和value保存到Map的内部类entry中,将entry对象保存到set容器中;

第二步:遍历set容器,通过部类entry中的getKey方法和getValue方法遍历。

TreeSet和HashSet的区别是什么?

两者的共同点:

都是Set接口的实现类,所以其中的元素都是不可重复的。

两者的区别:

TreeSet可以按照一定的排序规则,对元素进行排序。

线程的生命周期有哪些?

线程的生命周期包括:

新建、就绪、运行、阻塞、死亡等状态。

集合和数组的区别是什么?

两者的区别:

集合只能存储引用数据类型,而数组既可以存储基本数据类型,也可以存储引用数据类型。

集合的长度可以任意改变,数组的长度不能改变。

JVM的内存分为哪些区域?

JVM的内存分为:

堆、虚拟机栈、本地方法栈、方法区、程序计数器、运行时常量池等区域。

什么是拆箱和装箱?

拆箱:引用数据类型转换为对应的基本数据类型。

装箱:基本数据类型转换为对应的引用数据类型。

throw和throws的区别是什么?

throw:执行异常的抛出动作。

throws:声明可能抛出的异常。

什么是面向对象?

面向对象也叫OOP,面向对象的核心思想是将现实世界的问题抽象为一系列相互交互的对象。而对象中包含了数据和操作这些数据的方法。

它的主要特性包括多态、封装、继承。

多态就是对于父类的统一个方法,不同的子类有不同的实现,调用时会根据子类的具体实现,展现出不同的效果。

封装就是利用访问权限修饰符等将类的部分信息隐藏起来,并提供方法供外部调用者调用。

继承就是子类可以继承父类的属性和方法等。继承也是多态的重要条件。

线程的 run()和 start()有什么区别?

run和start都来自Thread类。

run方法也叫线程体,每个线程都是通过其对应的Thread对象的run方法来完成操作的。

start方法用于启动线程;run方法用于执行线程的运行时代码,run方法运行结束,也就意味着线程终止。

run方法可以重复调用;start方法只能调用一次。

为什么不能直接调用run方法来启动线程?

start方法会使线程从新建状态变为就绪状态,当处于就绪状态的线程分配到时间片后,就可以开始运行了。

而run方法知识一个普通的方法,只能在主线程中执行。

创建线程的方式有哪些?

有四种创建线程的方法:

继承Thread类;

实现Runnable接口;

实现Callable接口;

使用Executors工具类创建线程池继承Thread类。

Callable接口和Runnable接口有什么区别?

Callable接口比Runnable接口更加强大,

Runnable接口不会返回结果,且无法抛出返回结果的异常,而Callable可以返回值。

Java中,线程的状态有哪些?

Java中的线程有六种状态:

新建、就绪/运行、等待、时间等待、阻塞、结束。

为什么String是不可变的?

String本身由于被final修饰,所以是一个最终类,不能被继承。而其底层的数组实现也是被final修饰的,所以也不能修改。对String的修改的本质,是创建了一个新的String对象。

sleep方法和wait方法有什么区别?

sleep方法来自Thread类,是静态方法;wait来自Object类,是普通方法。

sleep不会释放锁;wait释放锁。

sleep用于暂停执行;wait用于线程间的通信。

sleep方法会再执行完成之后,自动苏醒线程;wait方法需要其它线程调用notify方法或notifyAll方法来苏醒线程,或等待超时后自动苏醒线程。

如何终止一个正在运行的线程?

使用退出标志,即在run方法执行完成后,线程终止。

使用stop方法强行终止线程,但不推荐这种方式。

使用interrupt方法中断线程。

wait方法有什么作用?

当线程调用了wait方法时,线程便会被置于该对象的等待池中,而等待池中的线程不会去竞争该对象的锁。

notify方法和notifyAll方法有什么区别?

\1. notify方法会唤醒所有的线程;notify只会唤醒一个线程。

\2. 调用notify方法后,等待池中的所有线程都会被转移到锁池中,并参与锁的竞争。

\3. 而notify方法只会唤醒一个线程,而具体的唤醒哪个线程则由虚拟机控制。

synchronized和Lock有什么区别?

\1. synchronized是关键字,而Lock是一个类;

\2. synchronized可以对类、方法、代码块加锁,而Lock只能为代码块加锁;

\3. synchronized不需要手动的获取和释放锁,当发生异常时,可以自动释放锁,从而避免死锁;Lock需要手动获取和释放锁,如果没有unlock方法来释放锁,就会造成死锁。

\4. synchronized无法知道是否成功获取锁,而Lock可以知道。

sunchronized和ReentrantLock有什么区别?

\1. synchronized是关键字,而ReentrantLock是一个类;

\2. ReentrantLock只能对代码块上锁,而synchronized可以对方法、类、变量、代码块上锁;

\3. ReentrantLock需要手动的获取和释放锁,而synchronized不需要。

volatile关键字的作用是什么?

volatile关键字用于保证可见性和禁止指令重排,常用于多线程情况下的单次读或单次写。volatile会保证其修饰的变量在被修改时,立即向主存中更新。

线程池有什么优点?

降低资源的消耗:提高线程的复用性,避免线程资源的浪费。

提高响应的速度:任务不再需要重新创建线程来执行。

为线程的管理提供方便:线程池可以对线程提供统一的分配,调优和监控。

提供额外的功能:提供定时执行、定期执行、并发控制等功能。

BIO、NIO、AIO有什么区别?

Block IO:同步阻塞式IO,模式简单使用方便,但是并发处理能力低;

New IO:同步非阻塞IO,客户端和服务端实现了通道(Channel)通信,实现了多路复用;

Asynchronized IO:实现了异步非堵塞IO。

Collection和Collections有什么区别?

Collection是集合框架中的重要接口之一,List、Set等接口都是它的子接口。

Collections是一个工具类,其中包含了很多操作集合的静态方法,如排序的方法:COllections.sort(list)。

List、Map、Set之间的区别是什么?

三者的区别主要在两个方面:是否有序、是否可重复。

HashSet的实现原理是?

HashSet的底层是通过HashMap实现的,其中,HashSet的值存放在HashMap的键中,HashMap的值均为PRESENT。因此,HashSet中不允许存在重复的元素。

ArrayList和LinkedList的区别是什么?

两者底层的数据结构是不同的ArrayList是数组结构,LinkedList是双向链表结构。也正是因此,ArrayList的查询效率高于LinkedList,而LinkedList的增加删除效率高于ArrayList。

如何实现数组和List之间的转换?

分别通过ArrayList的toArray方法和Arrays的asList方法实现。

数组转List:Arrays的asList方法

List转数组:ArrayList的toArray方法

// list to array List

ArrayList和Vector的扩容机制有什么区别?

ArrayList按照1.5倍扩容,Vector按照2倍扩容。

你可能感兴趣的:(Java知识体系构建,java)