Skip to content

Java枚举、Record、Maven与单元测试完全指南

目录


一、枚举(Enum)

1.1 枚举概述

定义:枚举是一种引用类型,用于表示固定数量的常量值集合。

特点

  • 枚举值默认被 public static final 修饰
  • 每个枚举值都是当前枚举类的对象
  • 枚举类中的构造方法默认是 private
  • 适用于表示事物的固定状态

1.2 枚举的定义与使用

基本语法

java
public enum 枚举类名 {
    枚举值1, 枚举值2, 枚举值3;
}

完整示例

java
public enum State {
    WEIFUKUAN("未付款"),
    YIFUKUAN("已付款"),
    WEISHOUHUO("未收货"),
    YISHOUHUO("已收货");

    private String name;
    
    private State(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

使用示例

java
public class Test01 {
    public static void main(String[] args) {
        State yifukuan = State.YIFUKUAN;
        System.out.println(yifukuan);
        System.out.println(yifukuan.getName());
    }
}

1.3 枚举的常用方法

方法名说明示例
String toString()返回枚举值的名字State.YIFUKUAN.toString()
values()返回所有枚举值数组State[] values = State.values()
valueOf(String str)将字符串转成枚举类型State state = State.valueOf("YIFUKUAN")

方法使用示例

java
public class Test01 {
    public static void main(String[] args) {
        State[] values = State.values();
        for (State value : values) {
            System.out.println(value.getName());
        }
        
        State yishouhuo = State.valueOf("YISHOUHUO");
        System.out.println(yishouhuo);
    }
}

1.4 枚举的应用场景

  • 表示状态:订单状态、支付状态、用户状态等
  • 表示类型:用户类型、会员等级、日志级别等
  • 表示方向:上下左右、东南西北等
  • 表示季节:春夏秋冬

二、Record类与密封类

2.1 Record类(JDK 16+)

概述:Record是一种全新的类型,本质上是一个final类,所有属性都是final修饰。

特点

  • 自动生成构造方法、getter方法、equals、hashCode、toString
  • 只有一个全参构造
  • 重写的equals方法比较所有属性值
  • 可以定义静态字段、静态方法或实例方法
  • 不能定义实例字段
  • 不能声明为abstract
  • 默认父类是java.lang.Record

定义语法

java
public record Person(String name, int age) {
}

使用示例

java
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("zhangsan", 18);
        System.out.println(person1.name() + "..." + person1.age());
    }
}

优势

  • 减少样板代码
  • 自动实现不可变对象
  • 适合作为数据载体(DTO)

2.2 密封类(Sealed Classes,JDK 17)

概述:密封类用于限制哪些类可以继承或实现它。

语法

java
【修饰符】 sealed class 密封类 permits 子类1, 子类2 {
    
}

规则

  • 使用 sealed 修饰符描述
  • 使用 permits 关键字指定允许的子类
  • 子类必须是 sealednon-sealedfinal 修饰
  • sealed修饰的类必须有子类

示例

java
public sealed class Animal permits Dog, Cat {
}

public non-sealed class Dog extends Animal {
}

public non-sealed class Cat extends Animal {
}

接口示例

java
sealed interface Flyable permits Bird {
}

non-sealed class Bird implements Flyable {
}

三、Debug调试工具

3.1 Debug概述

作用:让代码逐行执行,清晰地看到代码中每一个值的变化情况。

3.2 Debug使用步骤

  1. 设置断点:在想要开始debug的代码对应的左边单击,出现"小红点"
  2. 启动Debug:右键,选择"Debug"运行
  3. 逐步执行:使用调试按钮控制代码执行

3.3 Debug常用操作

Debug调试界面

Debug控制按钮

Debug变量查看

常用快捷键

  • F8:单步执行(Step Over)
  • F7:进入方法(Step Into)
  • Shift+F8:跳出方法(Step Out)
  • F9:恢复运行(Resume)

四、Object类核心方法

4.1 Object类概述

定义:Object是所有类的根类(父类),所有类都会直接或间接继承Object类。

4.2 toString()方法

Object中的toString()

java
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

