常用工具类,正则和枚举以及异常

常用工具类

java提供了许多实用的工具类,可以大大提高开发效率。以下是java中最实用的工具类分类介绍

1.集合工具类

java.util.Collections

提供对集合操作的静态方法

常用的方法
Collections.sort(list);               // 排序
Collections.reverse(list);            // 反转
Collections.shuffle(list);            // 随机打乱
Collections.max(list);                // 获取最大值
Collections.min(list);                // 获取最小值
Collections.binarySearch(list, key);   // 二分查找
Collections.synchronizedList(list);    // 获取线程安全集合

java.util.Arrays

数组操作工具类

常用方法
Arrays.sort(arr);                     // 数组排序
Arrays.binarySearch(arr, key);        // 二分查找
Arrays.copyOf(arr, newLength);        // 数组复制
Arrays.equals(arr1, arr2);            // 数组比较
Arrays.fill(arr, value);              // 填充数组
Arrays.toString(arr);                 // 数组转字符串

2.字符串工具类

org.apache.commons.lang3.StringUtils(Apache Commons Lang)

比JDK的String类提供更多的功能

常用方法

StringUtils.isEmpty(str);            // 判断空字符串
StringUtils.isBlank(str);             // 判断空白字符串
StringUtils.join(array, separator);   // 数组/集合拼接
StringUtils.split(str, separator);    // 字符串分割
StringUtils.trim(str);                // 去除两端空格
StringUtils.substring(str, start, end); // 截取子串

java.util.StringJoiner (JDK 8+)

用于构造由分隔符分隔的字符序列

示例:

StringJoiner sj = new StringJoiner(",", "[", "]");
sj.add("A").add("B").add("C");
System.out.println(sj);  // 输出: [A,B,C]

3.日期时间工具类

java.time包(JDK 8+)

LocalDate – 日期
LocalTime – 时间
LocalDateTime – 日期时间
DateTimeFoermatter – 日期格式化

示例

LocalDate today = LocalDate.now();

LocalDateTime now = LocalDateTime.now();

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

String formatted = now.format(formatter);

org.apache.commons.lang3.time.ateUtils(Apche Commons Lang)

提供日期操作功能

常用方法

DateUtils.addDays(date, 1);           // 添加天数
DateUtils.addHours(date, 1);          // 添加小时
DateUtils.truncate(date, Calendar.DAY_OF_MONTH); // 截断时间

4.数学工具类

java.lang.Math

基本数学运算

常用方法
Math.abs(-1);           // 绝对值
Math.max(a, b);         // 最大值
Math.min(a, b);         // 最小值
Math.sqrt(9);           // 平方根
Math.pow(2, 3);         // 幂运算
Math.round(3.14);       // 四舍五入
Math.random();          // 随机数 [0,1)

java.math.BigDecimal

精确的十进制运算

示例

BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal sum = bd1.add(bd2);  // 0.3 (精确)

5.IO/文件工具类

org.apache.commons.io.FileUtils(Apach Commons IO)

文件操作工具

常用方法
FileUtils.readFileToString(file, "UTF-8");  // 读取文件内容
FileUtils.writeStringToFile(file, content);  // 写入文件
FileUtils.copyFile(src, dest);               // 复制文件
FileUtils.deleteDirectory(dir);              // 删除目录

Org.apache.commons.io.IOUtils(Apache Commons IO)

IO流操作工具

常用方法
IOUtils.copy(inputStream, outputStream);    // 流复制
IOUtils.toString(inputStream, "UTF-8");     // 流转字符串
IOUtils.closeQuietly(closeable);            // 安静关闭流

6.反射工具类

org.apache.commons.lang3.reflect.FieldUtils(Apache Commons Lang)

反射操作工具

常用方法
FieldUtils.readField(obj, "fieldName", true); // 读取字段值
FieldUtils.writeField(obj, "fieldName", value, true); // 设置字段值

7.其他实用工具类

java.util.Objects(JDK 7+)

对象操作工具

常用方法
Objects.equals(a, b);      // 安全的对象比较
Objects.hashCode(obj);     // 安全的哈希码
Objects.requireNonNull(obj); // 非空检查

org.apache.commons.lang3.RandomUtils(Apache Commons Lang)

随机数生成

常用方法
RandomUtils.nextInt(startInclusive, endExclusive); // 随机整数
RandomUtils.nextDouble(startInclusive, endExclusive); // 随机浮点数

