1. Java常用类概述
在Java开发中,常用类就像是我们日常生活中的"工具箱",里面装满了各种实用工具。这些类被设计得非常完善,可以直接拿来使用,大大提高了开发效率。作为Java开发者,熟练掌握这些常用类就相当于掌握了编程的"瑞士军刀"。
Java常用类主要分为以下几大类:字符串处理类、数学运算类、日期时间类、集合框架类、IO流类等。每个类别都有其特定的应用场景和使用技巧。在实际开发中,合理选择和使用这些类,可以让代码更加简洁高效。
提示:Java常用类都位于java.lang包和java.util包中,大部分不需要额外导入就可以直接使用。
2. 字符串处理类
2.1 String类详解
String类是Java中最常用的类之一,用于处理文本数据。它有几个重要特性:
- 不可变性:String对象一旦创建就不能修改
- 字符串常量池:相同的字符串字面量会共享内存
- 丰富的API:提供了大量字符串操作方法
// 字符串创建示例 String str1 = "Hello"; // 使用字面量创建 String str2 = new String("World"); // 使用构造方法创建在实际开发中,字符串拼接是一个常见操作。Java提供了多种拼接方式:
// 字符串拼接示例 String result = str1 + " " + str2; // 使用+运算符 String result2 = str1.concat(" ").concat(str2); // 使用concat方法 String result3 = String.join(" ", str1, str2); // 使用String.join注意:在循环中进行大量字符串拼接时,使用StringBuilder性能更好。
2.2 StringBuilder和StringBuffer
StringBuilder和StringBuffer都是可变字符串类,适用于需要频繁修改字符串的场景。它们的主要区别在于线程安全性:
- StringBuilder:非线程安全,性能更高
- StringBuffer:线程安全,性能稍低
// StringBuilder使用示例 StringBuilder sb = new StringBuilder(); sb.append("Hello").append(" ").append("World"); String result = sb.toString();在实际项目中,如果确定只在单线程环境下使用字符串,优先选择StringBuilder以获得更好的性能。
3. 数学运算类
3.1 Math类
Math类提供了各种数学运算的静态方法,包括三角函数、指数、对数、取整等常用数学运算。
// Math类使用示例 double pi = Math.PI; // 圆周率 double sqrt = Math.sqrt(16); // 平方根 double pow = Math.pow(2, 3); // 幂运算 long round = Math.round(3.6); // 四舍五入Math类的方法都是静态的,可以直接通过类名调用,不需要创建Math对象。
3.2 Random类
Random类用于生成伪随机数,在需要随机数的场景非常有用。
// Random类使用示例 Random random = new Random(); int randomInt = random.nextInt(100); // 0-99的随机整数 double randomDouble = random.nextDouble(); // 0.0-1.0的随机小数 boolean randomBoolean = random.nextBoolean(); // 随机布尔值提示:如果需要更安全的随机数生成器,可以考虑使用SecureRandom类。
4. 日期时间类
4.1 Date类
Date类用于表示特定的时间点,精确到毫秒。虽然Java 8之后推荐使用新的时间API,但在一些旧项目中仍然会见到Date类的使用。
// Date类使用示例 Date now = new Date(); // 当前时间 long time = now.getTime(); // 获取时间戳4.2 Calendar类
Calendar类提供了更丰富的日期操作方法,可以方便地进行日期计算。
// Calendar类使用示例 Calendar calendar = Calendar.getInstance(); calendar.set(2023, Calendar.JANUARY, 1); // 设置日期 calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加一天 int year = calendar.get(Calendar.YEAR); // 获取年份4.3 Java 8新日期时间API
Java 8引入了全新的日期时间API,位于java.time包中,更加易用和安全。
// Java 8日期时间API示例 LocalDate today = LocalDate.now(); // 当前日期 LocalTime now = LocalTime.now(); // 当前时间 LocalDateTime dateTime = LocalDateTime.now(); // 当前日期时间 // 日期计算 LocalDate nextWeek = today.plusDays(7); // 一周后的日期新的日期时间API解决了旧API的许多问题,如线程安全、设计混乱等,是Java日期时间处理的未来方向。
5. 集合框架类
5.1 List接口及其实现类
List接口代表有序、可重复的集合,常用的实现类有ArrayList和LinkedList。
// List使用示例 List<String> arrayList = new ArrayList<>(); arrayList.add("Java"); arrayList.add("Python"); arrayList.add("C++"); List<String> linkedList = new LinkedList<>(); linkedList.add("Apple"); linkedList.add("Banana");ArrayList基于动态数组实现,随机访问效率高;LinkedList基于链表实现,插入删除效率高。
5.2 Set接口及其实现类
Set接口代表无序、不可重复的集合,常用的实现类有HashSet和TreeSet。
// Set使用示例 Set<String> hashSet = new HashSet<>(); hashSet.add("Red"); hashSet.add("Green"); hashSet.add("Blue"); Set<String> treeSet = new TreeSet<>(); treeSet.add("Zebra"); treeSet.add("Apple"); treeSet.add("Banana");HashSet基于哈希表实现,查询效率高;TreeSet基于红黑树实现,元素会自动排序。
5.3 Map接口及其实现类
Map接口代表键值对集合,常用的实现类有HashMap和TreeMap。
// Map使用示例 Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("Alice", 25); hashMap.put("Bob", 30); hashMap.put("Charlie", 35); Map<String, Integer> treeMap = new TreeMap<>(); treeMap.put("Orange", 5); treeMap.put("Apple", 3); treeMap.put("Banana", 4);HashMap基于哈希表实现,查询效率高;TreeMap基于红黑树实现,键会自动排序。
6. IO流类
6.1 字节流
字节流用于处理二进制数据,主要类有InputStream和OutputStream。
// 文件复制示例(字节流) try (InputStream in = new FileInputStream("source.txt"); OutputStream out = new FileOutputStream("target.txt")) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); }6.2 字符流
字符流用于处理文本数据,主要类有Reader和Writer。
// 文件读取示例(字符流) try (BufferedReader reader = new BufferedReader(new FileReader("text.txt"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); }提示:使用缓冲流(BufferedInputStream/BufferedReader等)可以显著提高IO性能。
7. 其他实用类
7.1 Arrays类
Arrays类提供了各种操作数组的静态方法,如排序、搜索、填充等。
// Arrays类使用示例 int[] numbers = {5, 3, 8, 1, 4}; Arrays.sort(numbers); // 排序 int index = Arrays.binarySearch(numbers, 4); // 二分查找 Arrays.fill(numbers, 0); // 填充数组7.2 System类
System类提供了与系统相关的实用方法,如标准输入输出、系统属性等。
// System类使用示例 long start = System.currentTimeMillis(); // 获取当前时间戳 // 执行一些操作 long end = System.currentTimeMillis(); System.out.println("耗时:" + (end - start) + "毫秒"); System.getProperties().list(System.out); // 打印系统属性7.3 Objects类
Objects类提供了各种操作对象的静态方法,如空值检查、哈希码计算等。
// Objects类使用示例 String str = null; String result = Objects.requireNonNullElse(str, "default"); // 空值检查 int hash = Objects.hash("Java", "Python", "C++"); // 计算哈希码8. 常见问题与解决方案
8.1 字符串比较问题
新手常犯的错误是使用==比较字符串内容,正确的做法是使用equals方法。
// 错误示例 String s1 = "Java"; String s2 = new String("Java"); if (s1 == s2) { // 错误,比较的是引用 System.out.println("相等"); } // 正确示例 if (s1.equals(s2)) { // 正确,比较的是内容 System.out.println("相等"); }8.2 日期格式化问题
SimpleDateFormat不是线程安全的,在多线程环境下应该避免共享实例。
// 错误示例(多线程环境下) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 多个线程共享使用sdf会导致问题 // 解决方案1:每次创建新实例 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String formatted = sdf.format(new Date()); // 解决方案2:使用ThreadLocal private static final ThreadLocal<SimpleDateFormat> dateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd")); String formatted = dateFormat.get().format(new Date());8.3 集合遍历时的修改问题
在遍历集合时直接修改集合会导致ConcurrentModificationException。
// 错误示例 List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); for (String s : list) { if (s.equals("B")) { list.remove(s); // 抛出ConcurrentModificationException } } // 正确解决方案1:使用迭代器的remove方法 Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); if (s.equals("B")) { it.remove(); // 安全删除 } } // 正确解决方案2:使用Java 8的removeIf方法 list.removeIf(s -> s.equals("B"));9. 性能优化建议
9.1 字符串拼接优化
在循环中进行字符串拼接时,使用StringBuilder可以显著提高性能。
// 低效做法 String result = ""; for (int i = 0; i < 1000; i++) { result += i; // 每次循环都创建新的StringBuilder和String对象 } // 高效做法 StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append(i); } String result = sb.toString();9.2 集合初始化大小
如果能预估集合最终大小,初始化时指定容量可以避免多次扩容。
// 预估有1000个元素 List<String> list = new ArrayList<>(1000); // 避免多次扩容 Map<String, Integer> map = new HashMap<>(1000); // 初始容量10009.3 避免不必要的自动装箱
基本类型和包装类型之间的自动转换会带来性能开销,在性能敏感场景应避免。
// 低效做法(大量自动装箱) Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; // 每次i都会自动装箱为Long } // 高效做法 long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; // 使用基本类型 }10. 实际应用案例
10.1 日志记录工具
结合日期时间和IO流类,我们可以实现一个简单的日志记录工具。
public class SimpleLogger { private static final String LOG_FILE = "application.log"; public static void log(String message) { String timestamp = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); String logEntry = timestamp + " - " + message + System.lineSeparator(); try (FileWriter fw = new FileWriter(LOG_FILE, true); BufferedWriter bw = new BufferedWriter(fw)) { bw.write(logEntry); } catch (IOException e) { System.err.println("日志记录失败: " + e.getMessage()); } } }10.2 配置文件读取
使用Properties类可以方便地读取配置文件。
// config.properties 文件内容 // db.url=jdbc:mysql://localhost:3306/mydb // db.username=root // db.password=123456 public class ConfigLoader { private static final String CONFIG_FILE = "config.properties"; public static Properties loadConfig() { Properties props = new Properties(); try (InputStream input = new FileInputStream(CONFIG_FILE)) { props.load(input); return props; } catch (IOException e) { throw new RuntimeException("加载配置文件失败", e); } } }10.3 数据统计工具
结合集合类和数学运算类,可以实现各种数据统计功能。
public class StatisticsUtils { public static double calculateAverage(List<Double> numbers) { if (numbers == null || numbers.isEmpty()) { return 0; } double sum = 0; for (double num : numbers) { sum += num; } return sum / numbers.size(); } public static double calculateStandardDeviation(List<Double> numbers) { if (numbers == null || numbers.size() < 2) { return 0; } double avg = calculateAverage(numbers); double sum = 0; for (double num : numbers) { sum += Math.pow(num - avg, 2); } return Math.sqrt(sum / (numbers.size() - 1)); } }在实际项目中,熟练掌握这些常用类可以大大提高开发效率。我个人的经验是,对于每个常用类,至少要掌握其核心API和典型使用场景,遇到问题时知道该使用哪个类来解决。同时,要注意不同类之间的性能差异,在性能敏感的场景选择合适的实现类。