默认行为:返回对象的类名+@+哈希码(地址值)

重写toString()

java
public class Person {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

使用示例

java
public class Test01 {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 10);
        System.out.println(p1); // 自动调用toString()
    }
}

小结:如果输出对象名不想看到地址值,而是想看到对象的内容,就重写toString方法。

4.3 equals()方法

Object中的equals()

java
public boolean equals(Object obj) {
    return (this == obj);
}

默认行为:比较两个对象的地址值

重写equals()的完整实现

java
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

重写equals()的注意事项

  1. 判断是否为同一对象(this == obj)
  2. 判断是否为null
  3. 判断类型是否一致(instanceof或getClass())
  4. 向下转型并比较属性值

使用示例

java
public class Test02 {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 10);
        Person p2 = new Person("张三", 10);
        System.out.println(p1.equals(p2)); // true
        
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.equals(s2)); // true
    }
}

小结:如果比较两个对象不想比较地址值,想比较内容,就重写equals方法。


五、Maven项目管理工具

5.1 为什么使用Maven

5.1.1 从构建角度

Maven构建流程

问题

  • 手动导入jar包,依赖传递困难
  • 脱离IDE后编译、打包、部署复杂
  • 手动打war包部署到Tomcat耗时

解决方案:Maven自动完成编译、打包、部署等构建工作。

5.1.2 从依赖角度

Maven依赖管理

问题

  • jar包数量庞大,依赖关系复杂
  • jar包版本冲突
  • 手动管理成本高

解决方案:Maven自动管理jar包及其依赖关系。

5.2 Maven介绍

概述:Maven是Apache软件基金会维护的Java项目构建和依赖管理工具。

核心作用

  1. 依赖管理:统一管理第三方jar包,自动下载依赖
  2. 项目构建:编译、测试、打包、部署、运行
  3. 模块化管理:提高开发效率

5.3 Maven安装与配置

5.3.1 下载Maven

官网:https://maven.apache.org/docs/history.html

推荐版本:Maven 3.9.11(要求JDK 7+)

5.3.2 安装步骤

  1. 解压:将apache-maven-3.9.11-bin.zip解压到指定位置

  2. 配置环境变量

    • 变量名:MAVEN_HOME
    • 变量值:Maven安装路径
    • Path中添加:%MAVEN_HOME%\bin
  3. 验证安装

bash
mvn -v

Maven安装验证

环境变量配置

5.4 仓库配置

仓库类型

仓库名称作用
本地仓库缓存jar包,第一次从远程下载后存储在本地
中央仓库Maven团队维护的官方仓库
远程仓库阿里云镜像等第三方仓库

Maven仓库结构

5.4.1 配置本地仓库

conf/settings.xml 中配置:

xml
<localRepository>D:\repository</localRepository>

5.4.2 配置阿里云镜像

xml
<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

5.4.3 配置JDK版本

xml
<profile>
    <id>jdk-17</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>17</jdk>
    </activation>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
    </properties>
</profile>

5.5 IDEA集成Maven

配置路径:File → Settings → Build → Build tools → Maven

IDEA集成Maven

配置项

  • Maven home path:Maven安装路径
  • User settings file:settings.xml路径
  • Local repository:本地仓库路径

5.6 创建Maven项目

创建Maven项目

步骤

  1. File → New → Project
  2. 选择Maven构建系统
  3. 填写GroupId、ArtifactId、Version
  4. 选择项目路径

5.7 导入依赖

Maven依赖仓库https://mvnrepository.com/

pom.xml配置

xml
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.38</version>
    </dependency>
</dependencies>

导入依赖后刷新刷新Maven依赖

使用示例

java
public class Demo01Hutool {
    public static void main(String[] args) {
        int[] arr = {5, 3, 4, 5, 7, 5, 4};
        System.out.println(ArrayUtil.max(arr));
    }
}

5.8 Maven坐标详解

坐标组成

xml
<dependency>
    <groupId>组织名/公司名</groupId>
    <artifactId>项目名/模块名</artifactId>
    <version>版本号</version>
</dependency>

示例