使用建议

优先使用 JDK 自带的工具类
对于复杂操作,可以考虑引入 Apache Commons Lang/IO 等第三方库
注意线程安全问题,特别是集合工具类
对于日期操作,推荐使用 JDK 8 的 java.time

这些工具类可以显著减少样板代码,提高开发效率和代码质量。

正则和枚举

正则表达式

1.基本正则表达式类

java提供了java.util.regex包来处理正则表达式,

主要包含了两个类

Pattern:真个则表达式的编译表示

Matcher:通过解释Pattern对字符序列执行匹配操作的引擎

java正则表达式的基本用法

import java.util.regex.*;

public class RegexBasic {
    public static void main(String[] args) {
        // 1. 简单匹配
        Pattern pattern = Pattern.compile("hello");
        Matcher matcher = pattern.matcher("hello world");
        System.out.println("简单匹配结果: " + matcher.find());
        
        // 2. 元字符使用
        checkPattern("\d", "123", "数字匹配");       // 匹配数字
        checkPattern("\D", "abc", "非数字匹配");     // 匹配非数字
        checkPattern("\w", "a1_", "单词字符匹配");   // 匹配单词字符[a-zA-Z_0-9]
        checkPattern("\W", "@#$", "非单词字符匹配"); // 匹配非单词字符
        checkPattern("\s", " ", "空白字符匹配");      // 匹配空白字符
        checkPattern("\S", "a", "非空白字符匹配");    // 匹配非空白字符
        
        // 3. 量词使用
        checkPattern("a?", "a", "0或1次匹配");        // 0或1次
        checkPattern("a*", "aaa", "0或多次匹配");     // 0或多次
        checkPattern("a+", "aaa", "1或多次匹配");      // 1或多次
        checkPattern("a{3}", "aaa", "精确次数匹配");   // 精确3次
        checkPattern("a{2,4}", "aaa", "范围次数匹配"); // 2到4次
    }
    
    private static void checkPattern(String regex, String input, String description) {
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        System.out.printf("%s (%s): %b%n", description, regex, m.find());
    }
}

2.常用正则表达式模式

电子邮件验证

import java.util.regex.*;

public class EmailValidation {
    public static void main(String[] args) {
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$";
        
        String[] emails = {
            "test@example.com",
            "user.name@domain.co",
            "invalid.email@",
            "missing@dotcom",
            "special@chars.com"
        };
        
        Pattern pattern = Pattern.compile(emailRegex);
        
        for (String email : emails) {
            Matcher matcher = pattern.matcher(email);
            System.out.printf("%-20s: %s%n", email, matcher.matches() ? "有效" : "无效");
        }
    }
}

手机号验证

import java.util.regex.*;

public class PhoneValidation {
    public static void main(String[] args) {
        // 中国手机号正则
        String phoneRegex = "^1[3-9]\d{9}$";
        
        String[] phones = {
            "13800138000",
            "12345678901",
            "15812345678",
            "98765432109",
            "17712345678"
        };
        
        Pattern pattern = Pattern.compile(phoneRegex);
        
        for (String phone : phones) {
            Matcher matcher = pattern.matcher(phone);
            System.out.printf("%-11s: %s%n", phone, matcher.matches() ? "有效" : "无效");
        }
    }
}

3.高级正则表达式功能

分组和捕获

import java.util.regex.*;

public class RegexGroups {
    public static void main(String[] args) {
        String dateRegex = "(\d{4})-(\d{2})-(\d{2})";
        String date = "2023-05-15";
        
        Pattern pattern = Pattern.compile(dateRegex);
        Matcher matcher = pattern.matcher(date);
        
        if (matcher.find()) {
            System.out.println("完整匹配: " + matcher.group(0));
            System.out.println("年份: " + matcher.group(1));
            System.out.println("月份: " + matcher.group(2));
            System.out.println("日期: " + matcher.group(3));
        }
    }
}

查找和替换

import java.util.regex.*;

