🚀 第一阶段:Java基础入门④Java核心API
💡 学习目标:掌握Java核心API的使用,包括String类、包装类、日期时间API、常用工具类等
📝 String类详解
🎯 String类的特点
📝 String类:Java中最常用的类之一,用于处理字符串数据
✨ String类核心特性
dart
📝 String类特性
│
├── 🔒 不可变性 (Immutable)
│ ├── 字符串内容不能修改
│ ├── 每次"修改"都创建新对象
│ └── 线程安全
│
├── 🏊 字符串池 (String Pool)
│ ├── 字面量存储在常量池
│ ├── 相同内容共享同一对象
│ └── 节省内存空间
│
├── 🧬 继承关系
│ ├── 继承自Object类
│ ├── 实现Serializable接口
│ ├── 实现Comparable接口
│ └── 实现CharSequence接口
│
└── 🔧 丰富的API方法
├── 字符串操作方法
├── 查找和替换方法
├── 格式化方法
└── 转换方法
🏗️ String对象的创建方式
💻 String创建方式对比
java
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类常用方法
📏 长度和字符访问
💻 基本操作方法
java
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();
}
}
🔍 查找和匹配方法
💻 查找方法示例
java
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
}
}
✂️ 字符串截取和分割
💻 截取和分割方法
java
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);
}
}
}
}
🔄 字符串替换和转换
💻 替换和转换方法
java
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
💻 StringBuilder使用示例
java
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; |
🔄 自动装箱与拆箱
💻 自动装箱拆箱示例
java
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);
}
}
🔧 包装类常用方法
🔄 类型转换方法
💻 包装类转换方法
java
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)
}
}
🔍 包装类的比较
💻 包装类比较陷阱
java
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("空指针异常被避免");
}
}
}
🎯 包装类的实际应用
💻 包装类实际应用示例
java
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;
}
}
📅 日期时间API
🎯 Java日期时间API概述
📅 Java日期时间API:Java 8引入了全新的日期时间API,解决了旧API的诸多问题
✨ 新旧API对比
特性 | 旧API (Java 7及之前) | 新API (Java 8+) |
---|---|---|
🏗️ 主要类 | Date, Calendar, SimpleDateFormat | LocalDate, LocalTime, LocalDateTime |
🔒 线程安全 | ❌ 不安全 | ✅ 不可变,线程安全 |
🎯 易用性 | 复杂,容易出错 | 简洁,直观 |
🌍 时区支持 | 有限 | 完善的时区支持 |
📊 性能 | 较差 | 更好 |
🔄 可变性 | 可变 | 不可变 |
🕐 LocalDate - 日期类
💻 LocalDate基本使用
java
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基本使用
java
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综合使用
java
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 + "分钟");
}
}
}
🌍 时区处理
💻 时区处理示例
java
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工具类使用
java
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工具类使用
java
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类常用方法
java
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类使用示例
java
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拼接会创建大量临时对象,影响性能
✅ 正确做法
使用StringBuilder进行频繁的字符串操作
💻 对比示例
java
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️⃣ 字符串比较陷阱
💻 字符串比较最佳实践
java
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️⃣ 自动装箱拆箱陷阱
💻 装箱拆箱注意事项
java
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️⃣ 日期时间最佳实践
💻 日期时间最佳实践
java
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处理可能的解析异常
• 在多线程环境中使用不可变对象
• 避免在循环中进行昂贵的操作
• 合理选择数据类型,避免不必要的转换
📝 本章小结
🎉 恭喜!你已经掌握了Java核心API的使用!
✅ 学习成果检查清单
🎯 知识掌握情况
学习内容 | 掌握程度 | 检查方式 |
---|---|---|
📝 String类 | ✅ 已掌握 | 能熟练使用字符串操作方法 |
🔢 包装类 | ✅ 已掌握 | 理解自动装箱拆箱机制 |
📅 日期时间API | ✅ 已掌握 | 能使用新的日期时间API |
🔧 工具类 | ✅ 已掌握 | 熟悉Objects、Arrays等工具类 |
📊 Math类 | ✅ 已掌握 | 能进行各种数学运算 |
🎲 Random类 | ✅ 已掌握 | 能生成各种类型的随机数 |
🏆 技能成就解锁
📝 字符串处理专家
掌握String类的各种操作方法
🔢 数据类型大师
熟练使用包装类和类型转换
📅 时间管理能手
掌握现代日期时间API
🔧 工具类专家
熟练使用各种工具类
🎯 核心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:字符串处理工具 ⭐⭐⭐
java
// 编写一个字符串工具类,包含以下功能:
// 1. 统计字符串中各字符出现次数
// 2. 判断字符串是否为回文
// 3. 移除字符串中的重复字符
// 4. 将字符串按指定长度分割
练习2:数据类型转换器 ⭐⭐⭐
java
// 编写一个安全的数据类型转换工具:
// 1. 字符串安全转换为各种数值类型
// 2. 提供默认值机制
// 3. 异常处理和日志记录
// 4. 支持批量转换
🚀 进阶练习(选做)
练习3:日期时间工具类 ⭐⭐⭐⭐
java
// 开发一个实用的日期时间工具类:
// 1. 计算两个日期间的工作日天数
// 2. 获取指定月份的所有周末日期
// 3. 时区转换和格式化
// 4. 节假日判断功能
练习4:随机数据生成器 ⭐⭐⭐⭐⭐
java
// 创建一个随机数据生成器:
// 1. 生成随机姓名、邮箱、电话号码
// 2. 生成指定格式的测试数据
// 3. 支持批量生成和导出
// 4. 可配置的数据规则
🗺️ 下一步学习计划
📈 学习路径图
📚 当前章节 🔧 下一章节 🌐 第六章节 🧵 第七章节 🚀 高级内容
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Java核心API │───▶│ 异常处理机制 │───▶│ 集合框架 │───▶│ 多线程编程 │───▶│ 高级特性 │
│ │ │ │ │ │ │ │ │ │
│ ✅ 已完成 │ │ 🎯 即将学习 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
📋 详细学习计划
章节 | 主要内容 | 预计时间 | 难度 | 状态 |
---|---|---|---|---|
📦 第4章 | String、包装类、日期时间API | 3-4天 | ⭐⭐⭐ | ✅ 已完成 |
🔧 第5章 | 异常处理、try-catch、自定义异常 | 3-4天 | ⭐⭐⭐ | 🎯 下一步 |
🌐 第6章 | 集合框架、List、Set、Map | 5-6天 | ⭐⭐⭐⭐ | 📅 计划中 |
🧵 第7章 | 多线程、并发编程 | 6-7天 | ⭐⭐⭐⭐⭐ | 📅 计划中 |
🚀 第8章 | Lambda表达式、Stream API | 4-5天 | ⭐⭐⭐⭐ | 📅 计划中 |
🎯 学习建议
• 多查阅官方API文档,了解方法的详细用法
• 在实际项目中应用所学的API
• 关注性能和安全性,养成良好的编程习惯
• 学会使用IDE的代码提示和自动补全功能
• 定期回顾和总结,建立知识体系
📚 推荐学习资源
🌟 官方文档
资源 | 链接 | 说明 |
---|---|---|
📖 Oracle Java API文档 | docs.oracle.com | 最权威的API参考 |
📚 Java教程 | docs.oracle.com/javase/tuto... | 官方学习教程 |
🔍 OpenJDK文档 | openjdk.java.net | 开源Java实现 |
📖 推荐书籍
📚 深入学习
• 《Java核心技术 卷I》 - API使用的详细说明
• 《Effective Java》 - API使用的最佳实践
• 《Java性能权威指南》 - 性能优化技巧
• 《Java并发编程实战》 - 并发API的深入理解
🎬 下一章预告
🔧 Java异常处理机制
🎯 下章学习内容
- 🚨 异常的概念和分类
- 🛡️ try-catch-finally语句
- 🎯 自定义异常类
- 📝 异常处理最佳实践
- 🔍 调试和日志记录
🚀 准备好学习如何优雅地处理程序异常了吗?
💡 学习小贴士
掌握了Java核心API,你就拥有了强大的编程工具箱! 这些API是日常开发中最常用的,务必熟练掌握!
记住:熟练使用API是高效编程的基础! 🌟
📧 有问题?欢迎在评论区讨论交流!
⭐ 觉得有用?别忘了点赞收藏!
🔄 继续关注,更多精彩内容即将到来!