xml
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>6.0.0</version>
</dependency>

六、Lombok简化开发

6.1 Lombok概述

作用:通过注解自动生成getter、setter、构造方法、toString、equals等方法。

优势

  • 减少样板代码
  • 提高开发效率
  • 代码更简洁

6.2 Lombok安装

Maven依赖

xml
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

IDEA插件:安装Lombok插件(IDEA 2020.3+已内置)

6.3 Lombok常用注解

注解作用
@Data生成getter、setter、toString、equals、hashCode、无参构造
@Getter生成getter方法
@Setter生成setter方法
@NoArgsConstructor生成无参构造
@AllArgsConstructor生成全参构造
@ToString生成toString方法
@EqualsAndHashCode生成equals和hashCode方法
@Builder生成建造者模式代码

6.4 Lombok使用示例

传统方式

java
public class Person {
    private String name;
    private int age;

    public Person() {}

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

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

Lombok方式

java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private int age;
}

使用示例

java
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("张三");
        person.setAge(18);
        System.out.println(person.getName());
        System.out.println(person);
        
        Person person2 = new Person("李四", 20);
        System.out.println(person2);
    }
}

七、JUnit单元测试

7.1 JUnit概述

作用:单元测试框架,用于测试代码的正确性。

优势

  • 自动化测试
  • 断言验证结果
  • 测试结果可视化

7.2 JUnit安装

Maven依赖

xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>

7.3 JUnit常用注解

注解作用
@Test标记测试方法
@BeforeEach每个测试方法前执行
@AfterEach每个测试方法后执行
@BeforeAll所有测试方法前执行一次
@AfterAll所有测试方法后执行一次

7.4 JUnit断言方法

方法说明
assertEquals(expected, actual)判断是否相等
assertTrue(condition)判断是否为true
assertFalse(condition)判断是否为false
assertNull(value)判断是否为null
assertNotNull(value)判断是否不为null

7.5 JUnit使用示例

java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CalculatorTest {
    
    @Test
    public void testAdd() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 3);
        assertEquals(5, result);
    }
    
    @Test
    public void testSubtract() {
        Calculator calc = new Calculator();
        int result = calc.subtract(5, 3);
        assertEquals(2, result);
    }
}

八、常见面试题

8.1 枚举相关面试题

⭐ 问题1:枚举的本质是什么?

答案

  • 枚举本质上是一个特殊的类,继承自 java.lang.Enum
  • 每个枚举值都是该枚举类的一个实例对象
  • 枚举类中的构造方法默认是private的
  • 枚举值默认被 public static final 修饰

⭐⭐ 问题2:枚举可以继承吗?

答案

  • 枚举类不能继承其他类(因为已经继承了Enum类)
  • 枚举类可以实现接口
  • 枚举类不能被继承(默认是final的)

⭐⭐ 问题3:枚举与常量类的区别?

答案

特性枚举常量类
类型安全✅ 编译时检查❌ 无类型检查
可读性✅ 高⚠️ 一般
功能扩展✅ 支持方法和属性❌ 仅常量值
switch支持✅ 支持❌ 不支持

⭐⭐⭐ 问题4:如何在枚举中定义抽象方法?

答案

java
public enum Operation {
    ADD {
        @Override
        public double apply(double x, double y) {
            return x + y;
        }
    },
    SUBTRACT {
        @Override
        public double apply(double x, double y) {
            return x - y;
        }
    };
    
    public abstract double apply(double x, double y);
}

8.2 Record相关面试题

⭐ 问题1:Record类的特点是什么?

答案

  • Record类是final的,不能被继承
  • 所有属性都是final的,不可变
  • 自动生成全参构造、getter、equals、hashCode、toString
  • 不能定义实例字段
  • 默认父类是java.lang.Record

⭐⭐ 问题2:Record与传统类的区别?

答案

特性Record传统类
不可变性✅ 强制不可变⚠️ 需手动实现
样板代码✅ 自动生成❌ 需手动编写
继承❌ 不能继承✅ 可以继承
可变性❌ 不可变✅ 可变

8.3 Object类相关面试题