public class RegexReplace {
    public static void main(String[] args) {
        String text = "The quick brown fox jumps over the lazy dog.";
        String regex = "\b\w{4}\b"; // 匹配4字母单词
        
        // 替换所有4字母单词为"****"
        String replaced = text.replaceAll(regex, "****");
        System.out.println("替换结果: " + replaced);
        
        // 使用Matcher进行更复杂的替换
        Pattern pattern = Pattern.compile("(\w)(\w{2})(\w)");
        Matcher matcher = pattern.matcher(text);
        StringBuffer sb = new StringBuffer();
        
        while (matcher.find()) {
            matcher.appendReplacement(sb, 
                matcher.group(1).toUpperCase() + 
                matcher.group(2) + 
                matcher.group(3).toLowerCase());
        }
        matcher.appendTail(sb);
        
        System.out.println("复杂替换: " + sb.toString());
    }
}

4.常用正则表达式模式总结

用途

正则表达式模式

说明

用户名

^[a-zA-Z0-9_-]{3,16}$

3-16字符,包含字母数字-_

强密码

^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@#$%^&+=]).{8,}$

至少8字符,包含大小写字母、数字和特殊字符

IPv4地址

^(\d{1,3}\.){3}\d{1,3}$

基本IPv4格式验证

URL

^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$

HTTP/HTTPS URL验证

中文

^[\u4e00-\u9fa5]+$

纯中文字符

身份证号(15或18位)

`^(d{15}

d{17}[dxX])$`

5.性能优化建议

1. 预编译模式

对于频繁使用的正则表达式,使用 Pattern.compile() 预编译

2. 避免贪婪量词

在不需要时使用非贪婪量词 *?+???

3. 使用边界匹配

^$ 可以提高匹配效率

4. 简化字符类

[a-z](a|b|c|...|z) 更高效

5. 避免回溯

复杂的正则表达式可能导致性能问题

通过掌握这些正则表达式知识和技巧,您可以在Java中高效地进行文本处理和验证。

枚举(Enum)

1. 基本枚举定义

基础枚举示例

public enum Day {
    MONDAY, 
    TUESDAY, 
    WEDNESDAY,
    THURSDAY, 
    FRIDAY, 
    SATURDAY, 
    SUNDAY
}

2. 带属性的枚举

带属性的枚举

public enum Planet {
    MERCURY(3.303e+23, 2.4397e6),
    VENUS(4.869e+24, 6.0518e6),
    EARTH(5.976e+24, 6.37814e6),
    MARS(6.421e+23, 3.3972e6),
    JUPITER(1.9e+27, 7.1492e7),
    SATURN(5.688e+26, 6.0268e7),
    URANUS(8.686e+25, 2.5559e7),
    NEPTUNE(1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double getMass() { return mass; }
    public double getRadius() { return radius; }

    // universal gravitational constant (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }

    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}

3. 枚举方法与抽象方法

枚举方法与抽象方法

public enum Operation {
    PLUS {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE {
        public double apply(double x, double y) { return x / y; }
    };

    public abstract double apply(double x, double y);
}

4. 枚举实用方法

枚举实用方法

import java.util.EnumSet;

public class EnumTest {
    public static void main(String[] args) {
        // 遍历枚举
        for (Day day : Day.values()) {
            System.out.println(day);
        }

        // 使用EnumSet
        EnumSet<Day> weekdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
        System.out.println("Weekdays: " + weekdays);

        // 根据名称获取枚举实例
        Day day = Day.valueOf("MONDAY");
        System.out.println("Found: " + day);

        // 枚举比较
        System.out.println("Is Monday before Friday? " + 
            Day.MONDAY.compareTo(Day.FRIDAY) < 0);
    }
}

5. 枚举实现接口

枚举实现接口

一、枚举基础

1. 枚举定义

枚举(enum)是Java 5引入的一种特殊数据类型,用于定义一组固定的常量。

// 基本枚举定义
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

2. 枚举特点

类型安全:比使用常量(int/String)更安全
可读性强:枚举值有明确的名称
功能丰富:可以添加方法、属性等
天然单例:每个枚举实例都是单例的

二、带属性的枚举

1. 定义带属性的枚举

public enum Planet {
    // 枚举值(调用构造函数)
    MERCURY(3.303e+23, 2.4397e6),
    VENUS(4.869e+24, 6.0518e6),
    EARTH(5.976e+24, 6.37814e6);
    
    // 枚举属性
    private final double mass;   // 质量(kg)
    private final double radius; // 半径(m)
    
    // 枚举构造函数(必须是private或包私有)
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    
    // 枚举方法
    public double getMass() { return mass; }
    public double getRadius() { return radius; }
    
