介绍
这是从面试网站自我理解整理的面试笔记,如有不对的地方请大佬指正!也欢迎大家关注我,和我一起学习冲击大厂,如果文章对你有些许帮助,不妨不要吝啬大伙的点赞收藏,这是我出下一篇的笔记最大的支持~~~
如果侵权纯属巧合,通知我会修改
Java 中的序列化和反序列化是什么?
序列化:序列化将对象转为字节流对象。网络传输,远程调用,分布式系统等...类上继承java.io.serilizable接口实现方法
反序列化:将字节流对象转为java对象。
transient关键字可标记不被序列化字段。
SerialVersionUID:用于反序列化时验证版本是否一致.
什么是 Java 中的不可变类?
不可变类:类字段有private和final,创建后类的字段一切都不能修改。
声明类为final,类不能被继承。
只能通过构造函数初始化。
不提供任何修改字段方法。
类包含可变对象引用,确保该对象外部无法修改。
(String、Integer、Character、LocalDate、BigDecimal等)
Java 中 Exception 和 Error 有什么区别?
Exception和Error都实现于Throwable接口。
Exception:编译时异常(checkedException)和运行异常(uncheckedException)。检查错误需要通过try...catch进行捕获或throw抛出。运行时异常常见有:空指针异常,不合法变量。
Error:JVM级错误比较严重的错误,无法在代码层面修改解决。(栈溢出,内存耗尽)
你认为 Java 的优势是什么?
跨平台:一次编译,处处运行。
生态:生态圈庞大,比如spring全家桶,开源社区庞大。
面向对象:封装、继承、多态。
垃圾回收:内存管理交给GC(垃圾自动回收),提高内存管理效率。
什么是 Java 的多态特性?
多态:一个方法在不同对象上有不同的行为。分为编译时多态和运行时多态
编译时多态:方法重载实现,相同方法不同行为。
运行时多态:方法重写实现,继承关系或接口实现时,相同方法不同类不同行为。
优势:降低代码耦合度,增强扩展性。
Java 中的参数传递是按值还是按引用?
参数传递按值传递,无论基本数据类型还是引用类型。
基本数据类型:传递数值。修改不影响原始变量。
引用数据类型:传递对象引用的内存地址。可修改对象属性,但无法改变其引用本身。
为什么 Java 不支持多重继承?
会出现钻石继承问题,导致无法找到对应的方法。
jdk8以前接口无法实现方法,不会出现该问题。jdk8后接口出现默认方法,如果出现多个方法冲突,则强制类中重写该方法。
抽象类无法多继承
Java 面向对象编程与面向过程编程的区别是什么?
面向对象:基于类。将数据和方法封装为对象为基本单位。继承、封装、多态,注重模块和对象之间的配合。
面向过程:基于方法函数。以过程来组织代码。注重过程逻辑分布。
OOP更适合需扩展的复杂系统,面向过程更适合简单任务。
人.煮咖啡 对比 执行煮咖啡方法
Java 方法重载和方法重写之间的区别是什么?
重载:编译时找到。同一个类中,方法名一样,通过参数数量,位置,类型找到方法。返回类型可不一样。访问修饰符不受影响。
重写:运行时找到。继承或接口实现,参数类,方法名,返回都不能更改。子类访问修饰符不能小于父类。不能抛出比父类更多的异常。
什么是 Java 内部类?它有什么作用?
内部类:类中内部定义的类,可以访问外部类的成员变量。分为成员内部类,静态内部类(只能访问外部静态成员),局部内部类,匿名内部类。
访问外部类成员;操作外部类对象场景有用。
简化代码开发。
封装性:逻辑相关类封装一起,提高内聚。
事件处理:回调函数或事件监听,简化结构。
在实际jvm中没有内部类,编译出来还是正常类。
JDK8 有哪些新特性?
接口有默认实现方法:default。
新增时间类:LocalDateTime,线程安全。
Stream流:方便操作集合。
Optional类。
lambda表达式。
元空间代替永久代:元空间是分配在直接内存中,解决永久代存在的内存不足,GC效率低。
Java 中 String、StringBuffer 和 StringBuilder 的区别是什么?
String线程安全,不可变(final),适用操作少量字符串。
StringBuffer线程安全,可变,适用并发频繁操作字符串。(synchronized)
StringBuilder线程不安全,适用单线程大量操作字符串。
Java 的 StringBuilder 是怎么实现的?
stringbuilder解决不可变字符串问题。在jdk1.8中,底层使用char[] value数组,占用连续内存空间,默认大小是16,也可以自行修改。
常用方法有append、insert、delete、replace等
append字符串拼接底层实现:(int举例)将int数字转为字符所占位数(Integer.stringSize,查表法),判断char[] 是否充足,不充足扩容,充足就放入。
扩容:Arrays.copyOf方法,将容量扩大到原始容量两倍+2。没有实现缩容
优化策略:节约内存可以将char[] 改为byte[],然后添加一个标记区分不同编码。(jdk9)
Java 中包装类型和基本类型的区别是什么?
基本类型:int , short ,long , double ,float , byte , boolean , char
不可变。默认不是0就是false,没有null。==比较的是值。性能快。初始化方式直接创建。局部变量存储在栈,成员变量存储在堆。
包装类型:Integer,Short,Long,Double,Float,Byte,Boolean,Character
操作对象属性。默认是null。==比较的是引用对象地址,eqalus比较值。性能慢。new对象。存储在堆。
接口和抽象类有什么区别?
接口:自上而下设计。成员变量默认public static final(常量)。方法默认是public abstract方法(Java8后可设置default方法或静态方法)。允许多实现。
抽象类:自下而上设计。成员变量没有约束。方法可以abstract(未实现方法)和具体方法。只允许单继承。
JDK 和 JRE 有什么区别?
JDK是java开发工具包,它包含了常用开发工具和JRE运行环境,给开发人员使用,可以将.java文件转为.class字节文件以供运行。JRE是java运行环境,它包含了Java常见库和JVM虚拟机,给最终用户使用,提供运行Java程序运行环境。JVM虚拟机提供运行.class文件的工具,如果单有jvm是无法执行java程序的。
Java 中 hashCode 和 equals 方法是什么?它们与 == 操作符有什么区别?
hashCode,equals和==都是java用于比较对象的方法。hashcode通常是用于在散列表内存存储中记录位置,如果对象的hashcode不同那么对象肯定不同。而equals通常比较的是对象的属性值是否一致,如果需要可以重写equals,如果对象equals相等,那么它们的hashCode也一定相等,但反之却不一定。==比较的是对象中的引用地址,如果是基本数据类型则比较对象的值。
什么是 Java 中的动态代理?
动态代理是一种在运行时动态生成代理对象的技术,它可以在不修改原有对象代码的情况下,扩展或改变对象的行为。动态代理的核心思想是通过一个代理对象来间接访问目标对象,从而在目标对象的方法执行前后插入额外的逻辑。
动态代理的常用方法有:JDK动态代理和CGLIB动态代理
JDK 动态代理和 CGLIB 动态代理有什么区别?
1.JDK动态代理:只能代理实现了接口的类,通过实现InvocationHandler接口进行方法增强操作,通过proxy创建代理对象
2.CGLIB:通过继承的方式实现代理,所有要求被代理类和方法不能使用final修饰。
Java 中的注解原理是什么?
注解其实是对对象的描述,提供了一种元数据的方式,其本身并不影响具体对象的功能。常用于框架开发等,可以通过反射机制拿到对应的注解与其值,然后对其扩展功能或修改。注解的使用可以用@interface关键字进行标识,元注解有@Rentention描述注解的有效范围,@Target描述注解使用的对象。
你使用过 Java 的反射机制吗?如何应用反射?
反射机制指的是在运行过程中获取对象属性与方法,无需在编译时了解该对象情况,并对其进行强制操作。一般用于框架开发。
详细使用
Java 中的反射机制:
1. 反射的本质
- 反射机制允许程序在运行时动态获取类的元数据(如类名、方法、字段等),并操作对象的属性和方法。
- 反射的核心类是
java.lang.Class,它表示一个类或接口的元数据。
2. 反射的核心类
Class类:
-
- 用于获取类的元数据。
- 可以通过
Class.forName()、对象.getClass()或类名.class获取Class对象。
Method类:
-
- 用于获取和调用方法。
- 可以通过
Class.getMethod()或Class.getDeclaredMethod()获取Method对象。
Field类:
-
- 用于获取和修改字段。
- 可以通过
Class.getField()或Class.getDeclaredField()获取Field对象。
Constructor类:
-
- 用于获取和调用构造方法。
- 可以通过
Class.getConstructor()或Class.getDeclaredConstructor()获取Constructor对象。
3. 反射的典型应用场景
- 框架开发:
-
- 如 Spring 通过反射实现依赖注入(DI)和 AOP。
- 如 Hibernate 通过反射实现对象关系映射(ORM)。
- 动态代理:
-
- 通过反射调用目标对象的方法。
- 配置文件解析:
-
- 通过反射动态加载类和调用方法。
4. 反射的优缺点
- 优点:
-
- 灵活性高,可以在运行时动态操作对象。
- 适用于框架开发和动态加载类。
- 缺点:
-
- 性能开销较大,反射操作比直接调用慢。
- 安全性较低,可以访问私有成员,破坏封装性。
什么是 Java 的 SPI(Service Provider Interface)机制?
SPI是一种插件机制,用于运行时动态加载服务的实现。它通过定义接口并提供一种可扩展的方式来让服务提供者运行时注入,实现解耦和模块化设计。
编辑
Java 泛型的作用是什么?
泛型在编译时检查类型安全,可以将代码抽离复用,避免运行时发生类型转换错误。大白话说:能够将运行时异常转为编译时异常。
Java 泛型擦除是什么?
泛型擦除是为了适应java1.4版本及之前版本的向后兼容性,Java在编译阶段将泛型信息擦除,将其转换为该对象的上限,如果没有就转为Object类,这样所有泛型信息都不再保留,称为泛型擦除。
什么是 Java 泛型的上下界限定符?
泛型的上下界定符用于指定泛型传入的范围,比如上界定符为?extends T,指的是传入时需要传入T的子类包括T,而下界定符为? super T,是传入T的父类包括T
Java 中的深拷贝和浅拷贝有什么区别?
深拷贝:递归复制原来对象的属性,生成一份独立于原来的对象,修改不影响原来的对象
浅拷贝:复制引用的内存地址,指向原来的对象,修改影响原来的值
什么是 Java 的 Integer 缓存池?
在大部分使用场景中,发现int的使用大部分在小数值范围,为了提升速度,Java中引入integer缓存池,从-128到127范围,减少内存分支,加快运行速度,减少每次调用生成新的integer对象。
使用场景:自动装箱和值比较
Java 的类加载过程是怎样的?
Java的类加载过程分为:加载,连接,初始化三个阶段
在加载阶段,通过类加载器将类对象转为字节码文件
连接分为验证,准备和解析三个子阶段。验证字节码文件是否安全并为静态变量和方法分配内存空间,将常量池的符号引用转为直接引用
初始化阶段,将执行类的初始化逻辑,并将静态变量和静态代码块的初始化操作整合运行
什么是 Java 的 BigDecimal?
BigDecimal是Java中用于高精度计算的类,属于Java.math包,常用于数学和金融领域。它的特点有:
1.可以处理任何精度的数值,不像double和float限制精度位数
2.BIgDecimal是一个不可变类,每次使用都会创建一个新的对象(使用时要注意性能问题)
3.丰富的功能:提供加减乘除等多种方法
BigDecimal 为什么能保证精度不丢失?
BigDecimal内部是使用整数表示法,通过整数部分intVal和一个记录小数点scale的位置,避免了浮点数计算时的误差。计算时通过整数计算,结合小数点位置和设置的精度去计算。
使用 new String("y") 语句在 Java 中会创建多少个对象?
一个或两个对象。首先会在堆内存中的字符串常量池中查找是否有对应的字符串,如果没有则会先在字符串常量池里创建对应的字符串,再到堆中创建一个对象引用该字符串。如果有的话则只在堆中创建一个字符串。
Java 中 final、finally 和 finalize 各有什么区别?
final是修饰不可变对象。加在类上,类无法被继承和修改。加在方法上,方法无法被重写和修改。加在变量上,变量无法被修改。
finally是在try...catch中,无论如何都会执行。一般用于释放资源。
finalize是Object类中的方法,允许对象在被回收前进行清理操作。少用,因为JVM不保证finalize会被及时执行。
为什么在 Java 中编写代码时会遇到乱码问题?
编码和译码不一致。
为什么 JDK 9 中将 String 的 char 数组改为 byte 数组?
JDK9之前char数组用于存储utf-16编码,每个字符会占两个字节。但如果有些字节只占用一个字节,那么就会浪费空间,比如一些latin-1字符用一个字节。
所以采用byte数组可以减少内存占用。并引入coder来标识编码方式,保持了兼容性。
如何在 Java 中调用外部可执行程序或系统命令?
Runtime.exec或者ProcessBuilder
如果一个线程在 Java 中被两次调用 start() 方法,会发生什么?
线程会发生异常。一个线程只能被调用一次,线程一旦被启动,无法回到初始状态。否则会发生illegalThreadException。
栈和队列在 Java 中的区别是什么?
栈:先进后出,在java中可以用Stack或者LinkedList双端队列实现。使用场景:函数调用
队列:先进先出,可以用Queue(LinkedList)。使用场景:消息队列
Java 的 Optional 类是什么?它有什么用?
它是Java8新出的一个容器类。可以处理如果方法返回的是null对象时类的保存机制,可以减少空指针异常。它提供了一套清楚的处理空值的方法,比如常用的orElse().
Java 的 I/O 流是什么?
I/O流是处理数据读入读出的接口。I/O流分为字节流和字符流,字节流处理8位字节,用于处理二进制数据(视频,文件)。主要类是InputStream和OutputStream及其子类。字符流用于处理16位字节,适合处理文本文件。主要类有reader和writer。
什么是 Java 的网络编程?
网络编程是Java中用于通信的工具。
IP:网络中计算机的地址。
端口号:计算机中应用程序的位置。
Socket:用于在计算机间通信的工具。
协议:通信间需遵循的规则。
TCP:三次握手。比较安全但传输速度不够快
UDP:无连接的协议,但传输速度快。
Java 中的基本数据类型有哪些?
整型:byte(1字节)、short(2)、int(4)、long(8)
浮点型:float(4)、double(8)
字符型:char(2)
布尔型:boolean(根据JVM查看,一般一个或多个)
什么是 Java 中的自动装箱和拆箱?
Integer、Character、Short、Long、Boolean、Double、Byte、Float
自动装箱:将基础数据类型自动转为包装类。常见的例子有:List a = ...会自动将传入的基本数据类型转为对象。
拆箱:将包装类自动转为基础数据类型。
简化代码开发,提高代码阅读性。
什么是 Java 中的迭代器(Iterator)?
迭代器是在Collection接口中用于遍历元素操作元素的工具,不注重集合类的实现。优点:方便快捷操作集合中的元素。核心方法:hasNext查看是否下一个元素,next转到下个元素,remove方法。但其他线程在中途修改会快速失败报错
Java 运行时异常和编译时异常之间的区别是什么?
主要有三个不同:发生时机,处理方式和设计意图
编译时异常:在编译过程中出错,一般要进行try..catch进行捕获或throw抛出错误进行处理,否则无法使用。常见的编译时异常处理:释放资源。设计意图:外部因素引发,需捕获处理
运行时异常:在运行过程中出错,一般是程序逻辑错误,可以在运行前发现解决。常见运行异常:空指针异常,数组越界。设计意图:逻辑漏洞,在调试阶段可以处理。
什么是 Java 中的继承机制?
是三大特征之一,指一个类在原有类的基础上进行extends关键字继承,用于扩展原有对象的方法或者改变原有对象的行为,体现层级结构。是实现多态、抽象和代码复用的关键机制。
什么是 Java 的封装特性?
封装指将所有方法和属性都存在一个对象中,并对外提供查看和修改的接口。封装主要目的是隐藏对象内部实现细节,只暴露必要功能,从而保护数据和降低系统复杂性。
Java 中的访问修饰符有哪些?
public全部范围
protected其他包访问不了
default默认,子类(不同包)访问不了
private只有当前类才能访问
Java 中静态方法和实例方法的区别是什么?
编辑
Java 中 for 循环与 foreach 循环的区别是什么?
for循环是传统遍历方式,提供步长,循环条件,支持索引下标。
foreach基于Iterator类开发,如果循环过程中有修改则会快速失败,不支持索引下标遍历每个对象,速度相对较快,并且代码可读性高。
什么是 Java 中的双亲委派模型?
双亲委派模型是类加载器在加载类的时候,会将其交给父类进行处理,如果父类已加载此类则会直接返回加载后的class对象,否则会再次传给父类,直到初始化加载器(bootstrap ClassLoader),再从上往下进下加载。
Java 中 wait() 和 sleep() 的区别?
wait()是Object类的方法。会释放对应的内存资源,但会释放锁,wait()需要被notify()唤醒必须配合synchronized一起使用,否则会抛出异常。
sleep()是Thread类的方法,会释放对应的内存资源,但不会释放锁资源。sleep(1000)在一秒后会自动唤醒
Java Object 类中有什么方法,有什么作用?
toString()返回对象的字符串表现形式、clone()默认浅拷贝,可重写实现深拷贝、equals()判断对象是否相等、notify()唤醒、notifyAll()、wait()等待、getClass()拿到当前的类、finalize()释放资源
Java 中的字节码是什么?
字节码是编译器编译后处于源代码和机器码的中间表现形式,可以交给虚拟机进行解析为机器码并运行。
什么是 BIO、NIO、AIO?
BIO:传统阻塞I/O格式,调用方发起IO请求时在任务未完成时会阻塞等待其完成后才继续执行。
NIO:非阻塞I/O格式,调用方调用后无需等待线程完成,通过selector实现多路复用技术,可在执行其他任务时等待其线程,等到线程完成在回去执行(边干活边看着煮水)
AIO:异步I/O格式,调用方发起IO请求后无需等待线程。直到操作系统或底层库完成IO操作后通知调用方。(雇了个保姆看煮水)
什么是 Channel?
可以双向读写。常用于非阻塞IO操作,通过实现selector实现多路复用,并发操作。
有四种实现方式:SocketChannel、ServerSocketChannel、DataGramChannel、FileChannel
什么是 Selector?
Selector是NIO中实现IO多路复用的组件,可以通过一个单独的线程管理多个通道(Channel)事件。