八股文-——java基础篇(1)
Java的特点
可移植性:
Java编译器将源代码编译成字节码(bytecode),该字节码可以在任何安装了Java虚拟机(JVM)的系统上运行
面向对象:
java 是一门面向对象的语言,几乎所有的都是对象,oop的特性使得代码易维护
内存管理:
java有自己的垃圾回收机制,自动管理和回收不再使用的对象
java的优与劣
优:oop编程 一次编译到处运行,生态完善spring等各种框架和工具
劣: 性能开销较大,启动时间不如其他原生编译语言(c++,Rust)微服务场景下,可能不如Go之类的快
JVM、JDK、JRE三者之间的关系

-
JVM是Java虚拟机,是Java程序运行的环境。JVM提供了内存管理、垃圾回收、安全性等功能,使得Java程序具备跨平台性
-
JDK是Java开发工具包,是开发Java程序所需的工具集合。JDK提供了开发、编译、调试和运行Java程序所需的全部工具和环境
-
JRE是Java运行时环境,是Java程序运行所需的最小环境。JRE不包含开发工具,只提供Java程序运行所需的运行环境
重写和重载的区别
-
重载发生在本类,重写发生在父类与子类之间
-
重载方法名必须相同,参数列表不同 ;重写的方法名相同且返回值类型必须相同,参数列表也必须相同
-
构造方法不能被重写
接口和抽象类的区别
-
接口要被实现 implement 抽象类要被子类继承
-
接口可以被多继承(多是实现)抽象类只能够单继承
-
接口不能有构造方法,只有声明变量(final修饰) 抽象类可以有构造器,可以有成员变量
-
抽象类不能被 new instance 不能被实例化 ,它和普通的java类没有区别
-
接口只能是public 修饰 抽象类方法可以有 public default protected
浅拷贝和深拷贝的理解
两者都是指对象的拷贝,一个对象中存在两种类型的属性,一种是基本数据类型,一种是实例对象的引用
浅:指挥拷贝基本数据类型的值,以及实例对象的引用地址,并不会复制一份引用地址所指向的对象
深:既会拷贝基本数据类型,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部类指向的不是同一个对象
两者的实现方法:
//浅
//直接**.clone()**即可,也可以实现 Cloneable 接口并简单重写 clone() 方法
//实现 Cloneable 接口
class Address implements Cloneable {
private String street;
public Address(String street) { this.street = street; }
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝 Address 对象
}
//深 重写clone()方法后,手动实现深拷贝
//City 是最内层的对象,只需要实现基本的浅拷贝 Address 包含 City 对象,因此需要在 clone() 中递归拷贝 City
class City implements Cloneable {
private String name;
public City(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝 City(仅复制 name 字段)
}
}
class Address implements Cloneable {
private String street;
private City city;
public Address(String street, City city) {
this.street = street;
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 1. 先调用父类 clone() 复制基本类型(street)
Address cloned = (Address) super.clone();
// 2. 递归拷贝引用类型(city):调用 City 的 clone() 方法
cloned.city = (City) this.city.clone();
return cloned;
}
}
sleep 和 wait 的区别
| 方法 | 定义 | 常见用途 |
|---|---|---|
| wait() | 释放锁并且进入等待状态,直到被其他线程 notify() 或 notifyAll() 唤醒 |
线程间协作,等待某个条件的发生 |
| sleep() | 暂停当前线程一段时间,但不释放锁 | 模拟延迟,控制线程执行节奏 |
区别:
| 特性 | wait() |
sleep() |
|---|---|---|
| 所属类 | Object |
Thread |
| 锁释放 | 释放当前锁 | 不释放锁 |
| 唤醒方式 | 需 notify()/notifyAll() 唤醒 |
固定时间后自动唤醒 |
| 使用场景 | 线程协作(等待条件) | 简单延迟 |
| 同步要求 | 必须在同步块(synchronized)中调用 |
可在任何位置调用 |
wait() 用法(生产者-消费者)
public class ProducerConsumer {
private final Object lock = new Object();
private boolean resourceAvailable = false;
public void produce() throws InterruptedException {
synchronized (lock) {
while (resourceAvailable) {
lock.wait(); // 等待消费者消费,释放锁
}
// 生产资源
resourceAvailable = true;
lock.notify(); // 唤醒消费者
}
}
public void consume() throws InterruptedException {
synchronized (lock) {
while (!resourceAvailable) {
lock.wait(); // 等待生产者生产,释放锁
}
// 消费资源
resourceAvailable = false;
lock.notify(); // 唤醒生产者
}
}
}
sleep() 用法(简单延迟)
Thread.sleep(1000); // 延迟 1 秒,不释放锁
自动拆装箱,int和 Integer 有什么区别
自动装箱(Autoboxing) 和 自动拆箱(Unboxing) 是 Java 为了简化基本类型和包装类型之间的转换而引入的机制
为什么会有这个功能呢?主要是用于java集合中,
List<Inteter> list=new ArrayList<Integer>();list集合如果要放整数的话,只能放对象,不能放基本类型,因此需要将整数自动装箱成对象
自动装箱(Autoboxing):将 基本类型 转换为 对应的包装类型。int primitiveInt = 10; Integer wrappedInt = primitiveInt;
自动拆箱(Unboxing):将 包装类型 转换为 对应的基本类型。Integer wrappedInt = 20; int primitiveInt = wrappedInt;
Integer缓存 机制
Integer 在 -128 到 127 之间的值会 缓存,在这个范围内的 Integer 对象会复用已有实例,超出这个范围的值则会创建新的实例。
==和equals区别
| 特性 | == |
equals() |
|---|---|---|
| 比较内容 | 比较引用地址(基本类型比较值) | 默认比较引用地址,可重写后比较值 |
| 适用类型 | 基本数据类型和引用类型 | 仅适用于引用类型 |
| 性能 | 更快 | 较慢(涉及方法调用) |
| 可重写性 | 不可重写 | 可在类中重写 |
| 空指针安全 | 安全 | 可能抛出 NullPointerException |
String*特殊情况*
虽然 String 是引用类型,但在某些情况下可以直接使用 == 进行比较,这是因为 String 具有常量池机制。但String还是建议使用.equals()去比较字符串,也可使用Objects.equals()避免空指针异常。
String 常量池(String Constant Pool)是 Java 在方法区(JDK 7+ 是堆)中专门为字符串优化的内存区域。
主要特点:
-
相同内容的字符串只存储一份,节省内存。
-
编译时确定的字符串会自动放入常量池。
-
运行时可以手动将字符串添加到常量池中。
public class StringPoolExample {
public static void main(String[] args) {
String s1 = "hello"; // 存入常量池
String s2 = "hello"; // 复用常量池中的 "hello"
String s3 = new String("hello"); // 创建新对象,不在常量池
String s4 = s3.intern(); // 将 s3 放入常量池
System.out.println(s1 == s2); // true, 指向常量池同一地址
System.out.println(s1 == s3); // false, 不同引用
System.out.println(s1 == s4); // true, intern() 返回常量池中的引用
}
}
StringBuffer 和 StringBuilder
StringBuffer 和 StringBuilder 是 可变字符串类,用于处理需要频繁修改字符串的场景
拼接、插入、删除
| 特性 | StringBuffer |
StringBuilder |
|---|---|---|
| 线程安全性 | 线程安全(方法用 synchronized 同步) |
非线程安全(无同步机制) |
| 性能 | 多线程环境下安全,但单线程有额外同步开销 | 单线程环境下更快(无同步开销) |
| 适用场景 | 多线程共享变量的字符串操作 | 单线程下的字符串操作(如循环拼接) |
| 历史背景 | JDK 1.0 就存在 | JDK 5.0 新增(弥补 StringBuffer 单线程低效) |
更多推荐




所有评论(0)