Java 基础

本文最后更新于 2 分钟前,文中所描述的信息可能已发生改变。

基本类型和包装类型

基本类型和包装类型的种类(8 种)
  • 基本类型:byte、short、int、long、float、double、char、boolean。
  • 包装类型:Byte、Short、Integer、Long、Float、Double、Character、Boolean。
基本类型和包装类型的区别?
  • 用途:除了定义一些常量和局部变量之外,在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且,包装类型可用于泛型,而基本类型不可以。
  • 存储方式:基本类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基础类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,几乎所有对象示例都存在于堆中。
  • 占用空间:相比于包装类型(对象类型), 基本类型占用的空间往往非常小。
  • 默认值:成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null。
  • 比较方式:对于基本类型来说,== 比较的是值。对于包装数据类型来说,== 比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用 equals() 方法。
浮点数运算带来的精度问题?

浮点数运算的精度问题是由于浮点数的二进制表示方式导致的。浮点数在计算机中是以二进制的形式存储的,而二进制无法精确表示某些十进制小数,比如 0.1,会被近似表示为一个无限循环小数。

解决方法:可以使用 BigDecimal 类来解决浮点数运算的精度问题。

String 为什么不可变?
  • 由于使用 final 关键字,String 对象被设计成不可变的。
  • 不可变的字符串有利于字符串常量池(位于方法区,存储字符串常量)的实现,提高字符串的共享性和安全性。
String,StringBuffer,StringBuilder 的区别?
  • String 是不可变的字符串,每次修改都会生成新的字符串对象,适用于字符串不经常变化的场景。
  • StringBuffer 是线程安全的可变字符串,适用于多线程场景。
  • StringBuilder 是非线程安全的可变字符串,适用于单线程场景。
字符串常量池拼接原理

字符串常量池拼接原理是编译期优化,比如String s1 = "ab",String s2 = "a" + "b",这里的s2是由两个字符串常量拼接而成,在编译期语句会转换成String s2 = "ab";换而言之,class 文件中不存在"a""b"(特殊情况,"a"为字面量,但是不会再次创建对象),所以s1s2都是串池中的"ab",表示的是同一个对象。

面向对象

面向对象(Object-Oriented Programming, OOP)是 Java 的核心编程范式,通过定义类和对象来组织程序。主要概念包括:

  • 类:描述一组具有相同属性和行为的对象的模板。
  • 对象:类的示例,具有状态和行为。
  • 封装:通过将数据和方法封装在类中,控制访问权限,提高安全性和可维护性。
  • 继承:通过继承父类,子类可以重用父类的属性和方法,并且可以扩展或重写父类的方法。
  • 多态:通过接口或继承实现不同对象以统一的方式被调用的能力,具体执行方法由实际对象类型决定。
面向对象的三大特征

封装、继承、多态。

重载与重写

反射

异常

JAR (Java Archive)

打包成 jar 包之后这些依赖包的位置在哪呢,Java 是怎么识别的?

在我的项目配置,项目中使用 maven 来管理依赖和打包,在编译后,会打包到./target/,Java 是通过 classpath 来识别依赖的。

  1. 普通打包:java -cp xxx.jar:lib/* com.example.demo.DemoApplication,需要使用-cp指定依赖包的位置。
  2. spring-boot-maven-plugin 打包:java -jar xxx.jar,spring-boot-loader 会自动识别BOOT-INF/lib下的依赖包。

Java 版本特性

Java 17

你了解 Java 的 Record 类吗?它解决了什么问题?

Record 是 Java 14 引入的预览特性,Java 17 正式发布。它是一种特殊的类,专门用来存储数据。

示例代码:

java
// 传统写法(繁琐)
public class User {
    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public boolean equals(Object obj) {
        // 一堆代码...
    }

    @Override
    public int hashCode() {
        // 一堆代码...
    }

    @Override
    public String toString() {
        // 一堆代码...
    }
}

// Record写法(简洁)
public record User(String name, int age) {
    // 自动生成构造器、getter、equals、hashCode、toString

    // 可以添加自定义方法
    public boolean isAdult() {
        return age >= 18;
    }

    // 可以添加验证逻辑
    public User {
        if (age < 0) {
            throw new IllegalArgumentException("年龄不能为负数");
        }
    }
}

使用场景:

  • DTO 对象
  • 配置类
  • 返回多个值的方法
  • 不可变数据载体
听说过虚拟线程吗?它和传统线程有什么区别?

示例代码:

java
// 传统线程创建(重量级)
Thread thread = new Thread(() -> {
    // 执行任务
});
thread.start();

// 虚拟线程创建(轻量级)
Thread virtualThread = Thread.ofVirtual().start(() -> {
    // 执行任务
});

// 或者使用Executors
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> {
        // 高并发IO任务
        return "result";
    });
}

优势:

  • 轻量级:创建成本极低,可以创建百万级别
  • 高并发:特别适合 IO 密集型任务
  • 简化编程:不需要异步回调,代码更直观

适用场景:

  • Web 服务器处理大量请求
  • 数据库连接池
  • 网络 IO 操作
  • 文件处理
模式匹配(Pattern Matching)

示例代码:

java
// instanceof的模式匹配(Java 17)
public String formatObject(Object obj) {
    if (obj instanceof String s) {
        return "String: " + s.toUpperCase();
    } else if (obj instanceof Integer i) {
        return "Integer: " + (i * 2);
    } else if (obj instanceof List<?> list) {
        return "List size: " + list.size();
    }
    return "Unknown type";
}

// Switch表达式的模式匹配(预览特性)
public String processValue(Object value) {
    return switch (value) {
        case String s -> "String: " + s;
        case Integer i -> "Integer: " + i;
        case null -> "Null value";
        default -> "Unknown: " + value.toString();
    };
}

排序

快速排序

  • 采用分治思想,选择基准值,分区交换
  • 时间复杂度平均 O(n log n),最坏 O(n^2)
  • 非稳定排序

堆排序

  • 基于大根堆或小根堆,先建堆后调整
  • 时间复杂度 O(n log n)
  • 不稳定排序

常见问题

Java 里的 sort 方法用的是什么排序算法?
  • 基本类型数组:双轴快速排序(Dual-Pivot Quicksort)。
  • 对象数组 & 集合:TimSort(归并 + 插入优化的稳定排序)。
材料计算常用资源