⭐ 问题1:==和equals的区别?

答案

特性==equals
基本类型比较值不适用
引用类型比较地址值默认比较地址值,可重写比较内容

⭐⭐ 问题2:重写equals()方法时为什么要重写hashCode()?

答案

  • Java规定:如果两个对象equals返回true,那么它们的hashCode必须相同
  • 如果只重写equals而不重写hashCode,会导致HashSet、HashMap等集合出现bug
  • 示例:
java
@Override
public int hashCode() {
    return Objects.hash(name, age);
}

⭐⭐⭐ 问题3:如何正确重写equals方法?

答案

java
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

8.4 Maven相关面试题

⭐ 问题1:Maven的作用是什么?

答案

  1. 依赖管理:自动下载和管理jar包及其依赖
  2. 项目构建:编译、测试、打包、部署
  3. 模块化管理:支持多模块项目开发

⭐⭐ 问题2:Maven的坐标是什么?

答案: Maven坐标是项目的唯一标识,由三部分组成:

  • groupId:组织名/公司名(如org.springframework)
  • artifactId:项目名/模块名(如spring-core)
  • version:版本号(如6.0.0)

⭐⭐ 问题3:Maven的依赖范围有哪些?

答案

范围编译测试运行打包
compile
test
provided
runtime

⭐⭐⭐ 问题4:Maven依赖冲突如何解决?

答案

  1. 最短路径优先:选择依赖路径最短的版本
  2. 声明优先:先声明的依赖优先
  3. 排除依赖:使用<exclusions>排除冲突依赖
  4. 强制版本:在pom.xml中明确指定版本
xml
<dependency>
    <groupId>com.example</groupId>
    <artifactId>example-lib</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.conflict</groupId>
            <artifactId>conflict-lib</artifactId>
        </exclusion>
    </exclusions>
</dependency>

8.5 Lombok相关面试题

⭐ 问题1:@Data注解的作用?

答案: @Data注解相当于以下注解的组合:

  • @Getter
  • @Setter
  • @ToString
  • @EqualsAndHashCode
  • @RequiredArgsConstructor

⭐⭐ 问题2:Lombok的原理是什么?

答案

  • Lombok在编译期通过注解处理器(Annotation Processor)修改抽象语法树(AST)
  • 在生成字节码之前,自动添加getter、setter等方法
  • 编译后的class文件包含完整的方法实现

⭐⭐⭐ 问题3:Lombok的优缺点?

答案

优点

  • 减少样板代码,提高开发效率
  • 代码更简洁易读
  • 自动维护equals、hashCode等方法

缺点

  • 需要安装插件支持
  • 可能影响代码调试
  • 过度使用可能降低代码可读性
  • 团队需要统一使用

九、实战练习题

9.1 枚举练习题

练习1:季节枚举 ⭐

题目:创建一个季节枚举,包含春夏秋冬四个季节,每个季节有一个描述属性。

参考答案

java
public enum Season {
    SPRING("春天"),
    SUMMER("夏天"),
    AUTUMN("秋天"),
    WINTER("冬天");

    private String description;

    private Season(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

练习2:计算器枚举 ⭐⭐

题目:创建一个计算器枚举,支持加减乘除四种运算。

参考答案

java
public enum Calculator {
    ADD("+") {
        @Override
        public double calculate(double a, double b) {
            return a + b;
        }
    },
    SUBTRACT("-") {
        @Override
        public double calculate(double a, double b) {
            return a - b;
        }
    },
    MULTIPLY("*") {
        @Override
        public double calculate(double a, double b) {
            return a * b;
        }
    },
    DIVIDE("/") {
        @Override
        public double calculate(double a, double b) {
            return a / b;
        }
    };

    private String symbol;

    private Calculator(String symbol) {
        this.symbol = symbol;
    }

    public String getSymbol() {
        return symbol;
    }

    public abstract double calculate(double a, double b);
}

9.2 Record练习题

练习1:学生Record ⭐

题目:创建一个学生Record,包含姓名、年龄、成绩三个属性。

参考答案

java
public record Student(String name, int age, double score) {
    public boolean isExcellent() {
        return score >= 90;
    }
}

public class Test {
    public static void main(String[] args) {
        Student student = new Student("张三", 18, 95.5);
        System.out.println(student.name());
        System.out.println(student.age());
        System.out.println(student.score());
        System.out.println(student.isExcellent());
    }
}

9.3 Object类练习题

练习1:重写equals和hashCode ⭐⭐

题目:创建一个Book类,包含书名和作者,重写equals和hashCode方法。

参考答案

java
import java.util.Objects;

public class Book {
    private String title;
    private String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(title, book.title) && 
               Objects.equals(author, book.author);
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author);
    }

