🚀 第一阶段:Java基础入门④Java核心API
💡 学习目标:掌握Java核心API的使用,包括String类、包装类、日期时间API、常用工具类等
📝 String类详解
🎯 String类的特点
📝 String类:Java中最常用的类之一,用于处理字符串数据
✨ String类核心特性
📝 String类特性
│
├── 🔒 不可变性 (Immutable)
│ ├── 字符串内容不能修改
│ ├── 每次"修改"都创建新对象
│ └── 线程安全
│
├── 🏊 字符串池 (String Pool)
│ ├── 字面量存储在常量池
│ ├── 相同内容共享同一对象
│ └── 节省内存空间
│
├── 🧬 继承关系
│ ├── 继承自Object类
│ ├── 实现Serializable接口
│ ├── 实现Comparable接口
│ └── 实现CharSequence接口
│
└── 🔧 丰富的API方法
├── 字符串操作方法
├── 查找和替换方法
├── 格式化方法
└── 转换方法
🏗️ String对象的创建方式
💻 String创建方式对比
public class StringCreation {
public static void main(String[] args) {
// 🎯 方式1:字符串字面量(推荐)
String str1 = "Hello World";
String str2 = "Hello World";
// 🎯 方式2:使用new关键字
String str3 = new String("Hello World");
String str4 = new String("Hello World");
// 🎯 方式3:字符数组构造
char[] chars = {'H', 'e', 'l', 'l', 'o'};
String str5 = new String(chars);
// 🎯 方式4:字节数组构造
byte[] bytes = {72, 101, 108, 108, 111}; // "Hello"的ASCII值
String str6 = new String(bytes);
// 🔍 比较不同创建方式的结果
System.out.println("=== 字符串比较 ===");
System.out.println("str1 == str2: " + (str1 == str2)); // true (字符串池)
System.out.println("str3 == str4: " + (str3 == str4)); // false (不同对象)
System.out.println("str1 == str3: " + (str1 == str3)); // false (不同对象)
System.out.println("str1.equals(str2): " + str1.equals(str2)); // true (内容相同)
System.out.println("str1.equals(str3): " + str1.equals(str3)); // true (内容相同)
// 🎯 intern()方法:将字符串加入字符串池
String str7 = str3.intern();
System.out.println("str1 == str7: " + (str1 == str7)); // true (intern后指向池中对象)
// 📊 显示创建的字符串
System.out.println("\n=== 创建的字符串 ===");
System.out.println("字面量创建: " + str1);
System.out.println("new创建: " + str3);
System.out.println("字符数组创建: " + str5);
System.out.println("字节数组创建: " + str6);
}
}
🔧 String类常用方法
📏 长度和字符访问
💻 基本操作方法
public class StringBasicMethods {
public static void main(String[] args) {
String text = "Hello Java Programming";
// 📏 获取字符串长度
System.out.println("字符串长度: " + text.length()); // 21
// 🔍 访问指定位置的字符
System.out.println("第0个字符: " + text.charAt(0)); // 'H'
System.out.println("第6个字符: " + text.charAt(6)); // 'J'
// 🎯 获取字符的ASCII值
System.out.println("'H'的ASCII值: " + (int)text.charAt(0)); // 72
// 📋 转换为字符数组
char[] charArray = text.toCharArray();
System.out.print("字符数组: ");
for (char c : charArray) {
System.out.print(c + " ");
}
System.out.println();
// 🔍 检查字符串是否为空
String emptyStr = "";
String nullStr = null;
System.out.println("text是否为空: " + text.isEmpty()); // false
System.out.println("emptyStr是否为空: " + emptyStr.isEmpty()); // true
System.out.println("text长度是否为0: " + (text.length() == 0)); // false
// ⚠️ 安全的空字符串检查
System.out.println("安全检查emptyStr: " + isNullOrEmpty(emptyStr)); // true
System.out.println("安全检查nullStr: " + isNullOrEmpty(nullStr)); // true
}
// 🛡️ 安全的空字符串检查方法
public static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
}
🔍 查找和匹配方法
💻 查找方法示例
public class StringSearchMethods {
public static void main(String[] args) {
String text = "Java is a programming language. Java is powerful.";
// 🔍 查找子字符串的位置
System.out.println("=== 查找方法 ===");
System.out.println("第一次出现'Java'的位置: " + text.indexOf("Java")); // 0
System.out.println("最后一次出现'Java'的位置: " + text.lastIndexOf("Java")); // 32
System.out.println("从位置5开始查找'a': " + text.indexOf('a', 5)); // 6
// 🎯 检查字符串是否包含子字符串
System.out.println("\n=== 包含检查 ===");
System.out.println("是否包含'programming': " + text.contains("programming")); // true
System.out.println("是否包含'Python': " + text.contains("Python")); // false
// 🚀 前缀和后缀检查
System.out.println("\n=== 前缀后缀检查 ===");
System.out.println("是否以'Java'开头: " + text.startsWith("Java")); // true
System.out.println("是否以'powerful.'结尾: " + text.endsWith("powerful.")); // true
System.out.println("从位置32开始是否以'Java'开头: " + text.startsWith("Java", 32)); // true
// 🔄 字符串匹配
System.out.println("\n=== 字符串匹配 ===");
String pattern = "Hello";
String test1 = "Hello";
String test2 = "hello";
String test3 = "HELLO";
System.out.println("精确匹配 'Hello': " + test1.equals(pattern)); // true
System.out.println("忽略大小写匹配 'hello': " + test2.equalsIgnoreCase(pattern)); // true
System.out.println("忽略大小写匹配 'HELLO': " + test3.equalsIgnoreCase(pattern)); // true
// 📊 字符串比较
System.out.println("\n=== 字符串比较 ===");
String str1 = "apple";
String str2 = "banana";
String str3 = "Apple";
System.out.println("'apple'与'banana'比较: " + str1.compareTo(str2)); // 负数
System.out.println("'banana'与'apple'比较: " + str2.compareTo(str1)); // 正数
System.out.println("'apple'与'Apple'比较: " + str1.compareTo(str3)); // 正数
System.out.println("'apple'与'Apple'忽略大小写比较: " + str1.compareToIgnoreCase(str3)); // 0
}
}
✂️ 字符串截取和分割
💻 截取和分割方法
public class StringSubstringMethods {
public static void main(String[] args) {
String text = " Java Programming Language ";
// ✂️ 字符串截取
System.out.println("=== 字符串截取 ===");
System.out.println("原字符串: '" + text + "'");
System.out.println("从位置2开始截取: '" + text.substring(2) + "'");
System.out.println("截取位置2到8: '" + text.substring(2, 8) + "'");
// 🧹 去除空白字符
System.out.println("\n=== 去除空白 ===");
System.out.println("去除前后空白: '" + text.trim() + "'");
System.out.println("去除所有空白: '" + text.replace(" ", "") + "'");
// 🔄 字符串分割
System.out.println("\n=== 字符串分割 ===");
String csvData = "张三,25,程序员,北京";
String[] parts = csvData.split(",");
System.out.println("CSV数据分割结果:");
for (int i = 0; i < parts.length; i++) {
System.out.println(" [" + i + "]: " + parts[i]);
}
// 🎯 限制分割次数
String data = "a-b-c-d-e";
String[] limitedSplit = data.split("-", 3); // 最多分割3次
System.out.println("\n限制分割次数的结果:");
for (int i = 0; i < limitedSplit.length; i++) {
System.out.println(" [" + i + "]: " + limitedSplit[i]);
}
// 📝 正则表达式分割
String phoneNumber = "188-8008-6666";
String[] phoneParts = phoneNumber.split("-");
System.out.println("\n电话号码分割:");
System.out.printf("区号: %s, 前缀: %s, 号码: %s%n",
phoneParts[0], phoneParts[1], phoneParts[2]);
// 🔍 处理特殊分隔符
String path = "C:\\Users\\Java\\Documents";
String[] pathParts = path.split("\\\\"); // 需要转义反斜杠
System.out.println("\n路径分割:");
for (String part : pathParts) {
if (!part.isEmpty()) {
System.out.println(" " + part);
}
}
}
}
🔄 字符串替换和转换
💻 替换和转换方法
public class StringReplaceMethods {
public static void main(String[] args) {
String text = "Java is great. Java is powerful. Java is popular.";
// 🔄 字符串替换
System.out.println("=== 字符串替换 ===");
System.out.println("原字符串: " + text);
System.out.println("替换第一个'Java': " + text.replaceFirst("Java", "Python"));
System.out.println("替换所有'Java': " + text.replace("Java", "Python"));
System.out.println("替换所有'.'为'!': " + text.replace(".", "!"));
// 🎯 正则表达式替换
System.out.println("\n=== 正则表达式替换 ===");
String phoneText = "联系电话:188-8008-6666 或 188-6006-6666";
String maskedPhone = phoneText.replaceAll("\\d{3}-\\d{4}-\\d{4}", "***-****-****");
System.out.println("手机号脱敏: " + maskedPhone);
// 📝 大小写转换
System.out.println("\n=== 大小写转换 ===");
String mixedCase = "Hello World Java Programming";
System.out.println("原字符串: " + mixedCase);
System.out.println("转为大写: " + mixedCase.toUpperCase());
System.out.println("转为小写: " + mixedCase.toLowerCase());
// 🎨 首字母大写
System.out.println("首字母大写: " + capitalizeFirstLetter(mixedCase.toLowerCase()));
// 🔢 数字和字符串转换
System.out.println("\n=== 数字转换 ===");
int number = 12345;
double decimal = 123.456;
boolean flag = true;
System.out.println("整数转字符串: " + String.valueOf(number));
System.out.println("小数转字符串: " + String.valueOf(decimal));
System.out.println("布尔值转字符串: " + String.valueOf(flag));
// 🎯 字符串转数字
String numStr = "12345";
String decimalStr = "123.456";
try {
int parsedInt = Integer.parseInt(numStr);
double parsedDouble = Double.parseDouble(decimalStr);
System.out.println("字符串转整数: " + parsedInt);
System.out.println("字符串转小数: " + parsedDouble);
} catch (NumberFormatException e) {
System.out.println("数字格式错误: " + e.getMessage());
}
}
// 🎨 首字母大写方法
public static String capitalizeFirstLetter(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
🚀 StringBuilder和StringBuffer
🎯 可变字符串类
🔄 String vs StringBuilder vs StringBuffer
• String:不可变,每次修改创建新对象
• StringBuilder:可变,非线程安全,性能最好
• StringBuffer:可变,线程安全,性能较好
• 使用场景:频繁字符串操作时使用StringBuilder
• String:不可变,每次修改创建新对象
• StringBuilder:可变,非线程安全,性能最好
• StringBuffer:可变,线程安全,性能较好
• 使用场景:频繁字符串操作时使用StringBuilder
💻 StringBuilder使用示例
public class StringBuilderDemo {
public static void main(String[] args) {
// 🚀 StringBuilder基本使用
StringBuilder sb = new StringBuilder();
// 📝 追加内容
sb.append("Hello");
sb.append(" ");
sb.append("World");
sb.append("!");
System.out.println("StringBuilder结果: " + sb.toString());
// 🔄 链式调用
StringBuilder chainSb = new StringBuilder()
.append("Java")
.append(" is")
.append(" awesome")
.append("!");
System.out.println("链式调用结果: " + chainSb.toString());
// ✂️ 插入和删除
StringBuilder editSb = new StringBuilder("Hello World");
editSb.insert(5, " Beautiful"); // 在位置5插入
System.out.println("插入后: " + editSb.toString());
editSb.delete(5, 15); // 删除位置5到15的字符
System.out.println("删除后: " + editSb.toString());
// 🔄 替换
editSb.replace(0, 5, "Hi"); // 替换位置0到5的字符
System.out.println("替换后: " + editSb.toString());
// 🔄 反转
StringBuilder reverseSb = new StringBuilder("12345");
reverseSb.reverse();
System.out.println("反转后: " + reverseSb.toString());
// 📊 性能对比演示
performanceComparison();
}
// 📊 性能对比方法
public static void performanceComparison() {
int iterations = 10000;
// String拼接性能测试
long startTime = System.currentTimeMillis();
String str = "";
for (int i = 0; i < iterations; i++) {
str += "a"; // 每次都创建新对象
}
long stringTime = System.currentTimeMillis() - startTime;
// StringBuilder拼接性能测试
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append("a"); // 在原对象上修改
}
long sbTime = System.currentTimeMillis() - startTime;
System.out.println("\n=== 性能对比 ===");
System.out.println("String拼接耗时: " + stringTime + "ms");
System.out.println("StringBuilder拼接耗时: " + sbTime + "ms");
System.out.println("StringBuilder比String快: " + (stringTime / (double)sbTime) + "倍");
}
}
🔢 包装类与自动装箱
🎯 包装类概述
🔢 包装类(Wrapper Classes):将基本数据类型封装成对象的类,提供了丰富的方法和功能
✨ 基本类型与包装类对应关系
| 基本类型 | 包装类 | 父类 | 示例 |
|---|---|---|---|
byte | Byte | Number | Byte b = 100; |
short | Short | Number | Short s = 1000; |
int | Integer | Number | Integer i = 12345; |
long | Long | Number | Long l = 123456L; |
float | Float | Number | Float f = 3.14f; |
double | Double | Number | Double d = 3.14159; |
char | Character | Object | Character c = 'A'; |
boolean | Boolean | Object | Boolean flag = true; |
🔄 自动装箱与拆箱
💻 自动装箱拆箱示例
public class AutoBoxingDemo {
public static void main(String[] args) {
// 🔄 自动装箱 (Autoboxing) - 基本类型自动转换为包装类
System.out.println("=== 自动装箱 ===");
Integer intObj = 100; // 等价于 Integer.valueOf(100)
Double doubleObj = 3.14; // 等价于 Double.valueOf(3.14)
Boolean boolObj = true; // 等价于 Boolean.valueOf(true)
Character charObj = 'A'; // 等价于 Character.valueOf('A')
System.out.println("装箱后的Integer: " + intObj);
System.out.println("装箱后的Double: " + doubleObj);
System.out.println("装箱后的Boolean: " + boolObj);
System.out.println("装箱后的Character: " + charObj);
// 🔄 自动拆箱 (Unboxing) - 包装类自动转换为基本类型
System.out.println("\n=== 自动拆箱 ===");
int intValue = intObj; // 等价于 intObj.intValue()
double doubleValue = doubleObj; // 等价于 doubleObj.doubleValue()
boolean boolValue = boolObj; // 等价于 boolObj.booleanValue()
char charValue = charObj; // 等价于 charObj.charValue()
System.out.println("拆箱后的int: " + intValue);
System.out.println("拆箱后的double: " + doubleValue);
System.out.println("拆箱后的boolean: " + boolValue);
System.out.println("拆箱后的char: " + charValue);
// 🎯 在表达式中的自动装箱拆箱
System.out.println("\n=== 表达式中的装箱拆箱 ===");
Integer a = 10;
Integer b = 20;
Integer sum = a + b; // 自动拆箱进行运算,然后装箱赋值
System.out.println("Integer运算: " + a + " + " + b + " = " + sum);
// 🔍 集合中的自动装箱
java.util.List<Integer> numbers = new java.util.ArrayList<>();
numbers.add(1); // 自动装箱
numbers.add(2); // 自动装箱
numbers.add(3); // 自动装箱
int first = numbers.get(0); // 自动拆箱
System.out.println("从集合中获取的值: " + first);
}
}
🔧 包装类常用方法
🔄 类型转换方法
💻 包装类转换方法
public class WrapperConversionDemo {
public static void main(String[] args) {
// 🔢 Integer类常用方法
System.out.println("=== Integer类方法 ===");
// 字符串转整数
String numStr = "12345";
int num1 = Integer.parseInt(numStr);
Integer num2 = Integer.valueOf(numStr);
System.out.println("parseInt结果: " + num1);
System.out.println("valueOf结果: " + num2);
// 不同进制转换
String binaryStr = "1010";
String octalStr = "777";
String hexStr = "FF";
int fromBinary = Integer.parseInt(binaryStr, 2); // 二进制转十进制
int fromOctal = Integer.parseInt(octalStr, 8); // 八进制转十进制
int fromHex = Integer.parseInt(hexStr, 16); // 十六进制转十进制
System.out.println("二进制" + binaryStr + "转十进制: " + fromBinary);
System.out.println("八进制" + octalStr + "转十进制: " + fromOctal);
System.out.println("十六进制" + hexStr + "转十进制: " + fromHex);
// 整数转不同进制字符串
int decimal = 255;
System.out.println("十进制" + decimal + "转二进制: " + Integer.toBinaryString(decimal));
System.out.println("十进制" + decimal + "转八进制: " + Integer.toOctalString(decimal));
System.out.println("十进制" + decimal + "转十六进制: " + Integer.toHexString(decimal));
// 🔢 Double类常用方法
System.out.println("\n=== Double类方法 ===");
String doubleStr = "123.456";
double d1 = Double.parseDouble(doubleStr);
Double d2 = Double.valueOf(doubleStr);
System.out.println("parseDouble结果: " + d1);
System.out.println("valueOf结果: " + d2);
// 特殊值检查
double positiveInfinity = Double.POSITIVE_INFINITY;
double negativeInfinity = Double.NEGATIVE_INFINITY;
double notANumber = Double.NaN;
System.out.println("是否为无穷大: " + Double.isInfinite(positiveInfinity));
System.out.println("是否为NaN: " + Double.isNaN(notANumber));
System.out.println("是否为有限数: " + Double.isFinite(123.456));
// 🔤 Character类常用方法
System.out.println("\n=== Character类方法 ===");
char ch = 'A';
System.out.println("是否为字母: " + Character.isLetter(ch));
System.out.println("是否为数字: " + Character.isDigit(ch));
System.out.println("是否为大写: " + Character.isUpperCase(ch));
System.out.println("是否为小写: " + Character.isLowerCase(ch));
System.out.println("是否为空白字符: " + Character.isWhitespace(ch));
System.out.println("转为小写: " + Character.toLowerCase(ch));
System.out.println("转为大写: " + Character.toUpperCase('a'));
// ✅ Boolean类常用方法
System.out.println("\n=== Boolean类方法 ===");
String boolStr1 = "true";
String boolStr2 = "false";
String boolStr3 = "TRUE";
String boolStr4 = "yes";
System.out.println("'true'转布尔: " + Boolean.parseBoolean(boolStr1)); // true
System.out.println("'false'转布尔: " + Boolean.parseBoolean(boolStr2)); // false
System.out.println("'TRUE'转布尔: " + Boolean.parseBoolean(boolStr3)); // true
System.out.println("'yes'转布尔: " + Boolean.parseBoolean(boolStr4)); // false (只有"true"返回true)
}
}
🔍 包装类的比较
💻 包装类比较陷阱
public class WrapperComparisonDemo {
public static void main(String[] args) {
// ⚠️ 包装类比较的陷阱
System.out.println("=== 包装类比较陷阱 ===");
// 🎯 Integer缓存范围 (-128 到 127)
Integer a1 = 100;
Integer a2 = 100;
Integer b1 = 200;
Integer b2 = 200;
System.out.println("a1 == a2 (100): " + (a1 == a2)); // true (缓存范围内)
System.out.println("b1 == b2 (200): " + (b1 == b2)); // false (超出缓存范围)
System.out.println("a1.equals(a2): " + a1.equals(a2)); // true
System.out.println("b1.equals(b2): " + b1.equals(b2)); // true
// 🔍 显式创建对象
Integer c1 = new Integer(100); // 已废弃,但仍可用
Integer c2 = new Integer(100);
Integer c3 = Integer.valueOf(100);
System.out.println("c1 == c2 (new创建): " + (c1 == c2)); // false
System.out.println("c1 == c3 (new vs valueOf): " + (c1 == c3)); // false
System.out.println("a1 == c3 (valueOf): " + (a1 == c3)); // true
// 🎯 正确的比较方式
System.out.println("\n=== 正确的比较方式 ===");
System.out.println("使用equals比较: " + c1.equals(c2)); // true
System.out.println("使用compareTo比较: " + c1.compareTo(c2)); // 0
// 🔢 不同类型包装类的缓存范围
System.out.println("\n=== 其他包装类缓存 ===");
// Boolean: true和false都被缓存
Boolean bool1 = true;
Boolean bool2 = true;
System.out.println("Boolean缓存: " + (bool1 == bool2)); // true
// Character: 0到127被缓存
Character char1 = 'A'; // ASCII 65
Character char2 = 'A';
System.out.println("Character缓存: " + (char1 == char2)); // true
// Byte: 所有值都被缓存 (-128到127)
Byte byte1 = 100;
Byte byte2 = 100;
System.out.println("Byte缓存: " + (byte1 == byte2)); // true
// 🎯 最佳实践建议
demonstrateBestPractices();
}
public static void demonstrateBestPractices() {
System.out.println("\n=== 最佳实践 ===");
// ✅ 推荐:使用valueOf而不是构造函数
Integer good = Integer.valueOf(100);
// ❌ 不推荐:使用构造函数(已废弃)
// Integer bad = new Integer(100);
// ✅ 推荐:使用equals比较内容
Integer num1 = 1000;
Integer num2 = 1000;
System.out.println("正确比较方式: " + num1.equals(num2));
// ✅ 推荐:空值安全比较
Integer nullValue = null;
Integer normalValue = 100;
// 安全的比较方式
System.out.println("空值安全比较: " + java.util.Objects.equals(nullValue, normalValue));
// ❌ 危险的比较方式
try {
// System.out.println(nullValue.equals(normalValue)); // 会抛出NullPointerException
} catch (NullPointerException e) {
System.out.println("空指针异常被避免");
}
}
}
🎯 包装类的实际应用
💻 包装类实际应用示例
import java.util.*;
public class WrapperApplicationDemo {
public static void main(String[] args) {
// 🎯 应用1:集合中只能存储对象
System.out.println("=== 集合应用 ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Map<String, Integer> scores = new HashMap<>();
scores.put("张三", 95);
scores.put("李四", 87);
scores.put("王五", 92);
System.out.println("数字列表: " + numbers);
System.out.println("成绩映射: " + scores);
// 🎯 应用2:泛型类型参数
Optional<Integer> optionalInt = Optional.of(42);
System.out.println("Optional包装: " + optionalInt.get());
// 🎯 应用3:方法参数可以为null
processScore(95); // 自动装箱
processScore(null); // 可以传null
// 🎯 应用4:常量定义
System.out.println("\n=== 常量应用 ===");
System.out.println("Integer最大值: " + Integer.MAX_VALUE);
System.out.println("Integer最小值: " + Integer.MIN_VALUE);
System.out.println("Double最大值: " + Double.MAX_VALUE);
System.out.println("Double最小值: " + Double.MIN_VALUE);
System.out.println("Character最大值: " + (int)Character.MAX_VALUE);
// 🎯 应用5:数据验证和转换
validateAndConvert();
}
// 方法可以接收null值
public static void processScore(Integer score) {
if (score == null) {
System.out.println("成绩为空,使用默认值0");
score = 0;
}
System.out.println("处理成绩: " + score);
}
// 数据验证和转换示例
public static void validateAndConvert() {
System.out.println("\n=== 数据验证转换 ===");
String[] inputs = {"123", "45.67", "true", "invalid", "", null};
for (String input : inputs) {
System.out.println("输入: " + input);
// 安全的整数转换
Integer intValue = safeParseInt(input);
System.out.println(" 转换为Integer: " + intValue);
// 安全的双精度转换
Double doubleValue = safeParseDouble(input);
System.out.println(" 转换为Double: " + doubleValue);
// 安全的布尔转换
Boolean boolValue = safeParseBoolean(input);
System.out.println(" 转换为Boolean: " + boolValue);
System.out.println();
}
}
// 安全的整数解析
public static Integer safeParseInt(String str) {
if (str == null || str.trim().isEmpty()) {
return null;
}
try {
return Integer.valueOf(str.trim());
} catch (NumberFormatException e) {
return null;
}
}
// 安全的双精度解析
public static Double safeParseDouble(String str) {
if (str == null || str.trim().isEmpty()) {
return null;
}
try {
return Double.valueOf(str.trim());
} catch (NumberFormatException e) {
return null;
}
}
// 安全的布尔解析
public static Boolean safeParseBoolean(String str) {
if (str == null || str.trim().isEmpty()) {
return null;
}
String trimmed = str.trim().toLowerCase();
if ("true".equals(trimmed) || "1".equals(trimmed) || "yes".equals(trimmed)) {
return true;
} else if ("false".equals(trimmed) || "0".equals(trimmed) || "no".equals(trimmed)) {
return false;
}
return null;
}
}
📊 集合框架
🎯 Java集合框架概述
📊 集合框架:Java提供的一套用于存储和操作对象集合的统一架构
✨ 集合框架的优势
| 优势 | 说明 | 示例 |
|---|---|---|
| 🔄 动态大小 | 可以根据需要自动调整大小 | ArrayList可以动态扩容 |
| 🎯 类型安全 | 使用泛型确保类型安全 | List<String> 只能存储字符串 |
| 🔧 丰富的操作 | 提供增删改查等丰富操作 | add、remove、contains等方法 |
| 📈 高性能 | 针对不同场景优化的数据结构 | HashMap的O(1)查找性能 |
| 🔄 统一接口 | 统一的编程接口 | 所有List都有相同的基本操作 |
🏗️ 集合框架体系结构
📊 Java集合框架
│
├── 📋 Collection接口
│ ├── 📝 List接口 (有序,可重复)
│ │ ├── ArrayList (动态数组)
│ │ ├── LinkedList (双向链表)
│ │ └── Vector (线程安全的动态数组)
│ │
│ ├── 🎯 Set接口 (无序,不可重复)
│ │ ├── HashSet (哈希表)
│ │ ├── LinkedHashSet (有序的哈希表)
│ │ └── TreeSet (红黑树,自动排序)
│ │
│ └── 🔄 Queue接口 (队列)
│ ├── LinkedList (也实现了Queue)
│ ├── PriorityQueue (优先队列)
│ └── ArrayDeque (双端队列)
│
└── 🗺️ Map接口 (键值对)
├── HashMap (哈希表)
├── LinkedHashMap (有序的哈希表)
├── TreeMap (红黑树,按键排序)
└── Hashtable (线程安全的哈希表)
📝 List接口详解
🔧 ArrayList - 动态数组
💻 ArrayList基本使用
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
// 🔧 创建ArrayList
List<String> fruits = new ArrayList<>();
// ➕ 添加元素
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("橙子");
fruits.add(1, "葡萄"); // 在指定位置插入
System.out.println("水果列表:" + fruits);
// 🔍 访问元素
System.out.println("第一个水果:" + fruits.get(0));
System.out.println("列表大小:" + fruits.size());
// 🔄 修改元素
fruits.set(0, "红苹果");
System.out.println("修改后:" + fruits);
// 🔍 查找元素
boolean hasApple = fruits.contains("红苹果");
int index = fruits.indexOf("香蕉");
System.out.println("包含红苹果:" + hasApple);
System.out.println("香蕉的位置:" + index);
// 🗑️ 删除元素
fruits.remove("橙子"); // 按值删除
fruits.remove(0); // 按索引删除
System.out.println("删除后:" + fruits);
// 🔄 遍历列表
System.out.println("=== 遍历方式 ===");
// 方式1:传统for循环
for (int i = 0; i < fruits.size(); i++) {
System.out.println("索引" + i + ":" + fruits.get(i));
}
// 方式2:增强for循环
for (String fruit : fruits) {
System.out.println("水果:" + fruit);
}
// 方式3:迭代器
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
System.out.println("迭代器:" + iterator.next());
}
}
}
🔗 LinkedList - 双向链表
💻 LinkedList基本使用
import java.util.*;
public class LinkedListDemo {
public static void main(String[] args) {
// 🔗 创建LinkedList
LinkedList<Integer> numbers = new LinkedList<>();
// ➕ 添加元素
numbers.add(10);
numbers.add(20);
numbers.add(30);
// 🔗 LinkedList特有方法
numbers.addFirst(5); // 在开头添加
numbers.addLast(40); // 在末尾添加
System.out.println("数字列表:" + numbers);
// 🔍 访问首尾元素
System.out.println("第一个元素:" + numbers.getFirst());
System.out.println("最后一个元素:" + numbers.getLast());
// 🗑️ 删除首尾元素
numbers.removeFirst();
numbers.removeLast();
System.out.println("删除首尾后:" + numbers);
// 🔄 作为栈使用
System.out.println("=== 作为栈使用 ===");
LinkedList<String> stack = new LinkedList<>();
stack.push("第一个");
stack.push("第二个");
stack.push("第三个");
System.out.println("栈顶元素:" + stack.peek());
while (!stack.isEmpty()) {
System.out.println("弹出:" + stack.pop());
}
// 🔄 作为队列使用
System.out.println("=== 作为队列使用 ===");
LinkedList<String> queue = new LinkedList<>();
queue.offer("第一个");
queue.offer("第二个");
queue.offer("第三个");
while (!queue.isEmpty()) {
System.out.println("出队:" + queue.poll());
}
}
}
🎯 Set接口详解
🔧 HashSet - 哈希集合
💻 HashSet基本使用
import java.util.*;
public class HashSetDemo {
public static void main(String[] args) {
// 🎯 创建HashSet
Set<String> cities = new HashSet<>();
// ➕ 添加元素
cities.add("北京");
cities.add("上海");
cities.add("广州");
cities.add("深圳");
cities.add("北京"); // 重复元素不会被添加
System.out.println("城市集合:" + cities);
System.out.println("集合大小:" + cities.size());
// 🔍 检查元素
boolean hasBeijing = cities.contains("北京");
System.out.println("包含北京:" + hasBeijing);
// 🗑️ 删除元素
cities.remove("广州");
System.out.println("删除广州后:" + cities);
// 🔄 遍历集合
System.out.println("=== 遍历城市 ===");
for (String city : cities) {
System.out.println("城市:" + city);
}
// 🔄 集合运算
Set<String> southCities = new HashSet<>();
southCities.add("深圳");
southCities.add("广州");
southCities.add("杭州");
// 交集
Set<String> intersection = new HashSet<>(cities);
intersection.retainAll(southCities);
System.out.println("交集:" + intersection);
// 并集
Set<String> union = new HashSet<>(cities);
union.addAll(southCities);
System.out.println("并集:" + union);
// 差集
Set<String> difference = new HashSet<>(cities);
difference.removeAll(southCities);
System.out.println("差集:" + difference);
}
}
🌳 TreeSet - 有序集合
💻 TreeSet基本使用
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
// 🌳 创建TreeSet(自动排序)
TreeSet<Integer> scores = new TreeSet<>();
// ➕ 添加元素
scores.add(85);
scores.add(92);
scores.add(78);
scores.add(96);
scores.add(85); // 重复元素不会被添加
System.out.println("成绩集合(自动排序):" + scores);
// 🔍 范围查询
System.out.println("最高分:" + scores.last());
System.out.println("最低分:" + scores.first());
System.out.println("大于等于85的成绩:" + scores.tailSet(85));
System.out.println("小于90的成绩:" + scores.headSet(90));
System.out.println("80-90之间的成绩:" + scores.subSet(80, 90));
// 🔄 自定义排序
TreeSet<String> names = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s2.compareTo(s1); // 逆序排列
}
});
names.add("张三");
names.add("李四");
names.add("王五");
names.add("赵六");
System.out.println("姓名集合(逆序):" + names);
}
}
🗺️ Map接口详解
🔧 HashMap - 哈希映射
💻 HashMap基本使用
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
// 🗺️ 创建HashMap
Map<String, Integer> studentScores = new HashMap<>();
// ➕ 添加键值对
studentScores.put("张三", 85);
studentScores.put("李四", 92);
studentScores.put("王五", 78);
studentScores.put("赵六", 96);
System.out.println("学生成绩:" + studentScores);
// 🔍 访问元素
Integer zhangSanScore = studentScores.get("张三");
System.out.println("张三的成绩:" + zhangSanScore);
// 🔍 检查键和值
boolean hasLiSi = studentScores.containsKey("李四");
boolean hasScore100 = studentScores.containsValue(100);
System.out.println("包含李四:" + hasLiSi);
System.out.println("包含100分:" + hasScore100);
// 🔄 更新值
studentScores.put("张三", 88); // 更新张三的成绩
studentScores.putIfAbsent("钱七", 82); // 如果不存在才添加
System.out.println("更新后:" + studentScores);
// 🗑️ 删除元素
studentScores.remove("王五");
System.out.println("删除王五后:" + studentScores);
// 🔄 遍历Map
System.out.println("=== 遍历方式 ===");
// 方式1:遍历键
for (String name : studentScores.keySet()) {
System.out.println(name + ":" + studentScores.get(name));
}
// 方式2:遍历值
for (Integer score : studentScores.values()) {
System.out.println("成绩:" + score);
}
// 方式3:遍历键值对
for (Map.Entry<String, Integer> entry : studentScores.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
// 🔄 统计操作
System.out.println("=== 统计信息 ===");
int totalScore = 0;
int maxScore = 0;
String topStudent = "";
for (Map.Entry<String, Integer> entry : studentScores.entrySet()) {
int score = entry.getValue();
totalScore += score;
if (score > maxScore) {
maxScore = score;
topStudent = entry.getKey();
}
}
double averageScore = (double) totalScore / studentScores.size();
System.out.println("平均分:" + averageScore);
System.out.println("最高分:" + maxScore + "(" + topStudent + ")");
}
}
📊 集合框架最佳实践
💡 选择合适的集合类型
• ArrayList:需要频繁随机访问元素
• LinkedList:需要频繁插入删除元素
• HashSet:需要快速查找,不关心顺序
• TreeSet:需要自动排序的集合
• HashMap:需要键值对映射,快速查找
• TreeMap:需要按键排序的映射
• ArrayList:需要频繁随机访问元素
• LinkedList:需要频繁插入删除元素
• HashSet:需要快速查找,不关心顺序
• TreeSet:需要自动排序的集合
• HashMap:需要键值对映射,快速查找
• TreeMap:需要按键排序的映射
⚠️ 使用注意事项
• 使用泛型确保类型安全
• 重写equals()和hashCode()方法
• 注意并发安全问题
• 选择合适的初始容量
• 及时释放不需要的引用
• 使用泛型确保类型安全
• 重写equals()和hashCode()方法
• 注意并发安全问题
• 选择合适的初始容量
• 及时释放不需要的引用
🚨 异常处理机制
🎯 异常处理概述
🚨 异常:程序运行时出现的错误或异常情况,Java提供了完善的异常处理机制
✨ 异常处理的重要性
| 重要性 | 说明 | 示例 |
|---|---|---|
| 🛡️ 程序健壮性 | 防止程序因错误而崩溃 | 处理文件不存在的情况 |
| 🔍 错误定位 | 帮助快速定位和解决问题 | 异常堆栈信息 |
| 👥 用户体验 | 提供友好的错误提示 | 显示"网络连接失败"而不是崩溃 |
| 🔄 程序恢复 | 允许程序从错误中恢复 | 重试机制 |
| 📝 日志记录 | 记录错误信息便于调试 | 异常日志 |
🏗️ Java异常体系结构
🚨 Java异常体系
│
└── Throwable (所有异常的根类)
├── Error (系统级错误,不建议捕获)
│ ├── OutOfMemoryError (内存溢出)
│ ├── StackOverflowError (栈溢出)
│ └── VirtualMachineError (虚拟机错误)
│
└── Exception (程序异常,可以处理)
├── RuntimeException (运行时异常,非检查异常)
│ ├── NullPointerException (空指针异常)
│ ├── ArrayIndexOutOfBoundsException (数组越界)
│ ├── IllegalArgumentException (非法参数)
│ ├── NumberFormatException (数字格式异常)
│ └── ClassCastException (类型转换异常)
│
└── 检查异常 (编译时必须处理)
├── IOException (输入输出异常)
├── FileNotFoundException (文件未找到)
├── SQLException (数据库异常)
└── ClassNotFoundException (类未找到)
🛡️ try-catch-finally语句
🔧 基本语法
💻 基本异常处理
public class BasicExceptionHandling {
public static void main(String[] args) {
// 🛡️ 基本try-catch结构
try {
int result = 10 / 0; // 会抛出ArithmeticException
System.out.println("结果:" + result);
} catch (ArithmeticException e) {
System.out.println("发生算术异常:" + e.getMessage());
}
System.out.println("程序继续执行...");
// 🛡️ 处理数组越界异常
int[] numbers = {1, 2, 3};
try {
System.out.println("访问索引5:" + numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界:" + e.getMessage());
}
// 🛡️ 处理空指针异常
String text = null;
try {
int length = text.length();
System.out.println("字符串长度:" + length);
} catch (NullPointerException e) {
System.out.println("空指针异常:" + e.getMessage());
}
// 🛡️ 处理数字格式异常
String numberStr = "abc123";
try {
int number = Integer.parseInt(numberStr);
System.out.println("转换结果:" + number);
} catch (NumberFormatException e) {
System.out.println("数字格式错误:" + e.getMessage());
}
}
}
🔄 多重catch语句
💻 多重异常处理
import java.util.Scanner;
public class MultipleCatchDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入两个整数进行除法运算:");
try {
System.out.print("被除数:");
int dividend = Integer.parseInt(scanner.nextLine());
System.out.print("除数:");
int divisor = Integer.parseInt(scanner.nextLine());
int result = dividend / divisor;
System.out.println("结果:" + result);
} catch (NumberFormatException e) {
System.out.println("输入格式错误,请输入有效的整数!");
} catch (ArithmeticException e) {
System.out.println("除数不能为零!");
} catch (Exception e) {
System.out.println("发生未知错误:" + e.getMessage());
}
scanner.close();
}
}
🔒 finally语句块
💻 finally语句使用
import java.io.*;
public class FinallyDemo {
public static void main(String[] args) {
// 🔒 finally块总是会执行
try {
System.out.println("执行try块");
int result = 10 / 2;
System.out.println("计算结果:" + result);
} catch (Exception e) {
System.out.println("执行catch块");
} finally {
System.out.println("执行finally块(总是执行)");
}
// 🔒 资源管理示例
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
System.out.println("文件打开成功");
// 读取文件操作...
} catch (FileNotFoundException e) {
System.out.println("文件未找到:" + e.getMessage());
} finally {
// 确保资源被释放
if (fis != null) {
try {
fis.close();
System.out.println("文件已关闭");
} catch (IOException e) {
System.out.println("关闭文件时出错:" + e.getMessage());
}
}
}
// 🔒 try-with-resources语句(Java 7+)
try (FileInputStream fis2 = new FileInputStream("test.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis2))) {
String line = reader.readLine();
System.out.println("读取内容:" + line);
} catch (IOException e) {
System.out.println("文件操作异常:" + e.getMessage());
} // 资源会自动关闭
}
}
🎯 自定义异常
💻 自定义异常类
// 🎯 自定义异常类
class AgeException extends Exception {
public AgeException(String message) {
super(message);
}
}
class BankAccountException extends Exception {
private double balance;
private double amount;
public BankAccountException(String message, double balance, double amount) {
super(message);
this.balance = balance;
this.amount = amount;
}
public double getBalance() { return balance; }
public double getAmount() { return amount; }
}
// 🏦 银行账户类
class BankAccount {
private String accountNumber;
private double balance;
public BankAccount(String accountNumber, double balance) {
this.accountNumber = accountNumber;
this.balance = balance;
}
// 🏦 取款方法
public void withdraw(double amount) throws BankAccountException {
if (amount <= 0) {
throw new BankAccountException("取款金额必须大于0", balance, amount);
}
if (amount > balance) {
throw new BankAccountException("余额不足", balance, amount);
}
balance -= amount;
System.out.println("取款成功,余额:" + balance);
}
// 👤 设置年龄方法
public void setAge(int age) throws AgeException {
if (age < 0 || age > 150) {
throw new AgeException("年龄必须在0-150之间,当前输入:" + age);
}
System.out.println("年龄设置成功:" + age);
}
public double getBalance() { return balance; }
}
public class CustomExceptionDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount("123456", 1000.0);
// 🏦 测试银行账户异常
try {
account.withdraw(1500); // 余额不足
} catch (BankAccountException e) {
System.out.println("银行操作失败:" + e.getMessage());
System.out.println("当前余额:" + e.getBalance());
System.out.println("尝试取款:" + e.getAmount());
}
// 👤 测试年龄异常
try {
account.setAge(-5); // 无效年龄
} catch (AgeException e) {
System.out.println("年龄设置失败:" + e.getMessage());
}
try {
account.setAge(25); // 有效年龄
} catch (AgeException e) {
System.out.println("年龄设置失败:" + e.getMessage());
}
}
}
📝 异常处理最佳实践
💡 异常处理原则
• 具体处理:捕获具体的异常类型,而不是Exception
• 及时处理:在合适的层级处理异常
• 资源管理:使用try-with-resources或finally确保资源释放
• 日志记录:记录异常信息便于调试
• 用户友好:向用户提供有意义的错误信息
• 具体处理:捕获具体的异常类型,而不是Exception
• 及时处理:在合适的层级处理异常
• 资源管理:使用try-with-resources或finally确保资源释放
• 日志记录:记录异常信息便于调试
• 用户友好:向用户提供有意义的错误信息
⚠️ 异常处理注意事项
• 不要忽略异常(空catch块)
• 不要过度使用异常处理控制程序流程
• 自定义异常要有明确的语义
• 注意异常的性能开销
• 合理使用检查异常和非检查异常
• 不要忽略异常(空catch块)
• 不要过度使用异常处理控制程序流程
• 自定义异常要有明确的语义
• 注意异常的性能开销
• 合理使用检查异常和非检查异常
📅 日期时间API
🎯 Java日期时间API概述
📅 Java日期时间API:Java 8引入了全新的日期时间API,解决了旧API的诸多问题
✨ 新旧API对比
| 特性 | 旧API (Java 7及之前) | 新API (Java 8+) |
|---|---|---|
| 🏗️ 主要类 | Date, Calendar, SimpleDateFormat | LocalDate, LocalTime, LocalDateTime |
| 🔒 线程安全 | ❌ 不安全 | ✅ 不可变,线程安全 |
| 🎯 易用性 | 复杂,容易出错 | 简洁,直观 |
| 🌍 时区支持 | 有限 | 完善的时区支持 |
| 📊 性能 | 较差 | 更好 |
| 🔄 可变性 | 可变 | 不可变 |
🕐 LocalDate - 日期类
💻 LocalDate基本使用
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class LocalDateDemo {
public static void main(String[] args) {
// 📅 创建LocalDate对象
System.out.println("=== LocalDate创建 ===");
// 获取当前日期
LocalDate today = LocalDate.now();
System.out.println("今天: " + today);
// 指定日期
LocalDate specificDate = LocalDate.of(2024, 1, 1);
System.out.println("指定日期: " + specificDate);
// 从字符串解析
LocalDate parsedDate = LocalDate.parse("2024-12-25");
System.out.println("解析日期: " + parsedDate);
// 📊 获取日期信息
System.out.println("\n=== 日期信息获取 ===");
System.out.println("年份: " + today.getYear());
System.out.println("月份: " + today.getMonth());
System.out.println("月份数值: " + today.getMonthValue());
System.out.println("日: " + today.getDayOfMonth());
System.out.println("星期: " + today.getDayOfWeek());
System.out.println("一年中的第几天: " + today.getDayOfYear());
// 🔄 日期运算
System.out.println("\n=== 日期运算 ===");
LocalDate tomorrow = today.plusDays(1);
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate nextYear = today.plusYears(1);
System.out.println("明天: " + tomorrow);
System.out.println("下周: " + nextWeek);
System.out.println("下月: " + nextMonth);
System.out.println("明年: " + nextYear);
LocalDate yesterday = today.minusDays(1);
LocalDate lastMonth = today.minusMonths(1);
System.out.println("昨天: " + yesterday);
System.out.println("上月: " + lastMonth);
// 🔍 日期比较
System.out.println("\n=== 日期比较 ===");
LocalDate date1 = LocalDate.of(2024, 6, 15);
LocalDate date2 = LocalDate.of(2024, 8, 20);
System.out.println("date1在date2之前: " + date1.isBefore(date2));
System.out.println("date1在date2之后: " + date1.isAfter(date2));
System.out.println("date1等于date2: " + date1.isEqual(date2));
// 📏 计算日期间隔
System.out.println("\n=== 日期间隔计算 ===");
long daysBetween = ChronoUnit.DAYS.between(date1, date2);
long monthsBetween = ChronoUnit.MONTHS.between(date1, date2);
System.out.println("两个日期相差天数: " + daysBetween);
System.out.println("两个日期相差月数: " + monthsBetween);
// 🎯 实用方法
System.out.println("\n=== 实用方法 ===");
System.out.println("是否为闰年: " + today.isLeapYear());
System.out.println("本月天数: " + today.lengthOfMonth());
System.out.println("本年天数: " + today.lengthOfYear());
// 获取月份的第一天和最后一天
LocalDate firstDayOfMonth = today.withDayOfMonth(1);
LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());
System.out.println("本月第一天: " + firstDayOfMonth);
System.out.println("本月最后一天: " + lastDayOfMonth);
}
}
🕐 LocalTime - 时间类
💻 LocalTime基本使用
import java.time.*;
import java.time.temporal.ChronoUnit;
public class LocalTimeDemo {
public static void main(String[] args) {
// 🕐 创建LocalTime对象
System.out.println("=== LocalTime创建 ===");
// 获取当前时间
LocalTime now = LocalTime.now();
System.out.println("现在时间: " + now);
// 指定时间
LocalTime specificTime = LocalTime.of(14, 30, 45);
System.out.println("指定时间: " + specificTime);
// 带纳秒的时间
LocalTime preciseTime = LocalTime.of(9, 15, 30, 123456789);
System.out.println("精确时间: " + preciseTime);
// 从字符串解析
LocalTime parsedTime = LocalTime.parse("18:30:45");
System.out.println("解析时间: " + parsedTime);
// 📊 获取时间信息
System.out.println("\n=== 时间信息获取 ===");
System.out.println("小时: " + now.getHour());
System.out.println("分钟: " + now.getMinute());
System.out.println("秒: " + now.getSecond());
System.out.println("纳秒: " + now.getNano());
// 🔄 时间运算
System.out.println("\n=== 时间运算 ===");
LocalTime oneHourLater = now.plusHours(1);
LocalTime thirtyMinutesLater = now.plusMinutes(30);
LocalTime tenSecondsLater = now.plusSeconds(10);
System.out.println("一小时后: " + oneHourLater);
System.out.println("30分钟后: " + thirtyMinutesLater);
System.out.println("10秒后: " + tenSecondsLater);
LocalTime oneHourEarlier = now.minusHours(1);
System.out.println("一小时前: " + oneHourEarlier);
// 🔍 时间比较
System.out.println("\n=== 时间比较 ===");
LocalTime morning = LocalTime.of(9, 0);
LocalTime afternoon = LocalTime.of(15, 0);
System.out.println("上午在下午之前: " + morning.isBefore(afternoon));
System.out.println("下午在上午之后: " + afternoon.isAfter(morning));
// 📏 计算时间间隔
System.out.println("\n=== 时间间隔计算 ===");
long hoursBetween = ChronoUnit.HOURS.between(morning, afternoon);
long minutesBetween = ChronoUnit.MINUTES.between(morning, afternoon);
System.out.println("相差小时数: " + hoursBetween);
System.out.println("相差分钟数: " + minutesBetween);
// 🎯 时间截断
System.out.println("\n=== 时间截断 ===");
LocalTime currentTime = LocalTime.now();
System.out.println("当前时间: " + currentTime);
System.out.println("截断到小时: " + currentTime.truncatedTo(ChronoUnit.HOURS));
System.out.println("截断到分钟: " + currentTime.truncatedTo(ChronoUnit.MINUTES));
System.out.println("截断到秒: " + currentTime.truncatedTo(ChronoUnit.SECONDS));
}
}
🕐 LocalDateTime - 日期时间类
💻 LocalDateTime综合使用
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class LocalDateTimeDemo {
public static void main(String[] args) {
// 🕐 创建LocalDateTime对象
System.out.println("=== LocalDateTime创建 ===");
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println("现在: " + now);
// 指定日期时间
LocalDateTime specificDateTime = LocalDateTime.of(2024, 12, 25, 10, 30, 45);
System.out.println("指定日期时间: " + specificDateTime);
// 从LocalDate和LocalTime组合
LocalDate date = LocalDate.of(2024, 6, 15);
LocalTime time = LocalTime.of(14, 30);
LocalDateTime combined = LocalDateTime.of(date, time);
System.out.println("组合日期时间: " + combined);
// 从字符串解析
LocalDateTime parsed = LocalDateTime.parse("2024-08-20T15:45:30");
System.out.println("解析日期时间: " + parsed);
// 📊 获取日期时间信息
System.out.println("\n=== 日期时间信息 ===");
System.out.println("年: " + now.getYear());
System.out.println("月: " + now.getMonthValue());
System.out.println("日: " + now.getDayOfMonth());
System.out.println("时: " + now.getHour());
System.out.println("分: " + now.getMinute());
System.out.println("秒: " + now.getSecond());
// 提取日期和时间部分
LocalDate dateOnly = now.toLocalDate();
LocalTime timeOnly = now.toLocalTime();
System.out.println("仅日期: " + dateOnly);
System.out.println("仅时间: " + timeOnly);
// 🔄 日期时间运算
System.out.println("\n=== 日期时间运算 ===");
LocalDateTime future = now.plusDays(7).plusHours(3).plusMinutes(30);
System.out.println("7天3小时30分钟后: " + future);
LocalDateTime past = now.minusMonths(2).minusWeeks(1);
System.out.println("2个月1周前: " + past);
// 🎨 格式化输出
System.out.println("\n=== 格式化输出 ===");
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a");
System.out.println("标准格式: " + now.format(formatter1));
System.out.println("中文格式: " + now.format(formatter2));
System.out.println("美式格式: " + now.format(formatter3));
// 🔍 日期时间比较和计算
System.out.println("\n=== 比较和计算 ===");
LocalDateTime start = LocalDateTime.of(2024, 1, 1, 9, 0);
LocalDateTime end = LocalDateTime.of(2024, 12, 31, 18, 0);
Duration duration = Duration.between(start, end);
Period period = Period.between(start.toLocalDate(), end.toLocalDate());
System.out.println("时间间隔(Duration): " + duration.toDays() + "天");
System.out.println("日期间隔(Period): " + period.getYears() + "年" +
period.getMonths() + "月" + period.getDays() + "天");
// 🎯 实际应用示例
demonstrateRealWorldUsage();
}
public static void demonstrateRealWorldUsage() {
System.out.println("\n=== 实际应用示例 ===");
// 📅 会议安排系统
LocalDateTime meetingStart = LocalDateTime.of(2024, 8, 20, 14, 0);
LocalDateTime meetingEnd = meetingStart.plusHours(2);
System.out.println("会议开始: " + meetingStart.format(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
System.out.println("会议结束: " + meetingEnd.format(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
// 检查会议是否在工作时间
LocalTime workStart = LocalTime.of(9, 0);
LocalTime workEnd = LocalTime.of(18, 0);
boolean isDuringWorkHours = meetingStart.toLocalTime().isAfter(workStart) &&
meetingEnd.toLocalTime().isBefore(workEnd);
System.out.println("会议在工作时间内: " + isDuringWorkHours);
// 📊 年龄计算
LocalDate birthDate = LocalDate.of(1990, 5, 15);
LocalDate today = LocalDate.now();
Period age = Period.between(birthDate, today);
System.out.println("出生日期: " + birthDate);
System.out.println("年龄: " + age.getYears() + "岁" + age.getMonths() + "个月");
// 🎯 倒计时计算
LocalDateTime newYear = LocalDateTime.of(2025, 1, 1, 0, 0);
LocalDateTime current = LocalDateTime.now();
if (current.isBefore(newYear)) {
Duration countdown = Duration.between(current, newYear);
long days = countdown.toDays();
long hours = countdown.toHours() % 24;
long minutes = countdown.toMinutes() % 60;
System.out.println("距离新年还有: " + days + "天" + hours + "小时" + minutes + "分钟");
}
}
}
🌍 时区处理
💻 时区处理示例
import java.time.*;
import java.time.format.DateTimeFormatter;
public class TimeZoneDemo {
public static void main(String[] args) {
// 🌍 ZonedDateTime - 带时区的日期时间
System.out.println("=== 时区处理 ===");
// 获取当前时区的日期时间
ZonedDateTime nowInSystemZone = ZonedDateTime.now();
System.out.println("系统时区时间: " + nowInSystemZone);
// 指定时区的日期时间
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
ZonedDateTime nowInNewYork = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime nowInLondon = ZonedDateTime.now(ZoneId.of("Europe/London"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("东京时间: " + nowInTokyo.format(formatter));
System.out.println("纽约时间: " + nowInNewYork.format(formatter));
System.out.println("伦敦时间: " + nowInLondon.format(formatter));
// 🔄 时区转换
System.out.println("\n=== 时区转换 ===");
LocalDateTime localDateTime = LocalDateTime.of(2024, 8, 20, 15, 30);
// 将本地时间转换为不同时区
ZonedDateTime beijingTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
ZonedDateTime tokyoTime = beijingTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
ZonedDateTime utcTime = beijingTime.withZoneSameInstant(ZoneId.of("UTC"));
System.out.println("北京时间: " + beijingTime.format(formatter));
System.out.println("转换为东京时间: " + tokyoTime.format(formatter));
System.out.println("转换为UTC时间: " + utcTime.format(formatter));
// 📊 显示所有可用时区
System.out.println("\n=== 部分可用时区 ===");
ZoneId.getAvailableZoneIds().stream()
.filter(zone -> zone.contains("Asia") || zone.contains("America"))
.sorted()
.limit(10)
.forEach(System.out::println);
// 🎯 实际应用:国际会议时间安排
scheduleInternationalMeeting();
}
public static void scheduleInternationalMeeting() {
System.out.println("\n=== 国际会议时间安排 ===");
// 会议安排在北京时间2024年8月20日下午3点
LocalDateTime meetingLocal = LocalDateTime.of(2024, 8, 20, 15, 0);
ZonedDateTime meetingBeijing = meetingLocal.atZone(ZoneId.of("Asia/Shanghai"));
// 转换为各个时区的时间
String[] timeZones = {
"Asia/Shanghai", // 北京
"Asia/Tokyo", // 东京
"Europe/London", // 伦敦
"America/New_York", // 纽约
"America/Los_Angeles" // 洛杉矶
};
String[] cities = {"北京", "东京", "伦敦", "纽约", "洛杉矶"};
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM月dd日 HH:mm");
System.out.println("国际会议时间安排:");
for (int i = 0; i < timeZones.length; i++) {
ZonedDateTime cityTime = meetingBeijing.withZoneSameInstant(ZoneId.of(timeZones[i]));
System.out.println(cities[i] + ": " + cityTime.format(formatter));
}
}
}
🔧 常用工具类
🎯 Objects工具类
🔧 Objects类:Java 7引入的工具类,提供了对象操作的实用方法
💻 Objects工具类使用
import java.util.Objects;
public class ObjectsDemo {
public static void main(String[] args) {
// 🔍 空值安全比较
System.out.println("=== 空值安全操作 ===");
String str1 = "Hello";
String str2 = "Hello";
String str3 = null;
String str4 = null;
// 安全的equals比较
System.out.println("Objects.equals(str1, str2): " + Objects.equals(str1, str2)); // true
System.out.println("Objects.equals(str1, str3): " + Objects.equals(str1, str3)); // false
System.out.println("Objects.equals(str3, str4): " + Objects.equals(str3, str4)); // true
// 安全的hashCode计算
System.out.println("Objects.hashCode(str1): " + Objects.hashCode(str1));
System.out.println("Objects.hashCode(str3): " + Objects.hashCode(str3)); // 0
// 🛡️ 空值检查
System.out.println("\n=== 空值检查 ===");
try {
// 要求非空,如果为空抛出异常
String nonNull = Objects.requireNonNull(str1, "字符串不能为空");
System.out.println("非空字符串: " + nonNull);
// 这行会抛出异常
// Objects.requireNonNull(str3, "字符串不能为空");
} catch (NullPointerException e) {
System.out.println("捕获异常: " + e.getMessage());
}
// 检查是否为空
System.out.println("str1是否为空: " + Objects.isNull(str1));
System.out.println("str3是否为空: " + Objects.isNull(str3));
System.out.println("str1是否非空: " + Objects.nonNull(str1));
// 🎯 toString安全转换
System.out.println("\n=== 安全toString ===");
System.out.println("Objects.toString(str1): " + Objects.toString(str1));
System.out.println("Objects.toString(str3): " + Objects.toString(str3)); // "null"
System.out.println("Objects.toString(str3, \"默认值\"): " + Objects.toString(str3, "默认值"));
// 🔢 深度equals和hashCode
System.out.println("\n=== 深度比较 ===");
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = {1, 2, 4};
System.out.println("Arrays.equals(array1, array2): " + java.util.Arrays.equals(array1, array2));
System.out.println("Objects.deepEquals(array1, array2): " + Objects.deepEquals(array1, array2));
System.out.println("Objects.deepEquals(array1, array3): " + Objects.deepEquals(array1, array3));
}
}
🔧 Arrays工具类
💻 Arrays工具类使用
import java.util.Arrays;
import java.util.List;
public class ArraysDemo {
public static void main(String[] args) {
// 📋 数组操作
System.out.println("=== 数组基本操作 ===");
int[] numbers = {5, 2, 8, 1, 9, 3};
System.out.println("原数组: " + Arrays.toString(numbers));
// 🔄 数组排序
int[] sortedNumbers = numbers.clone();
Arrays.sort(sortedNumbers);
System.out.println("排序后: " + Arrays.toString(sortedNumbers));
// 🔍 二分查找(需要先排序)
int index = Arrays.binarySearch(sortedNumbers, 8);
System.out.println("数字8的位置: " + index);
// 📋 数组填充
int[] filledArray = new int[5];
Arrays.fill(filledArray, 42);
System.out.println("填充数组: " + Arrays.toString(filledArray));
// 📋 数组复制
int[] copiedArray = Arrays.copyOf(numbers, 10); // 复制并扩展
System.out.println("复制扩展: " + Arrays.toString(copiedArray));
int[] rangeArray = Arrays.copyOfRange(numbers, 1, 4); // 复制范围
System.out.println("范围复制: " + Arrays.toString(rangeArray));
// 🔍 数组比较
System.out.println("\n=== 数组比较 ===");
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = {1, 2, 4};
System.out.println("array1 equals array2: " + Arrays.equals(array1, array2));
System.out.println("array1 equals array3: " + Arrays.equals(array1, array3));
// 📝 数组转List
System.out.println("\n=== 数组转换 ===");
String[] stringArray = {"apple", "banana", "cherry"};
List<String> stringList = Arrays.asList(stringArray);
System.out.println("数组转List: " + stringList);
// ⚠️ 注意:asList返回的是固定大小的List
try {
// stringList.add("date"); // 会抛出UnsupportedOperationException
} catch (UnsupportedOperationException e) {
System.out.println("asList返回的List不支持添加操作");
}
// 🎯 多维数组操作
System.out.println("\n=== 多维数组 ===");
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
System.out.println("二维数组: " + Arrays.deepToString(matrix));
int[][] matrix2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
System.out.println("深度比较: " + Arrays.deepEquals(matrix, matrix2));
}
}
📊 Math类与Random类
🔢 Math类
💻 Math类常用方法
public class MathDemo {
public static void main(String[] args) {
// 📊 基本数学运算
System.out.println("=== 基本数学运算 ===");
double a = 16.0;
double b = -25.0;
double c = 3.7;
System.out.println("绝对值 |" + b + "| = " + Math.abs(b));
System.out.println("平方根 √" + a + " = " + Math.sqrt(a));
System.out.println("立方根 ∛" + a + " = " + Math.cbrt(a));
System.out.println("2的3次方 = " + Math.pow(2, 3));
// 🔄 取整函数
System.out.println("\n=== 取整函数 ===");
double decimal = 3.7;
double negative = -3.7;
System.out.println("Math.ceil(" + decimal + ") = " + Math.ceil(decimal)); // 向上取整
System.out.println("Math.floor(" + decimal + ") = " + Math.floor(decimal)); // 向下取整
System.out.println("Math.round(" + decimal + ") = " + Math.round(decimal)); // 四舍五入
System.out.println("Math.ceil(" + negative + ") = " + Math.ceil(negative));
System.out.println("Math.floor(" + negative + ") = " + Math.floor(negative));
System.out.println("Math.round(" + negative + ") = " + Math.round(negative));
// 📏 最大值和最小值
System.out.println("\n=== 最值函数 ===");
int x = 10, y = 20, z = 5;
System.out.println("max(" + x + ", " + y + ") = " + Math.max(x, y));
System.out.println("min(" + x + ", " + y + ") = " + Math.min(x, y));
// 找出三个数的最大值
int maxOfThree = Math.max(Math.max(x, y), z);
System.out.println("三个数的最大值: " + maxOfThree);
// 📐 三角函数
System.out.println("\n=== 三角函数 ===");
double angle = Math.PI / 4; // 45度
System.out.println("sin(π/4) = " + Math.sin(angle));
System.out.println("cos(π/4) = " + Math.cos(angle));
System.out.println("tan(π/4) = " + Math.tan(angle));
// 角度和弧度转换
double degrees = 45;
double radians = Math.toRadians(degrees);
System.out.println(degrees + "度 = " + radians + "弧度");
System.out.println(radians + "弧度 = " + Math.toDegrees(radians) + "度");
// 📊 对数函数
System.out.println("\n=== 对数函数 ===");
double number = 100;
System.out.println("ln(" + number + ") = " + Math.log(number)); // 自然对数
System.out.println("log10(" + number + ") = " + Math.log10(number)); // 常用对数
System.out.println("e^2 = " + Math.exp(2)); // e的幂
// 🎯 常用常数
System.out.println("\n=== 数学常数 ===");
System.out.println("π = " + Math.PI);
System.out.println("e = " + Math.E);
// 🎲 随机数
System.out.println("\n=== 随机数 ===");
System.out.println("0-1之间的随机数: " + Math.random());
System.out.println("1-100之间的随机整数: " + (int)(Math.random() * 100 + 1));
// 🎯 实际应用示例
calculateDistance();
}
// 计算两点间距离
public static void calculateDistance() {
System.out.println("\n=== 实际应用:计算两点间距离 ===");
double x1 = 1, y1 = 1;
double x2 = 4, y2 = 5;
double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
System.out.printf("点(%.1f, %.1f)到点(%.1f, %.1f)的距离: %.2f%n",
x1, y1, x2, y2, distance);
}
}
🎲 Random类
💻 Random类使用示例
import java.util.Random;
import java.util.Arrays;
public class RandomDemo {
public static void main(String[] args) {
// 🎲 创建Random对象
Random random = new Random();
Random seededRandom = new Random(12345); // 使用种子,结果可重现
// 🔢 生成不同类型的随机数
System.out.println("=== 基本随机数生成 ===");
System.out.println("随机boolean: " + random.nextBoolean());
System.out.println("随机int: " + random.nextInt());
System.out.println("0-99的随机int: " + random.nextInt(100));
System.out.println("随机long: " + random.nextLong());
System.out.println("随机float: " + random.nextFloat());
System.out.println("随机double: " + random.nextDouble());
// 🎯 指定范围的随机数
System.out.println("\n=== 指定范围随机数 ===");
// 1-100之间的随机整数
int randomInt = random.nextInt(100) + 1;
System.out.println("1-100随机数: " + randomInt);
// 10.0-20.0之间的随机小数
double randomDouble = 10.0 + (20.0 - 10.0) * random.nextDouble();
System.out.println("10.0-20.0随机数: " + String.format("%.2f", randomDouble));
// 🎲 高斯分布随机数
System.out.println("\n=== 高斯分布随机数 ===");
for (int i = 0; i < 5; i++) {
double gaussian = random.nextGaussian(); // 均值0,标准差1
System.out.println("高斯随机数: " + String.format("%.3f", gaussian));
}
// 📊 随机数组
System.out.println("\n=== 随机数组 ===");
int[] randomArray = new int[10];
for (int i = 0; i < randomArray.length; i++) {
randomArray[i] = random.nextInt(100);
}
System.out.println("随机数组: " + Arrays.toString(randomArray));
// 🎯 实际应用示例
demonstrateApplications();
}
public static void demonstrateApplications() {
Random random = new Random();
// 🎲 模拟掷骰子
System.out.println("\n=== 应用1:掷骰子模拟 ===");
for (int i = 0; i < 5; i++) {
int dice = random.nextInt(6) + 1; // 1-6
System.out.println("第" + (i + 1) + "次掷骰子: " + dice);
}
// 🎰 随机选择
System.out.println("\n=== 应用2:随机选择 ===");
String[] colors = {"红色", "蓝色", "绿色", "黄色", "紫色"};
String randomColor = colors[random.nextInt(colors.length)];
System.out.println("随机选择的颜色: " + randomColor);
// 🔀 数组洗牌
System.out.println("\n=== 应用3:数组洗牌 ===");
Integer[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println("原数组: " + Arrays.toString(numbers));
// Fisher-Yates洗牌算法
for (int i = numbers.length - 1; i > 0; i--) {
int j = random.nextInt(i + 1);
Integer temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
System.out.println("洗牌后: " + Arrays.toString(numbers));
// 🎫 生成随机密码
System.out.println("\n=== 应用4:生成随机密码 ===");
String password = generateRandomPassword(12);
System.out.println("随机密码: " + password);
}
// 生成随机密码
public static String generateRandomPassword(int length) {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
Random random = new Random();
StringBuilder password = new StringBuilder();
for (int i = 0; i < length; i++) {
int index = random.nextInt(chars.length());
password.append(chars.charAt(index));
}
return password.toString();
}
}
🤔 常见问题与最佳实践
❓ String相关常见问题
1️⃣ String拼接性能问题
❌ 性能问题代码
在循环中使用String拼接会创建大量临时对象,影响性能
在循环中使用String拼接会创建大量临时对象,影响性能
✅ 正确做法
使用StringBuilder进行频繁的字符串操作
使用StringBuilder进行频繁的字符串操作
💻 对比示例
public class StringPerformanceDemo {
public static void main(String[] args) {
int iterations = 10000;
// ❌ 错误方式:String拼接
long startTime = System.currentTimeMillis();
String result1 = "";
for (int i = 0; i < iterations; i++) {
result1 += "a"; // 每次都创建新对象
}
long time1 = System.currentTimeMillis() - startTime;
// ✅ 正确方式:StringBuilder
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append("a"); // 在原对象上修改
}
String result2 = sb.toString();
long time2 = System.currentTimeMillis() - startTime;
System.out.println("String拼接耗时: " + time1 + "ms");
System.out.println("StringBuilder耗时: " + time2 + "ms");
System.out.println("性能提升: " + (time1 / (double)time2) + "倍");
}
}
2️⃣ 字符串比较陷阱
💻 字符串比较最佳实践
public class StringComparisonBestPractices {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = null;
// ❌ 错误:使用==比较内容
System.out.println("str1 == str2: " + (str1 == str2)); // false
// ✅ 正确:使用equals比较内容
System.out.println("str1.equals(str2): " + str1.equals(str2)); // true
// ✅ 更安全:常量在前,避免NullPointerException
System.out.println("\"Hello\".equals(str3): " + "Hello".equals(str3)); // false
// ✅ 最安全:使用Objects.equals
System.out.println("Objects.equals(str1, str3): " +
java.util.Objects.equals(str1, str3)); // false
// ✅ 忽略大小写比较
String str4 = "HELLO";
System.out.println("忽略大小写比较: " + str1.equalsIgnoreCase(str4)); // true
}
}
❓ 包装类相关问题
3️⃣ 自动装箱拆箱陷阱
💻 装箱拆箱注意事项
public class AutoBoxingTraps {
public static void main(String[] args) {
// ⚠️ 陷阱1:缓存范围内外的比较
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println("127 == 127: " + (a == b)); // true (缓存范围内)
System.out.println("128 == 128: " + (c == d)); // false (超出缓存范围)
// ⚠️ 陷阱2:null值的自动拆箱
Integer nullInteger = null;
try {
int value = nullInteger; // 自动拆箱,抛出NullPointerException
} catch (NullPointerException e) {
System.out.println("null值自动拆箱异常: " + e.getClass().getSimpleName());
}
// ✅ 正确做法:检查null值
if (nullInteger != null) {
int safeValue = nullInteger;
System.out.println("安全拆箱: " + safeValue);
}
// ⚠️ 陷阱3:性能问题
long startTime = System.currentTimeMillis();
Integer sum = 0;
for (int i = 0; i < 100000; i++) {
sum += i; // 每次都装箱拆箱
}
long boxingTime = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();
int primitiveSum = 0;
for (int i = 0; i < 100000; i++) {
primitiveSum += i; // 基本类型运算
}
long primitiveTime = System.currentTimeMillis() - startTime;
System.out.println("装箱运算耗时: " + boxingTime + "ms");
System.out.println("基本类型耗时: " + primitiveTime + "ms");
}
}
❓ 日期时间API问题
4️⃣ 日期时间最佳实践
💻 日期时间最佳实践
import java.time.*;
import java.time.format.DateTimeFormatter;
public class DateTimeBestPractices {
public static void main(String[] args) {
// ✅ 使用不可变的日期时间类
LocalDateTime now = LocalDateTime.now();
LocalDateTime future = now.plusDays(7); // 返回新对象,原对象不变
System.out.println("原时间: " + now);
System.out.println("7天后: " + future);
// ✅ 使用合适的类型
LocalDate dateOnly = LocalDate.now(); // 只需要日期
LocalTime timeOnly = LocalTime.now(); // 只需要时间
LocalDateTime dateTime = LocalDateTime.now(); // 需要日期和时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(); // 需要时区信息
// ✅ 安全的字符串解析
String dateStr = "2024-08-20";
try {
LocalDate parsed = LocalDate.parse(dateStr);
System.out.println("解析成功: " + parsed);
} catch (Exception e) {
System.out.println("解析失败: " + e.getMessage());
}
// ✅ 使用标准格式化器
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String formatted = now.format(formatter);
System.out.println("标准格式: " + formatted);
// ✅ 时区转换最佳实践
ZonedDateTime utcTime = ZonedDateTime.now(ZoneId.of("UTC"));
ZonedDateTime localTime = utcTime.withZoneSameInstant(ZoneId.systemDefault());
System.out.println("UTC时间: " + utcTime);
System.out.println("本地时间: " + localTime);
}
}
💡 性能优化建议
🚀 性能优化要点
| 场景 | 建议 | 原因 |
|---|---|---|
| 🔤 频繁字符串操作 | 使用StringBuilder | 避免创建大量临时对象 |
| 🔢 大量数值运算 | 使用基本类型 | 避免装箱拆箱开销 |
| 📅 日期时间处理 | 使用新API | 性能更好,线程安全 |
| 🔍 字符串比较 | 使用equals方法 | 比较内容而非引用 |
| 🎲 随机数生成 | 复用Random对象 | 避免重复创建开销 |
🛡️ 安全编程建议
🔒 安全编程要点
• 始终检查null值,使用Objects.equals进行安全比较
• 使用try-catch处理可能的解析异常
• 在多线程环境中使用不可变对象
• 避免在循环中进行昂贵的操作
• 合理选择数据类型,避免不必要的转换
• 始终检查null值,使用Objects.equals进行安全比较
• 使用try-catch处理可能的解析异常
• 在多线程环境中使用不可变对象
• 避免在循环中进行昂贵的操作
• 合理选择数据类型,避免不必要的转换
📝 本章小结
🎉 恭喜!你已经掌握了Java核心API的使用!
✅ 学习成果检查清单
🎯 知识掌握情况
| 学习内容 | 掌握程度 | 检查方式 |
|---|---|---|
| 📝 String类 | ✅ 已掌握 | 能熟练使用字符串操作方法 |
| 🔢 包装类 | ✅ 已掌握 | 理解自动装箱拆箱机制 |
| 📊 集合框架 | ✅ 已掌握 | 熟练使用List、Set、Map |
| 🚨 异常处理 | ✅ 已掌握 | 能正确处理各种异常情况 |
| 📅 日期时间API | ✅ 已掌握 | 能使用新的日期时间API |
| 🔧 工具类 | ✅ 已掌握 | 熟悉Objects、Arrays等工具类 |
| 📊 Math类 | ✅ 已掌握 | 能进行各种数学运算 |
| 🎲 Random类 | ✅ 已掌握 | 能生成各种类型的随机数 |
🏆 技能成就解锁
📝 字符串处理专家
掌握String类的各种操作方法
掌握String类的各种操作方法
🔢 数据类型大师
熟练使用包装类和类型转换
熟练使用包装类和类型转换
📅 时间管理能手
掌握现代日期时间API
掌握现代日期时间API
🔧 工具类专家
熟练使用各种工具类
熟练使用各种工具类
📊 集合框架大师
掌握List、Set、Map的使用
掌握List、Set、Map的使用
🚨 异常处理专家
能够优雅地处理各种异常
能够优雅地处理各种异常
🎯 核心API速查表
📝 String类常用方法
| 方法 | 功能 | 示例 |
|---|---|---|
length() | 获取长度 | "Hello".length() → 5 |
charAt(int) | 获取字符 | "Hello".charAt(1) → ‘e’ |
substring(int, int) | 截取子串 | "Hello".substring(1, 4) → “ell” |
indexOf(String) | 查找位置 | "Hello".indexOf("ll") → 2 |
replace(String, String) | 替换 | "Hello".replace("l", "x") → “Hexxo” |
split(String) | 分割 | "a,b,c".split(",") → [“a”, “b”, “c”] |
🔢 包装类对应关系
| 基本类型 | 包装类 | 解析方法 | 转换方法 |
|---|---|---|---|
int | Integer | parseInt() | valueOf() |
double | Double | parseDouble() | valueOf() |
boolean | Boolean | parseBoolean() | valueOf() |
char | Character | - | valueOf() |
📅 日期时间类选择
| 需求 | 推荐类 | 说明 |
|---|---|---|
| 只需要日期 | LocalDate | 2024-08-20 |
| 只需要时间 | LocalTime | 14:30:45 |
| 日期+时间 | LocalDateTime | 2024-08-20T14:30:45 |
| 需要时区 | ZonedDateTime | 2024-08-20T14:30:45+08:00 |
📋 实战练习作业
💪 实践出真知:通过练习巩固API使用技能
🎯 基础练习(必做)
练习1:字符串处理工具 ⭐⭐⭐
// 编写一个字符串工具类,包含以下功能:
// 1. 统计字符串中各字符出现次数
// 2. 判断字符串是否为回文
// 3. 移除字符串中的重复字符
// 4. 将字符串按指定长度分割
练习2:数据类型转换器 ⭐⭐⭐
// 编写一个安全的数据类型转换工具:
// 1. 字符串安全转换为各种数值类型
// 2. 提供默认值机制
// 3. 异常处理和日志记录
// 4. 支持批量转换
🚀 进阶练习(选做)
练习3:日期时间工具类 ⭐⭐⭐⭐
// 开发一个实用的日期时间工具类:
// 1. 计算两个日期间的工作日天数
// 2. 获取指定月份的所有周末日期
// 3. 时区转换和格式化
// 4. 节假日判断功能
练习4:随机数据生成器 ⭐⭐⭐⭐⭐
// 创建一个随机数据生成器:
// 1. 生成随机姓名、邮箱、电话号码
// 2. 生成指定格式的测试数据
// 3. 支持批量生成和导出
// 4. 可配置的数据规则
🗺️ 专栏学习路径图
📈 Java程序员从0到1成长路径
🎯 第一阶段:Java基础入门 (4-6周) - ✅ 已完成
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.开发环境 │───▶│ 2.基础语法 │───▶│ 3.面向对象 │───▶│ 4.核心API │
│ 搭建 │ │ │ │ 编程基础 │ │ │
│ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🚀 第二阶段:Java进阶技能 (4-6周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.高级特性 │ │ 2.I/O与网络 │ │ 3.新特性 │ │ 4.工具框架 │
│ │ │ 编程 │ │ │ │ 入门 │
│ 🎯 下一步 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🎯 第三阶段:项目实战 (4-8周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.小型项目 │ │ 2.Web开发 │ │ 3.Spring │ │ 4.数据库与 │
│ 开发 │ │ 基础 │ │ 框架入门 │ │ 持久层 │
│ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🏆 第四阶段:职业发展 (持续更新)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.代码质量 │ │ 2.开发工具 │ │ 3.面试准备 │ │ 4.职业规划 │
│ 与规范 │ │ 链 │ │ │ │ │
│ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
📋 学习进度总结
| 阶段 | 章节 | 主要内容 | 状态 | 完成度 |
|---|---|---|---|---|
| 🎯 第一阶段 | 1.开发环境搭建 | JDK安装、Hello World、IDE使用 | ✅ 已完成 | 100% |
| 🎯 第一阶段 | 2.基础语法 | 变量、数据类型、运算符、流程控制 | ✅ 已完成 | 100% |
| 🎯 第一阶段 | 3.面向对象基础 | 类与对象、封装、继承、多态 | ✅ 已完成 | 100% |
| 🎯 第一阶段 | 4.核心API | String、集合框架、异常处理 | ✅ 已完成 | 100% |
| 🚀 第二阶段 | 1.Java高级特性 | 泛型、反射、注解、枚举 | 🎯 下一步 | 0% |
🎉 第一阶段完成!
• 第一阶段进度:100% (4/4章节完成)
• 下一步:进入第二阶段 - Java进阶技能
• 建议:回顾总结第一阶段知识,准备学习高级特性
• 重点:掌握泛型编程、反射机制、注解和枚举
• 第一阶段进度:100% (4/4章节完成)
• 下一步:进入第二阶段 - Java进阶技能
• 建议:回顾总结第一阶段知识,准备学习高级特性
• 重点:掌握泛型编程、反射机制、注解和枚举
📚 推荐学习资源
🌟 官方文档
| 资源 | 链接 | 说明 |
|---|---|---|
| 📖 Oracle Java API文档 | docs.oracle.com | 最权威的API参考 |
| 📚 Java教程 | docs.oracle.com/javase/tutorial/ | 官方学习教程 |
| 🔍 OpenJDK文档 | openjdk.java.net | 开源Java实现 |
📖 推荐书籍
📚 深入学习
• 《Java核心技术 卷I》 - API使用的详细说明
• 《Effective Java》 - API使用的最佳实践
• 《Java性能权威指南》 - 性能优化技巧
• 《Java并发编程实战》 - 并发API的深入理解
• 《Java核心技术 卷I》 - API使用的详细说明
• 《Effective Java》 - API使用的最佳实践
• 《Java性能权威指南》 - 性能优化技巧
• 《Java并发编程实战》 - 并发API的深入理解
🎬 下一章预告
🚀 第二阶段第1章:Java高级特性
🎯 下章学习内容
- 🔧 泛型编程与类型安全
- 🔍 反射机制与动态编程
- 📝 注解详解与自定义注解
- 📊 枚举类型与应用场景
- 🎯 高级特性综合应用
📚 学习重点
- 掌握泛型的使用和通配符
- 理解反射的原理和应用
- 学会创建和使用注解
- 熟练使用枚举类型
- 提升代码质量和开发效率
🚀 准备好探索Java的高级特性了吗?
💡 学习小贴士
掌握了Java核心API,你就拥有了强大的编程工具箱!
这些API是日常开发中最常用的,务必熟练掌握!
记住:熟练使用API是高效编程的基础! 🌟
📧 有问题?欢迎在评论区讨论交流!
⭐ 觉得有用?别忘了点赞收藏!
🔄 继续关注,更多精彩内容即将到来!