    // 计算表面重力
    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    
    // 常量
    public static final double G = 6.67300E-11;
}

2. 使用带属性的枚举

public class EnumTest {
    public static void main(String[] args) {
        double earthWeight = 175; // 地球上的重量(磅)
        double mass = earthWeight / Planet.EARTH.surfaceGravity();
        
        for (Planet p : Planet.values()) {
            System.out.printf("Your weight on %s is %f%n",
                p, p.surfaceWeight(mass));
        }
    }
}

三、枚举方法与抽象方法

1. 枚举中定义方法

public enum Operation {
    PLUS, MINUS, TIMES, DIVIDE;
    
    // 枚举方法
    public double apply(double x, double y) {
        switch(this) {
            case PLUS: return x + y;
            case MINUS: return x - y;
            case TIMES: return x * y;
            case DIVIDE: return x / y;
        }
        throw new AssertionError("未知操作: " + this);
    }
}

2. 枚举中定义抽象方法(更优雅的实现)

public enum Operation {
    PLUS {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE {
        public double apply(double x, double y) { return x / y; }
    };
    
    // 抽象方法,每个枚举值必须实现
    public abstract double apply(double x, double y);
}

四、枚举实用方法

1. values()方法

返回枚举的所有值数组

Day[] days = Day.values();
for (Day day : days) {
    System.out.println(day);
}

2. valueOf()方法

根据名称获取枚举值

Day day = Day.valueOf("MONDAY"); // 返回Day.MONDAY

3. name()和ordinal()方法

Day day = Day.MONDAY;
System.out.println(day.name());    // 输出"MONDAY"
System.out.println(day.ordinal()); // 输出0(枚举定义的顺序)

五、枚举实现接口

1. 枚举实现接口

public interface Command {
    void execute();
}

public enum Direction implements Command {
    LEFT {
        public void execute() {
            System.out.println("向左转");
        }
    },
    RIGHT {
        public void execute() {
            System.out.println("向右转");
        }
    };
}

2. 使用接口统一处理枚举

public class Test {
    public static void main(String[] args) {
        Command cmd = Direction.LEFT;
        cmd.execute(); // 输出"向左转"
    }
}

六、枚举单例模式

1. 枚举实现单例(推荐方式)

public enum Singleton {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("单例方法调用");
    }
}

// 使用
Singleton.INSTANCE.doSomething();

2. 为什么枚举单例是最好的实现方式

线程安全:由JVM保证
防止反射攻击
防止序列化破坏单例
代码简洁

七、枚举高级特性

1. 枚举集合(EnumSet和EnumMap)

// EnumSet示例
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);

// EnumMap示例
EnumMap<Day, String> activityMap = new EnumMap<>(Day.class);
activityMap.put(Day.MONDAY, "上班");
activityMap.put(Day.SATURDAY, "休息");

2. 枚举常量特定方法

public enum ConstantSpecificMethod {
    DATE_TIME {
        String getInfo() { return "日期时间"; }
    },
    IP_ADDRESS {
        String getInfo() { return "IP地址"; }
    };
    
    abstract String getInfo();
}

八、枚举最佳实践

优先使用枚举代替常量:比public static final更安全
为枚举添加有用的方法:增强枚举的功能性
考虑使用枚举实现单例:最安全可靠的实现方式
合理使用枚举集合:EnumSet和EnumMap性能优异
避免过度复杂的枚举:保持简单清晰

枚举是Java中一种强大而灵活的特性,合理使用可以大大提高代码的可读性、安全性和可维护性。

关键特性总结

类型安全:枚举提供了编译时类型检查
可扩展性:可以添加属性、方法和构造函数
单例支持:枚举实例天然是单例的
多态支持:可以通过抽象方法实现多态行为
工具支持values()valueOf()方法自动生成
集合支持EnumSetEnumMap提供高效实现

枚举是Java中一种强大的类型,特别适合表示固定集合的常量,并能通过面向对象的方式扩展功能。

异常

一、异常体系结构

Java 异常体系采用层次化设计,所有异常都继承自 Throwable 类:

Throwable
├── Error (系统严重错误,通常不应捕获)
│   ├── VirtualMachineError
│   ├── OutOfMemoryError
│   └── ...
└── Exception (可检查异常)
    ├── RuntimeException (非检查异常/运行时异常)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── IllegalArgumentException
    │   └── ...
    └── 其他检查异常
        ├── IOException
        ├── SQLException
        └── ...

二、异常分类

1. 检查异常(Checked Exception)

继承自 Exception 但不继承 RuntimeException
编译器强制要求处理
代表程序可以预期并恢复的问题
示例:IOException, SQLException

2. 非检查异常(Unchecked Exception)

继承自 RuntimeException
编译器不强制要求处理
通常代表编程错误
示例:NullPointerException, ArrayIndexOutOfBoundsException

3. 错误(Error)

继承自 Error
表示严重系统问题
应用程序通常不应捕获
示例:OutOfMemoryError, StackOverflowError

三、异常处理关键字

1. try-catch-finally 基本结构

try {
    // 可能抛出异常的代码
} catch (ExceptionType1 e1) {
    // 处理ExceptionType1
} catch (ExceptionType2 e2) {
    // 处理ExceptionType2
} finally {
    // 无论是否发生异常都会执行的代码
    // 常用于资源清理
}

2. try-with-resources (Java 7+)

try (ResourceType resource = new ResourceType()) {
    // 使用资源的代码
} catch (Exception e) {
    // 异常处理
}
// 资源会自动关闭,无需finally块

四、自定义异常

1. 创建检查异常

public class BusinessException extends Exception {
    public BusinessException(String message) {
        super(message);
    }
    
    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }
}

