# 基于JAVA基础知识的学生管理系统 **Repository Path**: brightXML/SMS ## Basic Information - **Project Name**: 基于JAVA基础知识的学生管理系统 - **Description**: 学生管理系统V1.0 仅包含JAVA基础知识,用于知识回顾以及编程思维的扩展。 无数据库,仅使用TXT文件储存相关数据文件。 - **Primary Language**: Java - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-20 - **Last Updated**: 2025-10-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java ## README # Java 基础全面总结 ## 一、Java 语言概述 ### 1. Java 特点 - **可移植性**:一次编写,到处运行 - **操作简单**:语法简洁,易于学习 - **贴近人类语言**:面向对象,易于理解 - **强跨平台特性**:基于 JVM 实现跨平台 - **健壮性**:自动内存管理,异常处理机制 ### 2. Java 体系结构 ``` JVM (Java虚拟机) → JRE (Java运行时环境) → JDK (Java开发工具集) ``` - **JVM**:不同平台有不同的 JVM,实现跨平台 - **JRE**:包含 JVM + 核心类库 - **JDK**:包含 JRE + 开发工具 ### 3. 环境搭建步骤 1. 下载 JDK(推荐 .zip 压缩包版本) 2. 解压 JDK 文件 3. 配置环境变量: - 新建 `JAVA_HOME`:JDK 安装目录 - 修改 `Path`:添加 `;%JAVA_HOME%\bin` 4. 重启 CMD 验证 ## 二、入门程序编写 ### 1. 第一个 Java 程序 ```java class Hellowood { public static void main(String args[]) { System.out.print("Hello"); } } ``` ### 2. 编译和执行 ```cmd javac Hellowood.java # 编译 java Hellowood # 执行 ``` ## 三、Java 基础语法 ### 1. 命名规范 - **类名/接口名**:大驼峰 `HelloWorld` - **方法/变量名**:小驼峰 `helloWorld` - **包名**:全部小写 - **常量名**:全部大写 ### 2. 数据类型 #### 基本数据类型 | 类型 | 大小 | 范围 | 示例 | | ------- | ---- | ------------ | ---------------------- | | byte | 8位 | -128~127 | `byte b = 10;` | | short | 16位 | -32768~32767 | `short s = 100;` | | int | 32位 | -2^31~2^31-1 | `int i = 1000;` | | long | 64位 | -2^63~2^63-1 | `long l = 1000L;` | | float | 32位 | 单精度 | `float f = 3.14F;` | | double | 64位 | 双精度 | `double d = 3.14;` | | char | 16位 | Unicode字符 | `char c = 'A';` | | boolean | 1位 | true/false | `boolean flag = true;` | #### 引用数据类型 - 类、接口、数组等 ### 3. 变量和常量 ```java // 变量声明和初始化 int a; // 声明 a = 123; // 赋值 int b = 456; // 声明并初始化 // 常量声明 final int MAX_VALUE = 100; final double PI; PI = 3.14159; // 延后赋值 ``` ## 四、运算符和流程控制 ### 1. 运算符类型 - **算术运算符**:`+ - * / %` - **赋值运算符**:`= += -= *= /=` - **关系运算符**:`< > == != <= >=` - **逻辑运算符**:`&& || ! & |` - **位运算符**:`& | ~ ^` - **三目运算符**:`条件 ? 值1 : 值2` ### 2. 流程控制语句 #### if-else 语句 ```java if(score >= 91 && score <= 100) { System.out.println("A"); } else if(score >= 81 && score <= 90) { System.out.println("B"); } else if(score >= 61 && score <= 80) { System.out.println("C"); } else if(score >= 0 && score <= 60) { System.out.println("D"); } else { System.out.println("无效分数"); } ``` #### switch 语句 ```java switch(score/10) { case 10: case 9: System.out.println("A"); break; case 8: System.out.println("B"); break; case 7: case 6: System.out.println("C"); break; case 5: case 4: case 3: case 2: case 1: case 0: System.out.println("D"); break; default: System.out.println("无效分数"); } ``` #### 循环语句 ```java // while循环 int i = 0; while(i < 10) { System.out.println(i); i++; } // do-while循环 int j = 0; do { System.out.println(j); j++; } while(j < 10); // for循环 for(int k = 0; k < 10; k++) { System.out.println(k); } ``` ## 五、数组 ### 1. 一维数组 ```java // 声明和初始化 int[] arr1 = new int[5]; int[] arr2 = {1, 2, 3, 4, 5}; // 访问元素 arr1[0] = 10; int value = arr1[0]; // 遍历数组 for(int i = 0; i < arr1.length; i++) { System.out.println(arr1[i]); } ``` ### 2. 二维数组 ```java // 声明和初始化 int[][] matrix = new int[3][3]; int[][] matrix2 = {{1,2,3}, {4,5,6}, {7,8,9}}; // 不规则数组 int[][] irregular = new int[3][]; irregular[0] = new int[2]; irregular[1] = new int[3]; ``` ## 六、面向对象编程 ### 1. 类和对象 ```java // 类定义 class Dog { // 属性 private String name; private int age; // 构造方法 public Dog(String name, int age) { this.name = name; this.age = age; } // 方法 public void bark() { System.out.println(name + "在叫"); } } // 使用类 Dog myDog = new Dog("旺财", 3); myDog.bark(); ``` ### 2. 封装 ```java class Human { private String name; private boolean gender; // true-男, false-女 private int age; // getter和setter public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isMan() { return gender; } public void setGender(boolean gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { if(age > 0 && age < 150) { this.age = age; } } } ``` ### 3. 继承 ```java class Animal { public void eat() { System.out.println("吃东西"); } public void drink() { System.out.println("喝水"); } } class Rabbit extends Animal { public void jump() { System.out.println("兔子跳"); } } class Horse extends Animal { public void run() { System.out.println("马奔跑"); } } ``` ### 4. 多态 ```java class Duck { public void quack() { System.out.println("嘎嘎叫"); } public void fly() { System.out.println("飞了"); } } class RobotDuck extends Duck { @Override public void quack() { System.out.println("机械声叫"); } @Override public void fly() { System.out.println("喷气飞行"); } } class RubberDuck extends Duck { @Override public void quack() { System.out.println("吱吱叫"); } @Override public void fly() { System.out.println("不能飞"); } } // 多态使用 Duck duck1 = new RobotDuck(); Duck duck2 = new RubberDuck(); duck1.quack(); // 机械声叫 duck2.quack(); // 吱吱叫 ``` ### 5. 抽象类和接口 ```java // 抽象类 abstract class AbstractClass { public abstract void abstractMethod(); public void concreteMethod() { System.out.println("具体方法"); } } // 接口 interface Flyable { void fly(); } interface Swimmable { void swim(); } // 类实现接口 class SuperDuck implements Flyable, Swimmable { public void fly() { System.out.println("飞"); } public void swim() { System.out.println("游"); } } ``` ## 七、异常处理 ### 1. 异常分类 - **Error**:系统错误,程序无法处理 - Exception :程序可处理的异常 - RuntimeException:运行时异常 - 其他Exception:受检异常 ### 2. 异常处理机制 ```java try { // 可能抛出异常的代码 int result = 10 / 0; } catch(ArithmeticException e) { // 捕获特定异常 System.out.println("算术异常: " + e.getMessage()); } catch(Exception e) { // 捕获其他异常 e.printStackTrace(); } finally { // 最终执行块 System.out.println("最终清理"); } // 抛出异常 public void riskyMethod() throws IOException { throw new IOException("自定义异常"); } ``` ## 八、Java 常用类库详解 ### 一、String 和 StringBuffer/StringBuilder #### 1. String 类详解 ##### 1.1 不可变性 - String 对象一旦创建就不可更改 - 所有看似修改 String 的方法都是返回新对象 - 优点:线程安全、可以缓存哈希值 - 缺点:频繁修改时性能较差 ##### 1.2 常用方法 ```java // 创建字符串 String str1 = "Hello"; // 字面量方式 String str2 = new String("World"); // 构造方法 char[] chars = {'J','a','v','a'}; String str3 = new String(chars); // 字符数组 // 字符串比较 boolean eq1 = str1.equals("Hello"); // true,内容比较 boolean eq2 = str1 == "Hello"; // true,字符串常量池 boolean eq3 = str1.equalsIgnoreCase("hello");// true,忽略大小写 // 字符串查找 int index1 = str1.indexOf('e'); // 1 int index2 = str1.indexOf("ll"); // 2 int index3 = str1.lastIndexOf('l'); // 3 boolean contains = str1.contains("ell"); // true // 字符串操作 String sub = str1.substring(1, 4); // "ell" String upper = str1.toUpperCase(); // "HELLO" String lower = str1.toLowerCase(); // "hello" String trimmed = " Hello ".trim(); // "Hello" String replaced = str1.replace('l', 'L'); // "HeLLo" // 字符串分割 String[] parts = "a,b,c".split(","); // ["a","b","c"] // 格式化字符串 String formatted = String.format("Name: %s, Age: %d", "Alice", 25); ``` ##### 1.3 字符串常量池 - JVM 为字符串维护的特殊存储区域 - 使用字面量创建字符串时会检查常量池 - 使用 new 创建字符串对象不会使用常量池 - `intern()` 方法可以将字符串放入常量池 #### 2. StringBuffer 和 StringBuilder ##### 2.1 可变字符串 ```java // StringBuffer (线程安全) StringBuffer sb1 = new StringBuffer(); sb1.append("Hello").append(" ").append("World"); sb1.insert(5, ","); sb1.delete(5, 6); sb1.reverse(); String result1 = sb1.toString(); // StringBuilder (非线程安全,性能更高) StringBuilder sb2 = new StringBuilder(); sb2.append("Java").append(" is").append(" cool"); String result2 = sb2.toString(); ``` ##### 2.2 性能比较 ```java // 测试字符串拼接性能 long start = System.currentTimeMillis();//用于获取自 1970年1月1日 00:00:00 UTC 起到当前时间的总毫秒数。它常用于性能测试、计时操作或生成唯一标识符。 String result = ""; for (int i = 0; i < 10000; i++) { result += i; // 每次循环创建新String对象 } long end = System.currentTimeMillis(); System.out.println("String 耗时: " + (end - start) + "ms"); start = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb.append(i); // 直接修改内部字符数组 } end = System.currentTimeMillis(); System.out.println("StringBuilder 耗时: " + (end - start) + "ms"); ``` ##### 2.3 选择策略 - 单线程环境:使用 StringBuilder - 多线程环境:使用 StringBuffer - 少量字符串操作:使用 String - 大量字符串拼接:使用 StringBuilder/StringBuffer ### 二、数学和日期类 #### 1. Math 类 ##### 1.1 基本数学运算 ```java // 基本运算 double abs = Math.abs(-3.14); // 3.14 double max = Math.max(10, 20); // 20 double min = Math.min(10, 20); // 10 double pow = Math.pow(2, 3); // 8.0 double sqrt = Math.sqrt(16); // 4.0 // 三角函数 double sin = Math.sin(Math.PI / 2); // 1.0 double cos = Math.cos(Math.PI); // -1.0 double tan = Math.tan(Math.PI / 4); // ≈1.0 // 对数运算 double log = Math.log(Math.E); // 1.0 double log10 = Math.log10(100); // 2.0 ``` ##### 1.2 随机数生成 ```java // 生成0.0-1.0之间的随机数 double random = Math.random(); // 生成指定范围的随机整数 (0-99) int randomInt = (int)(Math.random() * 100); // 生成指定范围的随机整数 (min-max) int min = 10, max = 20; int rangeRandom = min + (int)(Math.random() * (max - min + 1)); ``` #### 2. Random 类 ```java Random random = new Random(); // 生成随机整数 int randInt = random.nextInt(); // 任意整数 int randBound = random.nextInt(100); // 0-99 // 生成随机布尔值 boolean randBool = random.nextBoolean(); // 生成随机浮点数 double randDouble = random.nextDouble(); float randFloat = random.nextFloat(); // 设置种子(相同种子产生相同序列) Random seeded = new Random(12345); ``` #### 3. 日期时间类 ##### 3.1 Date 类(旧API) ```java Date now = new Date(); // 当前时间 Date specific = new Date(121, 9, 15); // 2021年10月15日(已过时) // 日期比较 boolean after = now.after(specific); // true boolean before = now.before(specific); // false long diff = now.getTime() - specific.getTime(); // 毫秒差 // 格式化输出 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String formatted = sdf.format(now); // "2023-07-20 14:30:45" ``` ##### 3.2 Calendar 类 ```java Calendar cal = Calendar.getInstance(); // 当前时间 // 设置日期 cal.set(2023, Calendar.JULY, 20); // 月份从0开始 cal.set(Calendar.HOUR_OF_DAY, 14); cal.set(Calendar.MINUTE, 30); cal.set(Calendar.SECOND, 0); // 获取日期信息 int year = cal.get(Calendar.YEAR); // 2023 int month = cal.get(Calendar.MONTH) + 1; // 7(需要+1) int day = cal.get(Calendar.DAY_OF_MONTH); // 20 int hour = cal.get(Calendar.HOUR_OF_DAY); // 14 int weekday = cal.get(Calendar.DAY_OF_WEEK); // 星期几(1-7) // 日期计算 cal.add(Calendar.DAY_OF_MONTH, 5); // 加5天 cal.add(Calendar.MONTH, -1); // 减1个月 // 转换为Date Date date = cal.getTime(); ``` ##### 3.3 Java 8 新日期时间 API ```java // LocalDate - 日期 LocalDate today = LocalDate.now(); LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 1); // LocalTime - 时间 LocalTime nowTime = LocalTime.now(); LocalTime specificTime = LocalTime.of(14, 30, 45); // LocalDateTime - 日期时间 LocalDateTime nowDateTime = LocalDateTime.now(); LocalDateTime specificDateTime = LocalDateTime.of(2023, 7, 20, 14, 30); // 日期操作 LocalDate tomorrow = today.plusDays(1); LocalDate nextWeek = today.plusWeeks(1); LocalDate lastMonth = today.minusMonths(1); // 日期比较 boolean isAfter = today.isAfter(birthday); boolean isBefore = today.isBefore(birthday); boolean isEqual = today.isEqual(birthday); // 格式化 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); String formatted = nowDateTime.format(formatter); // 解析 LocalDateTime parsed = LocalDateTime.parse("2023/07/20 14:30:45", formatter); ``` ### 三、Java Arrays 工具类详解 Arrays 类是 Java 中用于操作数组的实用工具类,提供了各种静态方法来操作数组(如排序、搜索、填充、比较等)。下面是对 Arrays 类的全面总结: #### 一、核心功能概览 #### 1. 数组转字符串 ``` int[] numbers = {1, 2, 3}; String str = Arrays.toString(numbers); // 输出: "[1, 2, 3]" ``` #### 2. 数组填充 ``` int[] arr = new int[5]; Arrays.fill(arr, 10); // 全部填充为10 → [10, 10, 10, 10, 10] Arrays.fill(arr, 1, 3, 5); // 从索引1到3(不包括)填充为5 → [10, 5, 5, 10, 10] ``` #### 3. 数组排序 ``` int[] numbers = {3, 1, 4, 2}; Arrays.sort(numbers); // 升序排序 → [1, 2, 3, 4] // 部分排序 Arrays.sort(numbers, 1, 3); // 只排序索引1到3(不包括)→ [3, 1, 2, 4] // 自定义排序(Java 8+) Integer[] nums = {3, 1, 4, 2}; Arrays.sort(nums, Comparator.reverseOrder()); // 降序排序 → [4, 3, 2, 1] ``` #### 4. 二分查找 ``` int[] sorted = {1, 2, 3, 4, 5}; int index = Arrays.binarySearch(sorted, 3); // 返回2(找到) int notFound = Arrays.binarySearch(sorted, 6); // 返回负值(未找到) ``` #### 二、进阶功能详解 #### 1. 数组比较 ``` int[] arr1 = {1, 2, 3}; int[] arr2 = {1, 2, 3}; boolean equal = Arrays.equals(arr1, arr2); // true // 多维数组比较 int[][] deep1 = {{1,2}, {3,4}}; int[][] deep2 = {{1,2}, {3,4}}; boolean deepEqual = Arrays.deepEquals(deep1, deep2); // true ``` #### 2. 数组复制 ``` int[] original = {1, 2, 3}; int[] copy = Arrays.copyOf(original, 5); // [1, 2, 3, 0, 0] int[] rangeCopy = Arrays.copyOfRange(original, 1, 3); // [2, 3] ``` #### 3. 数组流处理(Java 8+) ``` int[] numbers = {1, 2, 3}; int sum = Arrays.stream(numbers).sum(); long count = Arrays.stream(numbers).count(); double avg = Arrays.stream(numbers).average().orElse(0); ``` #### 4. 并行排序(大数据量优化) ``` int[] largeArray = new int[1000000]; // 使用多核并行排序 Arrays.parallelSort(largeArray); ``` #### 三、特殊类型数组处理 #### 1. 对象数组排序 ``` String[] names = {"Alice", "Bob", "Charlie"}; Arrays.sort(names); // 自然顺序排序 Arrays.sort(names, Comparator.comparing(String::length)); // 按长度排序 ``` #### 2. 并行前缀计算 ``` int[] nums = {1, 2, 3, 4}; Arrays.parallelPrefix(nums, (a, b) -> a + b); // [1, 3, 6, 10] ``` #### 3. 集合与数组转换 ``` List list = Arrays.asList("A", "B", "C"); // 固定大小列表 String[] array = list.toArray(new String[0]); // 集合转数组 ``` #### 四、性能与注意事项 1. **排序算法选择**: - 基本类型:双轴快速排序(O(n log n)) - 对象类型:TimSort(稳定排序) 2. **二分查找前提**: ``` // 必须先排序! int[] unsorted = {3, 1, 2}; Arrays.binarySearch(unsorted, 2); // 结果不可靠! ``` 3. **大数组处理**: ``` // 超过1万元素考虑并行排序 Arrays.parallelSort(largeArray); ``` 4. **多维数组处理**: ``` int[][] matrix = {{1,2}, {3,4}}; System.out.println(Arrays.deepToString(matrix)); // 深度输出 ``` #### 五、完整方法列表 | 方法签名 | 功能描述 | | ------------------------------------------------------- | ------------ | | `static void sort(int[] a)` | 数组排序 | | `static void sort(int[] a, int fromIndex, int toIndex)` | 部分排序 | | `static int binarySearch(int[] a, int key)` | 二分查找 | | `static boolean equals(int[] a, int[] b)` | 数组比较 | | `static void fill(int[] a, int val)` | 填充数组 | | `static int[] copyOf(int[] original, int newLength)` | 数组复制 | | `static List asList(T... a)` | 数组转集合 | | `static String toString(int[] a)` | 数组转字符串 | | `static void parallelSort(int[] a)` | 并行排序 | | `static IntStream stream(int[] array)` | 生成流 | #### 六、最佳实践示例 #### 1. 安全数组比较 ```java // 避免空指针 boolean safeEquals(int[] a, int[] b) { if (a == b) return true; if (a == null || b == null) return false; return Arrays.equals(a, b); } ``` #### 2. 灵活数组初始化 ``` // 初始化并填充 int[] squares = new int[10]; Arrays.setAll(squares, i -> (i+1)*(i+1)); // [1, 4, 9, ..., 100] ``` #### 3. 对象数组处理 ``` Person[] people = {new Person("Alice"), new Person("Bob")}; Arrays.sort(people, Comparator.comparing(Person::getName)); ``` #### 4. 高效数组拷贝 ``` // 系统级拷贝(性能最优) int[] fastCopy = new int[source.length]; System.arraycopy(source, 0, fastCopy, 0, source.length); ``` Arrays 工具类作为 Java 数组操作的瑞士军刀,合理使用可以显著提高开发效率和代码质量。建议: 1. 优先使用 `Arrays` 方法而非手动实现 2. 大数据集考虑并行操作 3. 注意排序前提条件 4. 结合 Java 8 Stream API 进行复杂处理 ### 三、集合框架详解 #### 1. List 接口实现类 ##### 1.1 ArrayList ```java // 创建ArrayList List arrayList = new ArrayList<>(); // 添加元素 arrayList.add("Apple"); arrayList.add("Banana"); arrayList.add(1, "Orange"); // 在指定位置插入 // 访问元素 String fruit = arrayList.get(0); // "Apple" int index = arrayList.indexOf("Banana"); // 2 // 修改元素 arrayList.set(1, "Pear"); // 替换元素 // 删除元素 arrayList.remove("Pear"); // 按对象删除 arrayList.remove(0); // 按索引删除 // 遍历方式 // 1. for循环 for (int i = 0; i < arrayList.size(); i++) { System.out.println(arrayList.get(i)); } // 2. 增强for循环 for (String item : arrayList) { System.out.println(item); } // 3. 迭代器 Iterator it = arrayList.iterator(); while (it.hasNext()) { System.out.println(it.next()); } // 4. forEach + Lambda arrayList.forEach(System.out::println); // 转换为数组 String[] array = arrayList.toArray(new String[0]); ``` ##### 1.2 LinkedList ```java // 创建LinkedList List linkedList = new LinkedList<>(); // 特有方法 LinkedList ll = (LinkedList) linkedList; ll.addFirst("First"); // 添加到头部 ll.addLast("Last"); // 添加到尾部 String first = ll.getFirst(); // 获取头部元素 String last = ll.getLast(); // 获取尾部元素 ll.removeFirst(); // 移除头部元素 ll.removeLast(); // 移除尾部元素 ``` ##### 1.3 Vector ```java // Vector是线程安全的ArrayList List vector = new Vector<>(); vector.add("Element"); // 其他方法与ArrayList类似 ``` #### 2. Set 接口实现类 ##### 2.1 HashSet ```java // 创建HashSet Set hashSet = new HashSet<>(); // 添加元素 hashSet.add("Apple"); hashSet.add("Banana"); hashSet.add("Apple"); // 重复元素不会被添加 // 检查元素 boolean contains = hashSet.contains("Apple"); // true // 删除元素 hashSet.remove("Banana"); // 遍历方式 for (String item : hashSet) { System.out.println(item); } // 大小和判空 int size = hashSet.size(); // 1 boolean empty = hashSet.isEmpty(); // false ``` ##### 2.2 TreeSet ```java // 创建TreeSet(自然排序) Set treeSet = new TreeSet<>(); treeSet.add("Orange"); treeSet.add("Apple"); treeSet.add("Banana"); // 遍历时自动排序 for (String fruit : treeSet) { System.out.println(fruit); // Apple, Banana, Orange } // 自定义排序 Set customSort = new TreeSet<>(Comparator.reverseOrder()); customSort.add(3); customSort.add(1); customSort.add(2); // 遍历顺序:3, 2, 1 ``` ##### 2.3 LinkedHashSet ```java // 创建LinkedHashSet(保持插入顺序) Set linkedHashSet = new LinkedHashSet<>(); linkedHashSet.add("Apple"); linkedHashSet.add("Banana"); linkedHashSet.add("Orange"); // 遍历顺序与插入顺序一致 for (String fruit : linkedHashSet) { System.out.println(fruit); // Apple, Banana, Orange } ``` #### 3. Map 接口实现类 ##### 3.1 HashMap ```java // 创建HashMap Map hashMap = new HashMap<>(); // 添加键值对 hashMap.put("Apple", 10); hashMap.put("Banana", 20); hashMap.put("Orange", 15); // 获取值 int apples = hashMap.get("Apple"); // 10 int defaultValue = hashMap.getOrDefault("Pear", 0); // 0 // 检查键/值 boolean hasKey = hashMap.containsKey("Apple"); // true boolean hasValue = hashMap.containsValue(20); // true // 删除键值对 hashMap.remove("Banana"); // 遍历方式 // 1. 遍历键 for (String key : hashMap.keySet()) { System.out.println(key + ": " + hashMap.get(key)); } // 2. 遍历值 for (Integer value : hashMap.values()) { System.out.println(value); } // 3. 遍历键值对 for (Map.Entry entry : hashMap.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } // 4. forEach + Lambda hashMap.forEach((k, v) -> System.out.println(k + ": " + v)); ``` ##### 3.2 TreeMap ```java // 创建TreeMap(按键自然排序) Map treeMap = new TreeMap<>(); treeMap.put("Orange", 15); treeMap.put("Apple", 10); treeMap.put("Banana", 20); // 遍历时按键排序 for (Map.Entry entry : treeMap.entrySet()) { System.out.println(entry.getKey()); // Apple, Banana, Orange } // 自定义排序 Map customSort = new TreeMap<>(Comparator.reverseOrder()); customSort.put(3, "Three"); customSort.put(1, "One"); customSort.put(2, "Two"); // 遍历顺序:3, 2, 1 ``` ##### 3.3 LinkedHashMap ```java // 创建LinkedHashMap(保持插入顺序) Map linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("Apple", 10); linkedHashMap.put("Banana", 20); linkedHashMap.put("Orange", 15); // 遍历顺序与插入顺序一致 for (String key : linkedHashMap.keySet()) { System.out.println(key); // Apple, Banana, Orange } ``` #### 4. 集合工具类 Collections ```java List numbers = new ArrayList<>(); numbers.add(3); numbers.add(1); numbers.add(4); numbers.add(2); // 排序 Collections.sort(numbers); // [1, 2, 3, 4] // 反转 Collections.reverse(numbers); // [4, 3, 2, 1] // 随机排序 Collections.shuffle(numbers); // 查找 int index = Collections.binarySearch(numbers, 3); // 需要先排序 // 最大/最小值 int max = Collections.max(numbers); int min = Collections.min(numbers); // 填充 Collections.fill(numbers, 0); // [0, 0, 0, 0] // 不可变集合 List unmodifiable = Collections.unmodifiableList(numbers); ``` #### 5. 集合选择策略 | 场景 | 选择 | 原因 | | ---------------- | ----------------- | ------------------------------- | | 需要快速随机访问 | ArrayList | 基于数组实现,get/set操作O(1) | | 频繁插入/删除 | LinkedList | 基于链表实现,插入/删除操作O(1) | | 需要去重 | HashSet | 基于哈希表,查找O(1) | | 需要有序集合 | TreeSet | 基于红黑树,保持元素有序 | | 需要保持插入顺序 | LinkedHashSet | 维护插入顺序的链表 | | 键值对存储 | HashMap | 基于哈希表,查找O(1) | | 需要有序键 | TreeMap | 基于红黑树,按键排序 | | 需要保持插入顺序 | LinkedHashMap | 维护插入顺序的链表 | | 多线程环境 | Vector/Hashtable | 线程安全,但性能较低 | | 高并发环境 | ConcurrentHashMap | 线程安全且性能较好 | ### 四、最佳实践和常见问题 #### 1. 字符串处理最佳实践 1. **避免频繁拼接字符串**:使用 StringBuilder/StringBuffer 2. **使用 equals 比较字符串内容**:不要使用 == 3. **注意字符串编码**:明确指定字符编码(如 UTF-8) 4. **使用 String.format 替代拼接**:提高可读性 5. **合理使用 intern 方法**:减少内存消耗但不要滥用 #### 2. 日期时间处理建议 1. **新项目使用 Java 8 日期时间 API**:LocalDate/LocalTime/LocalDateTime 2. **避免使用已过时的 Date 方法**:如 getYear(), setMonth() 3. **时区处理要明确**:使用 ZonedDateTime 处理时区 4. **格式化/解析要指定格式**:避免隐式依赖系统默认格式 5. **日期计算使用专门方法**:不要自己处理闰年、月份天数等问题 #### 3. 集合使用注意事项 1. **选择合适的集合类型**:根据需求选择 List/Set/Map 的具体实现 2. **预估初始容量**:避免频繁扩容影响性能 3. **注意集合的线程安全性**:多线程环境使用并发集合 4. **正确实现 hashCode 和 equals**:影响 HashSet/HashMap 的正确性 5. **实现 Comparable 或提供 Comparator**:用于 TreeSet/TreeMap 的排序 6. **避免在遍历时修改集合**:使用迭代器的 remove 方法或复制集合 #### 4. 性能优化技巧 1. **集合初始化时指定容量**:减少扩容次数 2. **使用 Arrays.asList 快速创建列表**:但返回的是固定大小列表 3. **优先使用增强 for 循环**:语法简洁且不易出错 4. **考虑使用原始类型集合**:如 Trove, FastUtil 等第三方库 5. **大批量数据考虑使用流式处理**:Java 8 Stream API #### 5. 常见问题解决方案 ##### 问题1:集合遍历时修改导致的 ConcurrentModificationException ```java List list = new ArrayList<>(Arrays.asList("a", "b", "c")); // 错误方式 - 会抛出异常 for (String s : list) { if (s.equals("b")) { list.remove(s); // ConcurrentModificationException } } // 正确方式1 - 使用迭代器 Iterator it = list.iterator(); while (it.hasNext()) { String s = it.next(); if (s.equals("b")) { it.remove(); // 安全删除 } } // 正确方式2 - 使用Java 8 removeIf list.removeIf(s -> s.equals("b")); // 正确方式3 - 创建新集合 List toRemove = new ArrayList<>(); for (String s : list) { if (s.equals("b")) { toRemove.add(s); } } list.removeAll(toRemove); ``` ##### 问题2:自定义对象在 HashSet/HashMap 中不工作 ```java class Person { String name; int age; // 必须正确实现equals和hashCode @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); } } Set people = new HashSet<>(); people.add(new Person("Alice", 25)); people.add(new Person("Bob", 30)); boolean contains = people.contains(new Person("Alice", 25)); // true ``` ##### 问题3:日期时间计算错误 ```java // 错误方式 - 使用Calendar的set方法可能溢出 Calendar cal = Calendar.getInstance(); cal.set(2023, 12, 1); // 月份从0开始,12会变成下一年的1月 // 正确方式1 - 使用Java 8 API LocalDate date = LocalDate.of(2023, 12, 1); // 直接报错,月份无效 // 正确方式2 - 使用Calendar的add方法 Calendar safeCal = Calendar.getInstance(); safeCal.set(2023, Calendar.JANUARY, 1); safeCal.add(Calendar.MONTH, 11); // 2023年12月1日 ``` ##### 问题4:字符串内存问题 ```java // 大量字符串拼接导致内存问题 String result = ""; for (int i = 0; i < 100000; i++) { result += i; // 每次循环创建新字符串对象 } // 优化方案 - 使用StringBuilder StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100000; i++) { sb.append(i); } String optimizedResult = sb.toString(); ``` 通过以上详细的类库解析和最佳实践,可以帮助开发者更有效地使用 Java 常用类库,编写出更高效、更健壮的代码。 ### 五、Lambda 表达式与方法引用详解 #### 一、Lambda 表达式 #### 1. 基本概念 Lambda 表达式是 Java 8 引入的函数式编程特性,本质上是一个匿名函数,可以简洁地表示函数式接口(只有一个抽象方法的接口)的实例。 #### 2. 语法结构 ``` (parameters) -> expression 或 (parameters) -> { statements; } ``` #### 3. 核心特点 - **匿名性**:没有显式的名称 - **函数式**:可以像方法一样接收参数和返回值 - **简洁性**:比匿名类更简洁 - **类型推断**:编译器可以推断参数类型 #### 4. 常见使用场景 #### (1) 替代匿名内部类 ``` // 传统方式 - 匿名内部类 Runnable r1 = new Runnable() { @Override public void run() { System.out.println("Hello World"); } }; // Lambda 方式 Runnable r2 = () -> System.out.println("Hello World"); ``` #### (2) 集合遍历 ``` List names = Arrays.asList("Alice", "Bob", "Charlie"); // 传统方式 for (String name : names) { System.out.println(name); } // Lambda 方式 names.forEach(name -> System.out.println(name)); ``` #### (3) 线程创建 ``` // 传统方式 new Thread(new Runnable() { @Override public void run() { System.out.println("Thread running"); } }).start(); // Lambda 方式 new Thread(() -> System.out.println("Thread running")).start(); ``` #### (4) 条件过滤 ``` List numbers = Arrays.asList(1, 2, 3, 4, 5); // 过滤偶数 List evens = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); ``` #### 二、方法引用 #### 1. 基本概念 方法引用是 Lambda 表达式的简化形式,用于直接引用已有方法。当 Lambda 表达式仅调用一个已有方法时,可以使用方法引用进一步简化代码。 #### 2. 四种类型 #### (1) 静态方法引用 ``` // Lambda 表达式 Function parser1 = s -> Integer.parseInt(s); // 静态方法引用 Function parser2 = Integer::parseInt; ``` #### (2) 实例方法引用 ``` List names = Arrays.asList("Alice", "Bob", "Charlie"); // Lambda 表达式 names.forEach(s -> System.out.println(s)); // 实例方法引用 names.forEach(System.out::println); ``` #### (3) 任意对象方法引用 ``` List words = Arrays.asList("Hello", "World"); // Lambda 表达式 words.stream().map(s -> s.length()).forEach(System.out::println); // 任意对象方法引用 words.stream().map(String::length).forEach(System.out::println); ``` #### (4) 构造方法引用 ``` // Lambda 表达式 Supplier> supplier1 = () -> new ArrayList<>(); // 构造方法引用 Supplier> supplier2 = ArrayList::new; ``` #### 3. 方法引用与 Lambda 的关系 方法引用是 Lambda 表达式的语法糖,当 Lambda 表达式仅调用一个方法时,可以用方法引用替代: ``` // Lambda 表达式 Function toUpper1 = s -> s.toUpperCase(); // 方法引用 Function toUpper2 = String::toUpperCase; ``` #### 三、综合示例 #### 1. 排序示例 ``` List names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // Lambda 表达式 Collections.sort(names, (s1, s2) -> s1.compareTo(s2)); // 方法引用 Collections.sort(names, String::compareTo); ``` #### 2. 对象处理 ``` class Person { private String name; private int age; // getter/setter省略 public static int compareByAge(Person a, Person b) { return a.age - b.age; } } List people = Arrays.asList( new Person("Alice", 25), new Person("Bob", 30), new Person("Charlie", 20) ); // Lambda 表达式 people.sort((p1, p2) -> p1.getAge() - p2.getAge()); // 静态方法引用 people.sort(Person::compareByAge); // 实例方法引用 people.sort(Comparator.comparingInt(Person::getAge)); ``` #### 3. Stream API 结合使用 ``` List names = Arrays.asList("Alice", "Bob", null, "Charlie", "", "David"); // 过滤非空和非空字符串,转换为大写,然后打印 names.stream() .filter(Objects::nonNull) // 静态方法引用 .filter(s -> !s.isEmpty()) // Lambda 表达式 .map(String::toUpperCase) // 实例方法引用 .forEach(System.out::println); // 实例方法引用 ``` #### 四、总结对比 #### Lambda 表达式 vs 方法引用 | **特性** | **Lambda 表达式** | **方法引用** | | ------------ | -------------------------- | ------------------------------------- | | **语法** | `(params) -> expression` | `Class::method` 或 `instance::method` | | **灵活性** | 高(可包含多行代码) | 低(只能引用已有方法) | | **可读性** | 中等 | 高(更简洁) | | **适用场景** | 复杂逻辑 | 简单方法调用 | | **性能** | 相同(编译后实现方式类似) | 相同 | | **类型推断** | 需要 | 需要 | #### 最佳实践建议 1. **优先使用方法引用**: - 当 Lambda 表达式仅调用一个已有方法时 - 代码可读性更高,更简洁 2. **使用 Lambda 表达式**: - 需要实现复杂逻辑时 - 需要多行代码时 - 方法引用无法满足需求时 3. **组合使用**: - 在 Stream API 中混合使用 Lambda 和方法引用 - 根据场景选择最合适的表达方式 4. **注意事项**: - 方法引用要确保方法签名匹配函数式接口 - 避免过度使用方法引用导致代码可读性下降 - 对于不熟悉的方法引用,可以先写 Lambda 表达式再转换 #### 演进关系 ``` 匿名内部类 → Lambda 表达式 → 方法引用 ``` Java 的函数式编程特性使得代码越来越简洁,表达能力越来越强,同时也提高了开发效率和代码可读性。 ## 九、JDK 8 新特性 ### 1. Lambda 表达式 ```java // 传统方式 List list = Arrays.asList("a", "b", "c"); Collections.sort(list, new Comparator() { public int compare(String a, String b) { return a.compareTo(b); } }); // Lambda 表达式 Collections.sort(list, (a, b) -> a.compareTo(b)); // 方法引用 list.forEach(System.out::println); ``` ### 2. Stream API ```java List strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); // 使用Stream进行函数式编程 long count = strings.stream() .filter(string -> !string.isEmpty()) // 过滤空字符串 .map(String::toUpperCase) // 转换为大写 .sorted() // 排序 .count(); // 计数 ``` ### 3. 接口的默认方法和静态方法 ```java interface Vehicle { // 传统抽象方法 void start(); // 默认方法 default void honk() { System.out.println("按喇叭"); } // 静态方法 static int getWheelCount() { return 4; } } class Car implements Vehicle { public void start() { System.out.println("汽车启动"); } } ``` ### 4. 新的日期时间 API ```java // 旧版Date的问题 // 新版java.time包 LocalDate date = LocalDate.now(); LocalTime time = LocalTime.now(); LocalDateTime dateTime = LocalDateTime.now(); // 日期操作 LocalDate tomorrow = date.plusDays(1); LocalDate lastWeek = date.minusWeeks(1); // 日期格式化 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String formattedDate = date.format(formatter); ``` ### 5. Optional 类 ```java // 避免空指针异常 Optional optional = Optional.of("hello"); // 安全访问 if(optional.isPresent()) { System.out.println(optional.get()); } // 函数式风格 optional.ifPresent(s -> System.out.println(s.length())); ``` ## 十、JDK 11 新特性 ### 1. 局部变量类型推断增强 ```java // JDK 10引入的var,JDK 11增强 var list = new ArrayList(); // 推断为ArrayList var stream = list.stream(); // 推断为Stream // Lambda参数也可以使用var var numbers = List.of(1, 2, 3, 4, 5); numbers.stream() .map((var x) -> x * 2) .forEach(System.out::println); ``` ### 2. 新的字符串方法 ```java String str = " Hello World "; // JDK 11新增方法 String trimmed = str.strip(); // 去除首尾空白 String leadingTrimmed = str.stripLeading(); // 去除头部空白 String trailingTrimmed = str.stripTrailing(); // 去除尾部空白 boolean isBlank = " ".isBlank(); // 检查是否为空或空白 String lines = "A\nB\nC".lines().findFirst().get(); // 行处理 String repeated = "Java".repeat(3); // 重复字符串 ``` ### 3. HTTP Client API(标准化) ```java // 创建HTTP客户端 HttpClient client = HttpClient.newHttpClient(); // 创建请求 HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get")) .build(); // 发送请求(异步) client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println) .join(); ``` ### 4. 单文件源代码程序 ```java // 可以直接运行.java文件,无需先编译 // java HelloWorld.java // HelloWorld.java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } ``` ### 5. 新的垃圾收集器 - **Epsilon**:无操作垃圾收集器,用于性能测试 - **ZGC**:可扩展的低延迟垃圾收集器(实验性) ### 6. 飞行记录器(JFR)开源 ```java # 启动JFR java -XX:StartFlightRecording=duration=60s,filename=recording.jfr MyApp # 商业版功能现在开源可用 ``` # 学生成绩管理系统 - 规范API接口文档 ## 1. 系统概述 ### 1.1 基本信息 - **系统名称**:学生成绩管理系统 (Student Management System) - **版本**:v1.1 - **架构**:控制台应用程序,分层架构设计 - **数据存储**:文件系统(文本文件) ### 1.2 核心模块 - 学生管理模块 - 课程管理模块 - 成绩管理模块 - 统计报表模块 - 数据持久化模块 ### 1.3 版本历史 | 版本 | 日期 | 作者 | 修订说明 | | ---- | ---------- | ----------- | ------------------------ | | v1.0 | 2025-10-13 | Br1ghtXu | 初始版本 | | v1.1 | 2025-10-14 | DocReviewer | 规范化修订,完善接口文档 | ## 2. 实体类接口规范 ### 2.1 Student 学生实体 ```java /** * 学生实体类 * 位置:com.sms.model.Student */ public class Student { // 属性定义 private String id; // 学号,主键,7位数字 private String name; // 姓名,2-10字符 private int age; // 年龄,15-50 private String gender; // 性别,M/F private String className; // 班级名称 /** * 验证学生数据有效性 * @return true-数据有效, false-数据无效 */ public boolean isValid(); /** * 转换为文件存储格式 * @return CSV格式字符串:"id,name,age,gender,className" */ public String toFileString(); /** * 从文件行解析学生对象 * @param line 文件行内容(CSV格式) * @return 解析后的Student对象 * @throws IllegalArgumentException 当数据格式错误时抛出 */ public static Student fromFileString(String line) throws IllegalArgumentException; } ``` ### 2.2 Course 课程实体 ```java /** * 课程实体类 * 位置:com.sms.model.Course */ public class Course { // 属性定义 private String courseId; // 课程ID,格式[A-Z]\\d{3} private String courseName; // 课程名称 private double credit; // 学分,0.5-10.0 /** * 验证课程数据有效性 * @return true-数据有效, false-数据无效 */ public boolean isValid(); /** * 转换为文件存储格式 * @return CSV格式字符串:"courseId,courseName,credit" */ public String toFileString(); /** * 从文件行解析课程对象 * @param line 文件行内容(CSV格式) * @return 解析后的Course对象 * @throws IllegalArgumentException 当数据格式错误时抛出 */ public static Course fromFileString(String line) throws IllegalArgumentException; } ``` ### 2.3 Score 成绩实体 ```java /** * 成绩实体类 * 位置:com.sms.model.Score */ public class Score { // 属性定义 private String studentId; // 学生ID,外键 private String courseId; // 课程ID,外键 private double score; // 成绩,0-100 private Date examDate; // 考试日期 /** * 验证成绩数据有效性 * @return true-数据有效, false-数据无效 */ public boolean isValid(); /** * 转换为文件存储格式 * @return CSV格式字符串:"studentId,courseId,score,examDate" */ public String toFileString(); /** * 从文件行解析成绩对象 * @param line 文件行内容(CSV格式) * @return 解析后的Score对象 * @throws IllegalArgumentException 当数据格式错误时抛出 */ public static Score fromFileString(String line) throws IllegalArgumentException; } ``` ## 3. 服务层接口规范 ### 3.1 StudentService 学生服务 ```java /** * 学生管理服务接口 * 位置:com.sms.service.StudentService */ public interface StudentService { /** * 添加学生信息 * @param student 学生对象 * @throws SMSException 当学号已存在或数据无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ void addStudent(Student student) throws SMSException, DataFileCorruptedException; /** * 删除学生信息 * @param studentId 学号 * @return true-删除成功, false-学生不存在 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean deleteStudent(String studentId) throws DataFileCorruptedException; /** * 根据学号查询学生信息 * @param studentId 学号 * @return 学生对象,未找到时返回null * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Student getStudent(String studentId) throws DataFileCorruptedException; /** * 获取所有学生列表 * @return 学生列表(按学号排序) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getAllStudents() throws DataFileCorruptedException; /** * 更新学生信息 * @param student 学生对象(包含更新后的数据) * @return true-更新成功, false-学生不存在 * @throws SMSException 当数据无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean updateStudent(Student student) throws SMSException, DataFileCorruptedException; /** * 根据姓名搜索学生 * @param name 姓名(支持模糊匹配) * @return 匹配的学生列表 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List searchStudentsByName(String name) throws DataFileCorruptedException; /** * 根据班级查询学生 * @param className 班级名称 * @return 该班级的学生列表 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getStudentsByClass(String className) throws DataFileCorruptedException; /** * 检查学号是否存在 * @param studentId 学号 * @return true-存在, false-不存在 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean existsStudent(String studentId) throws DataFileCorruptedException; /** * 批量添加学生 * @param students 学生列表 * @return 成功添加的学生数量 * @throws SMSException 当学号重复或数据无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ int batchAddStudents(List students) throws SMSException, DataFileCorruptedException; /** * 获取学生总数 * @return 学生数量 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ int getStudentCount() throws DataFileCorruptedException; } ``` ### 3.2 CourseService 课程服务 ```java /** * 课程管理服务接口 * 位置:com.sms.service.CourseService */ public interface CourseService { /** * 添加课程信息 * @param course 课程对象 * @throws SMSException 当课程ID已存在或数据无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ void addCourse(Course course) throws SMSException, DataFileCorruptedException; /** * 删除课程信息 * @param courseId 课程ID * @return true-删除成功, false-课程不存在 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean deleteCourse(String courseId) throws DataFileCorruptedException; /** * 根据课程ID查询课程信息 * @param courseId 课程ID * @return 课程对象,未找到时返回null * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Course getCourse(String courseId) throws DataFileCorruptedException; /** * 获取所有课程列表 * @return 课程列表(按课程ID排序) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getAllCourses() throws DataFileCorruptedException; /** * 根据课程名称搜索课程 * @param keyword 课程名称关键词 * @return 匹配的课程列表 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List searchCoursesByName(String keyword) throws DataFileCorruptedException; /** * 检查课程ID是否存在 * @param courseId 课程ID * @return true-存在, false-不存在 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean existsCourse(String courseId) throws DataFileCorruptedException; /** * 获取课程总数 * @return 课程数量 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ int getCourseCount() throws DataFileCorruptedException; } ``` ### 3.3 ScoreService 成绩服务 ```java /** * 成绩管理服务接口 * 位置:com.sms.service.ScoreService */ public interface ScoreService { /** * 添加成绩记录 * @param score 成绩对象 * @throws SMSException 当成绩已存在或数据无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ void addScore(Score score) throws SMSException, DataFileCorruptedException; /** * 更新成绩信息 * @param studentId 学号 * @param courseId 课程ID * @param newScore 新成绩 * @return true-更新成功, false-成绩记录不存在 * @throws SMSException 当成绩无效时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean updateScore(String studentId, String courseId, double newScore) throws SMSException, DataFileCorruptedException; /** * 删除成绩记录 * @param studentId 学号 * @param courseId 课程ID * @return true-删除成功, false-成绩记录不存在 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ boolean deleteScore(String studentId, String courseId) throws DataFileCorruptedException; /** * 根据学号和课程ID查询成绩 * @param studentId 学号 * @param courseId 课程ID * @return 成绩对象,未找到时返回null * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Score getScore(String studentId, String courseId) throws DataFileCorruptedException; /** * 根据学号查询该学生的所有成绩 * @param studentId 学号 * @return 成绩列表(按课程ID排序) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getScoresByStudent(String studentId) throws DataFileCorruptedException; /** * 根据课程ID查询该课程的所有成绩 * @param courseId 课程ID * @return 成绩列表(按学号排序) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getScoresByCourse(String courseId) throws DataFileCorruptedException; /** * 获取所有成绩记录 * @return 成绩列表 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getAllScores() throws DataFileCorruptedException; /** * 计算学生平均分 * @param studentId 学号 * @return 平均分(保留2位小数) * @throws SMSException 当学生不存在或没有成绩时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ double calculateStudentAverage(String studentId) throws SMSException, DataFileCorruptedException; /** * 计算课程平均分 * @param courseId 课程ID * @return 平均分(保留2位小数) * @throws SMSException 当课程不存在或没有成绩时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ double calculateCourseAverage(String courseId) throws SMSException, DataFileCorruptedException; /** * 获取课程成绩前N名的学生 * @param n 前N名 * @param courseId 课程ID * @return 成绩列表(按成绩降序排列) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ List getTopNStudents(int n, String courseId) throws DataFileCorruptedException; } ``` ### 3.4 ReportService 报表服务 ```java /** * 报表生成服务接口 * 位置:com.sms.service.ReportService */ public interface ReportService { /** * 生成学生成绩报表 * @param studentId 学号 * @return 报表数据(包含学生信息、各科成绩、平均分等) * @throws SMSException 当学生不存在时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Map generateStudentReport(String studentId) throws SMSException, DataFileCorruptedException; /** * 生成班级成绩报表 * @param className 班级名称 * @return 报表数据(包含班级学生成绩统计) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Map generateClassReport(String className) throws DataFileCorruptedException; /** * 生成课程成绩报表 * @param courseId 课程ID * @return 报表数据(包含课程成绩分布统计) * @throws SMSException 当课程不存在时抛出 * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Map generateCourseReport(String courseId) throws SMSException, DataFileCorruptedException; /** * 生成系统概要报表 * @return 系统统计信息(学生数、课程数、成绩记录数等) * @throws DataFileCorruptedException 当数据文件损坏时抛出 */ Map generateSystemSummary() throws DataFileCorruptedException; } ``` ## 4. 工具类接口规范 ### 4.1 FileUtil 文件工具 ```java /** * 文件操作工具类 * 位置:com.sms.util.FileUtil */ public final class FileUtil { /** * 从文件读取所有行 * @param filename 文件名(相对data目录路径) * @return 行内容列表 * @throws IOException 当文件不存在或读取失败时抛出 */ public static List readLines(String filename) throws IOException; /** * 写入数据到文件 * @param filename 文件名 * @param lines 要写入的行内容 * @throws IOException 当写入失败时抛出 */ public static void writeLines(String filename, List lines) throws IOException; /** * 写入数据到文件(追加模式) * @param filename 文件名 * @param lines 要写入的行内容 * @param append 是否追加模式 * @throws IOException 当写入失败时抛出 */ public static void writeLines(String filename, List lines, boolean append) throws IOException; /** * 检查文件是否存在 * @param filename 文件名 * @return true-存在, false-不存在 */ public static boolean fileExists(String filename); /** * 如果文件不存在则创建 * @param filename 文件名 * @throws IOException 当创建失败时抛出 */ public static void createFileIfNotExists(String filename) throws IOException; /** * 加载学生数据文件 * @param filename 文件名 * @return 学生对象列表 * @throws IOException 当文件读取失败时抛出 * @throws DataFileCorruptedException 当数据格式错误时抛出 */ public static List loadStudents(String filename) throws IOException, DataFileCorruptedException; /** * 保存学生数据到文件 * @param filename 文件名 * @param students 学生列表 * @throws IOException 当文件写入失败时抛出 */ public static void saveStudents(String filename, List students) throws IOException; } ``` ### 4.2 ValidateUtil 验证工具 ```java /** * 数据验证工具类 * 位置:com.sms.util.ValidateUtil */ public final class ValidateUtil { /** * 验证学号格式 * @param id 学号 * @return true-格式正确, false-格式错误 */ public static boolean isValidStudentId(String id); /** * 验证课程ID格式 * @param courseId 课程ID * @return true-格式正确, false-格式错误 */ public static boolean isValidCourseId(String courseId); /** * 验证成绩范围 * @param score 成绩 * @return true-在有效范围内, false-超出范围 */ public static boolean isValidScore(double score); /** * 验证年龄范围 * @param age 年龄 * @return true-在有效范围内, false-超出范围 */ public static boolean isValidAge(int age); /** * 验证学生对象数据完整性 * @param student 学生对象 * @return 验证结果对象 */ public static ValidationResult validateStudent(Student student); /** * 验证课程对象数据完整性 * @param course 课程对象 * @return 验证结果对象 */ public static ValidationResult validateCourse(Course course); /** * 验证成绩对象数据完整性 * @param score 成绩对象 * @return 验证结果对象 */ public static ValidationResult validateScore(Score score); } ``` ### 4.3 InputUtil 输入工具 ```java /** * 控制台输入工具类 * 位置:com.sms.util.InputUtil */ public final class InputUtil { /** * 获取字符串输入 * @param prompt 提示信息 * @return 用户输入的字符串 */ public static String getStringInput(String prompt); /** * 获取整数输入 * @param prompt 提示信息 * @return 用户输入的整数 * @throws NumberFormatException 当输入不是整数时抛出 */ public static int getIntInput(String prompt) throws NumberFormatException; /** * 获取范围内的整数输入 * @param prompt 提示信息 * @param min 最小值 * @param max 最大值 * @return 用户输入的整数 * @throws IllegalArgumentException 当输入超出范围时抛出 */ public static int getIntInput(String prompt, int min, int max) throws IllegalArgumentException; /** * 获取浮点数输入 * @param prompt 提示信息 * @return 用户输入的浮点数 * @throws NumberFormatException 当输入不是数字时抛出 */ public static double getDoubleInput(String prompt) throws NumberFormatException; /** * 获取菜单选择 * @param options 菜单选项数组 * @return 用户选择的选项索引(从0开始) */ public static int getMenuChoice(String[] options); } ``` ## 5. 异常类接口规范 ### 5.1 SMSException 基础异常 ```java /** * 自定义业务异常基类 * 位置:com.sms.exception.SMSException */ public class SMSException extends Exception { /** * @param message 异常描述信息 */ public SMSException(String message); /** * @param message 异常描述信息 * @param cause 原始异常 */ public SMSException(String message, Throwable cause); } ``` ### 5.2 DataFileCorruptedException 数据文件异常 ```java /** * 数据文件损坏异常 * 位置:com.sms.exception.DataFileCorruptedException */ public class DataFileCorruptedException extends SMSException { /** * @param filename 损坏的文件名 */ public DataFileCorruptedException(String filename); } ``` ## 6. 主程序接口 ### 6.1 MainApp 主程序 ```java /** * 应用程序主类 * 位置:com.sms.MainApp */ public class MainApp { /** * 初始化系统 * @throws SMSException 当初始化失败时抛出 */ public void initialize() throws SMSException; /** * 启动应用程序 * @throws SMSException 当启动失败时抛出 */ public void start() throws SMSException; /** * 关闭应用程序 * @throws SMSException 当关闭过程中发生错误时抛出 */ public void shutdown() throws SMSException; /** * 获取学生服务实例 * @return StudentService实例 */ public StudentService getStudentService(); /** * 检查系统是否正在运行 * @return true-运行中, false-已停止 */ public boolean isRunning(); } ``` ## 7. 常量定义 ### 7.1 SystemConstants 系统常量 ```java /** * 系统常量定义类 * 位置:com.sms.constant.SystemConstants */ public final class SystemConstants { // 文件路径常量 public static final String DATA_DIR = "./data"; public static final String STUDENT_FILE = "students.txt"; public static final String COURSE_FILE = "courses.txt"; public static final String SCORE_FILE = "scores.txt"; // 业务常量 public static final int MIN_SCORE = 0; public static final int MAX_SCORE = 100; public static final int MIN_AGE = 15; public static final int MAX_AGE = 50; public static final int PAGE_SIZE = 10; // 格式常量 public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String ID_PATTERN = "^\\d{7}$"; public static final String COURSE_ID_PATTERN = "^[A-Z]\\d{3}$"; } ``` ## 8. 附录 ### 8.1 数据文件格式规范 **学生数据文件(students.txt)格式:** ``` id,name,age,gender,className 2023001,张三,20,M,计算机1班 2023002,李四,21,F,计算机2班 ``` **课程数据文件(courses.txt)格式:** ``` courseId,courseName,credit C001,Java程序设计,4.0 C002,数据库原理,3.5 ``` **成绩数据文件(scores.txt)格式:** ``` studentId,courseId,score,examDate 2023001,C001,85.5,2024-01-15 2023001,C002,92.0,2024-01-20 ``` ### 8.2 接口使用示例 ```java // 学生服务调用示例 public class ExampleUsage { public static void main(String[] args) { try { MainApp app = new MainApp(); app.initialize(); StudentService studentService = app.getStudentService(); // 添加学生 Student student = new Student("2023001", "张三", 20, "M", "计算机1班"); studentService.addStudent(student); // 查询学生 Student found = studentService.getStudent("2023001"); System.out.println("找到学生: " + found.getName()); app.shutdown(); } catch (SMSException e) { System.err.println("系统错误: " + e.getMessage()); } } } ``` **备注**:此文档为API接口规范,具体实现需严格遵循本规范。接口变更需同步更新本文档。 ### 8.3 文件树状图 ```makefile sms/ # 项目根目录 ├── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── sms/ │ │ ├── MainApp.java # 程序主入口 │ │ ├── constant/ │ │ │ └── SystemConstants.java # 系统常量定义 │ │ ├── model/ # 实体类包 │ │ │ ├── Student.java # 学生实体 │ │ │ ├── Course.java # 课程实体 │ │ │ └── Score.java # 成绩实体 │ │ ├── service/ # 服务接口包 │ │ │ ├── StudentService.java # 学生服务接口 │ │ │ ├── CourseService.java # 课程服务接口 │ │ │ ├── ScoreService.java # 成绩服务接口 │ │ │ └── ReportService.java # 报表服务接口 │ │ ├── service/impl/ # 服务实现包 │ │ │ ├── StudentServiceImpl.java # 学生服务实现 │ │ │ ├── CourseServiceImpl.java # 课程服务实现 │ │ │ ├── ScoreServiceImpl.java # 成绩服务实现 │ │ │ └── ReportServiceImpl.java # 报表服务实现 │ │ ├── util/ # 工具类包 │ │ │ ├── FileUtil.java # 文件操作工具 │ │ │ ├── ValidateUtil.java # 数据验证工具 │ │ │ ├── InputUtil.java # 输入处理工具 │ │ │ └── ExceptionHandler.java # 异常处理工具 │ │ ├── exception/ # 异常类包 │ │ │ ├── SMSException.java # 基础业务异常 │ │ │ └── DataFileCorruptedException.java # 文件损坏异常 │ │ └── manager/ # 管理器包 │ │ ├── MenuManager.java # 菜单管理器 │ │ │ └── resources/ │ └── data/ # 初始数据文件 │ ├── sample_students.txt # 示例学生数据 │ ├── sample_courses.txt # 示例课程数据 │ └── sample_scores.txt # 示例成绩数据 ├── data/ # 运行时数据目录(自动创建) │ ├── students.txt # 学生数据文件 │ ├── courses.txt # 课程数据文件 │ └── scores.txt # 成绩数据文件 └── docs/ # 项目文档目录 └── readme.md #API接口文档 ```