    @Override
    public String toString() {
        return "Book{title='" + title + "', author='" + author + "'}";
    }
}

9.4 Maven练习题

练习1:创建Maven项目 ⭐

题目:创建一个Maven项目,导入Hutool工具包,并使用ArrayUtil工具类。

步骤

  1. 创建Maven项目
  2. 在pom.xml中添加Hutool依赖
  3. 编写测试代码

参考答案

xml
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.38</version>
    </dependency>
</dependencies>
java
import cn.hutool.core.util.ArrayUtil;

public class Demo {
    public static void main(String[] args) {
        int[] arr = {5, 3, 8, 1, 9};
        System.out.println("最大值:" + ArrayUtil.max(arr));
        System.out.println("最小值:" + ArrayUtil.min(arr));
        System.out.println("是否包含5:" + ArrayUtil.contains(arr, 5));
    }
}

9.5 Lombok练习题

练习1:使用Lombok创建实体类 ⭐

题目:使用Lombok创建一个User类,包含用户名、密码、邮箱三个属性。

参考答案

java
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String username;
    private String password;
    private String email;
}

public class Test {
    public static void main(String[] args) {
        User user = new User("zhangsan", "123456", "zhangsan@example.com");
        System.out.println(user.getUsername());
        System.out.println(user);
    }
}

9.6 综合练习题

练习1:订单状态管理 ⭐⭐⭐

题目:创建一个订单系统,使用枚举表示订单状态,使用Record表示订单信息,使用Lombok简化代码。

参考答案

java
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

public enum OrderStatus {
    PENDING("待支付"),
    PAID("已支付"),
    SHIPPED("已发货"),
    DELIVERED("已送达"),
    CANCELLED("已取消");

    private String description;

    private OrderStatus(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

public record Order(String orderId, String productName, double amount, OrderStatus status) {
    public boolean isPaid() {
        return status == OrderStatus.PAID || status == OrderStatus.SHIPPED || status == OrderStatus.DELIVERED;
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
    private String customerId;
    private String name;
    private String phone;
}

public class OrderSystem {
    public static void main(String[] args) {
        Customer customer = new Customer("C001", "张三", "13800138000");
        Order order = new Order("O001", "iPhone 15", 7999.0, OrderStatus.PENDING);
        
        System.out.println("客户信息:" + customer);
        System.out.println("订单信息:" + order);
        System.out.println("订单状态:" + order.status().getDescription());
        System.out.println("是否已支付:" + order.isPaid());
    }
}

十、学习建议

10.1 学习路径

  1. 基础阶段(1-2天)

    • 掌握枚举的定义和使用
    • 理解Object类的toString和equals方法
    • 学会Debug调试工具
  2. 进阶阶段(2-3天)

    • 掌握Maven项目创建和依赖管理
    • 理解Record类和密封类
    • 学会使用Lombok简化开发
  3. 实战阶段(3-5天)

    • 使用JUnit编写单元测试
    • 综合运用所学知识完成项目
    • 练习面试题和编程题

10.2 重点掌握

  • ✅ 枚举的定义和使用场景
  • ✅ Maven的安装、配置和使用
  • ✅ Lombok的常用注解
  • ✅ Object类的toString和equals方法重写
  • ✅ JUnit单元测试的基本使用

10.3 学习资源


附录:常用Maven依赖

xml
<dependencies>
    <!-- Hutool工具包 -->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.38</version>
    </dependency>
    
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- JUnit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>