2. 创建非检查异常

public class RuntimeBusinessException extends RuntimeException {
    public RuntimeBusinessException(String message) {
        super(message);
    }
    
    public RuntimeBusinessException(String message, Throwable cause) {
        super(message, cause);
    }
}

五、异常处理最佳实践

早抛出,晚捕获原则

在发现问题的地方立即抛出异常
在能够处理异常的地方集中捕获

避免空的catch块

// 错误示例
try {
    // ...
} catch (Exception e) {
    // 什么都不做
}

使用特定异常而非通用异常

// 好
catch (FileNotFoundException e) { ... }

// 不好
catch (Exception e) { ... }

保留原始异常信息

try {
    // ...
} catch (IOException e) {
    throw new BusinessException("文件处理失败", e);
}

合理使用finally进行资源清理

FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // ...
} catch (IOException e) {
    // ...
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            // 记录日志
        }
    }
}

考虑使用异常链

try {
    // ...
} catch (LowLevelException e) {
    throw new HighLevelException("高层异常信息", e);
}

六、常见异常处理模式

1. 防御性编程模式

public void process(String input) {
    if (input == null) {
        throw new IllegalArgumentException("输入不能为null");
    }
    // 继续处理
}

2. 异常转换模式

public void databaseOperation() throws BusinessException {
    try {
        // JDBC操作
    } catch (SQLException e) {
        throw new BusinessException("数据库操作失败", e);
    }
}

3. 模板方法模式中的异常处理

public void templateMethod() {
    try {
        // 前置处理
        doSomething();
        // 后置处理
    } catch (Exception e) {
        // 统一异常处理
    }
}

protected abstract void doSomething() throws Exception;

七、Java 8 异常处理新特性

1. CompletableFuture 异常处理

CompletableFuture.supplyAsync(() -> {
    // 可能抛出异常的操作
    return doSomething();
}).exceptionally(ex -> {
    // 异常处理
    return defaultValue;
}).thenAccept(result -> {
    // 正常结果处理
});

2. Optional 与异常处理结合

public Optional<String> findUserById(int id) {
    try {
        String user = userDao.findById(id);
        return Optional.ofNullable(user);
    } catch (DataAccessException e) {
        // 记录日志
        return Optional.empty();
    }
}

八、日志记录最佳实践

在捕获异常时记录日志

try {
    // ...
} catch (Exception e) {
    logger.error("处理失败,原因: {}", e.getMessage(), e);
    throw new BusinessException("处理失败", e);
}

避免重复记录日志

确保异常只在一个地方被记录

记录足够上下文信息

包括相关参数、状态等

九、性能考虑

异常处理成本

创建异常对象开销较大(需要填充栈轨迹)
不应使用异常进行常规流程控制

优化建议

在性能关键路径避免频繁抛出异常
预先检查条件比捕获异常更高效

十、总结

Java 异常处理的核心原则:

明确区分检查异常和非检查异常的使用场景
提供有意义的异常信息和适当的异常层次结构
确保资源被正确释放
在适当的抽象层次处理异常
保持异常处理代码简洁且专注

良好的异常处理能显著提高代码的健壮性和可维护性,是编写高质量Java程序的重要组成部分。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容