25. 【Java】异常处理:让程序更健壮

Python接口自动化测试框架搭建:pytest+requests+Allure实战 接口自动化测试是保障系统稳定性的关键环节,其核心在于将零散的请求脚本转化为可维护、可复用、可稳定执行的工程体系。通过分层设计思想,将配置管理、公共封装、测试数据与用例分离,结合pytest的fixture复用、参数化驱动以及requests对HTTP请求的高效处理,能够实现数据与代码解耦,大幅提升用例编写效率。同时引入Allure报告与持续集成流水线,让测试结果直观可读,并支持环境切换和并行执行。从基础概念到工程实践,本文系统梳理了接口自动化框架的搭建路径,帮助团队降低维护成本,保障回归测试的稳定性。 阅读详情

摘要: 本文全面讲解Java异常处理机制,从异常体系结构到实际应用技巧。详细介绍了try-catch-finally、throw与throws、自定义异常等核心概念,通过真实代码示例演示异常捕获与处理的最佳实践。帮助开发者编写更健壮、可维护的Java程序,让程序在遇到错误时能够优雅恢复而非直接崩溃。

关键词: Java异常处理, try-catch-finally, 受检异常, 自定义异常, 异常最佳实践


从前面的文章走过来,我们写了很多代码,也运行了很多次。但你可能早就注意到了一件事:程序并不总是乖乖听话的。

比如,你写了一个从用户输入读取数字的程序,用户却输入了字母“abc”。程序可能就崩溃了,抛出一串红字。再比如,你打开一个文件,但文件不存在;你访问一个数组的索引,但索引超出了范围。

这些情况,在编程术语中叫作 “异常(Exception)” ——程序在运行过程中发生的、打乱了正常执行流程的意外事件。

如果程序一遇到异常就崩溃,那它未免太脆弱了。一个健壮的程序,应该能够预见到可能发生的错误,并在错误发生时,从容地处理它,而不是直接“死掉”。

今天,我们就来学习 Java 中处理异常的完整机制。它让你的程序学会“带伤前行”,即使遇到问题也能优雅地恢复或退出。


1. 为什么需要异常处理?—— 一个真实的例子

假设你写了一个读取文件内容并显示的程序,代码如下(先不考虑异常处理):

public class FileReaderDemo {
    public static void main(String[] args) {
        // 假设文件不存在
        java.io.FileReader reader = new java.io.FileReader("not_exist.txt");
        // 如果上面抛出了异常,下面的代码不会执行
        System.out.println("文件打开成功");
        reader.close();
    }
}

如果 not_exist.txt 不存在,FileReader 的构造方法会抛出 FileNotFoundException,程序会直接停止,控制台会输出一堆红色错误信息,而“文件打开成功”和 close() 都不会执行。

这显然不是我们想要的。我们希望程序能检测到这个问题,然后告诉用户“文件不存在,请检查文件名”,让程序继续运行或安全退出。

异常机制正是为此而生的。


2. 异常体系的层次结构

在 Java 中,所有异常类都继承自 Throwable 类。Throwable 有两个主要的子类:

  • Error:表示严重错误,通常是 JVM 层面的问题,如 OutOfMemoryError、StackOverflowError。这类错误程序一般无法处理,也不应该去处理(你也处理不了)。我们通常不关心它。
  • Exception:表示程序可以处理的异常情况。这是我们今天的重点。

Exception 又分为两大类:

类型特点是否必须处理常见例子
Checked Exception(受检异常)编译器强制要求处理(要么 try-catch,要么 throws)✅ 必须IOException、SQLException、ClassNotFoundException
Unchecked Exception(非受检异常)不强制处理,通常由编程错误导致❌ 不强制(但可以处理)NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException、IllegalArgumentException

用一张简图表示:

Throwable
  ├── Error (严重错误,如 OutOfMemoryError)
  └── Exception
        ├── RuntimeException (及其子类) ← 未受检异常
        │     ├── NullPointerException
        │     ├── ArithmeticException
        │     └── ... 
        └── (其他 Exception 子类) ← 受检异常
              ├── IOException
              ├── SQLException
              └── ...

受检异常是 Java 的一大特色(很多语言没有)。它的设计哲学是:某些错误是“可预见的”,编译器强制你在编写代码时就考虑处理它们,而不是等到运行时才发现。例如,你打开一个文件,文件不存在是很有可能发生的,所以编译器强迫你处理这种情况。

非受检异常通常是由程序员的失误引起的,比如传入 null、数组越界、除以零。这些错误如果能避免(通过代码检查),就不需要强制处理。当然,你也可以选择捕获它们。


3. 捕获异常 —— try-catch-finally

处理异常的基本语法是 try-catch-finally。

① 基础形式:try-catch
try {
    // 可能抛出异常的代码
    int result = 10 / 0;   // 会抛出 ArithmeticException
} catch (ArithmeticException e) {
    // 捕获到异常后执行这里的代码
    System.out.println("除零错误:" + e.getMessage());
}
  • try 块中放置可能抛出异常的代码。
  • catch 块中放置处理异常的代码。一个 try 可以跟多个 catch 块,分别处理不同类型的异常。
② 多个 catch 块
try {
    String s = null;
    System.out.println(s.length());   // NullPointerException
    int[] arr = new int[5];
    System.out.println(arr[10]);      // ArrayIndexOutOfBoundsException
} catch (NullPointerException e) {
    System.out.println("空指针异常:" + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组越界:" + e.getMessage());
}

多个 catch 时,子类异常必须写在父类异常之前,否则编译报错(因为父类会捕获所有子类,后面的子类 catch 永远不会执行)。

// 错误顺序
catch (Exception e) { ... }   // 父类在前
catch (NullPointerException e) { ... }   // 子类在后,编译错误
③ finally —— 无论如何都会执行的“善后”代码

finally 块中的代码,无论 try 中是否抛出异常,也无论 catch 是否执行,都会在最后执行。它非常适合用来释放资源(如关闭文件、数据库连接)。

java.io.FileReader reader = null;
try {
    reader = new java.io.FileReader("test.txt");
    // 读取文件...
} catch (java.io.FileNotFoundException e) {
    System.out.println("文件未找到:" + e.getMessage());
} catch (java.io.IOException e) {
    System.out.println("IO错误:" + e.getMessage());
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (java.io.IOException e) {
            System.out.println("关闭文件出错:" + e.getMessage());
        }
    }
}

即使 try 或 catch 中有 return 语句,finally 也会在 return 之前执行。所以 finally 是“绝对可靠”的善后之地。

④ try-with-resources —— 更优雅的资源管理(JDK 7+)

上面的代码有点啰嗦,尤其是关闭资源时还要再包一层 try-catch。从 Java 7 开始,引入了 try-with-resources 语法,它自动帮你关闭实现了 AutoCloseable 接口的资源。

try (java.io.FileReader reader = new java.io.FileReader("test.txt");
     java.io.BufferedReader br = new java.io.BufferedReader(reader)) {
    String line = br.readLine();
    System.out.println(line);
} catch (java.io.IOException e) {
    System.out.println("IO错误:" + e.getMessage());
}
// reader 和 br 会自动关闭(不管是否发生异常)

try-with-resources 的语法是在 try 后面的括号里声明资源,多个资源用分号 ; 分隔。这些资源会在 try 结束后自动调用 close(),无需你手动 finally。代码简洁了很多,而且更安全(不会忘记关闭)。

JDK 21 的小提升:在 try-with-resources 中,你可以使用未命名变量 _ 来表示不需要引用的资源:

try (var _ = new java.io.FileInputStream("test.dat")) {
    // 文件自动关闭,但我们不需要引用它
    System.out.println("文件已处理");
} catch (java.io.IOException e) {
    System.out.println("错误:" + e.getMessage());
}

4. 抛出异常 —— throw 和 throws

① throw —— 主动“扔”出异常

你可以在代码中手动抛出异常,使用 throw 关键字。这通常用于检测到某种错误条件时,主动告知调用方。

public void withdraw(double amount) {
    if (amount > balance) {
        throw new IllegalArgumentException("余额不足,当前余额:" + balance);
    }
    balance -= amount;
}

你可以抛出 JDK 内置的异常,也可以抛出自定义异常(后面讲)。

② throws —— 声明“我可能会抛出”

如果一个方法内部可能抛出受检异常,但方法本身不处理它(即没有 try-catch),那么它必须在方法签名中用 throws 关键字声明,告诉调用方:“我可能会抛出这个异常,你看着办吧。”

public void readFile(String path) throws java.io.IOException {
    // 可能抛出 IOException,但不在这里处理
    java.io.FileReader reader = new java.io.FileReader(path);
    // ...
}

调用方要么用 try-catch 处理,要么继续向上 throws。

public void process() throws java.io.IOException {
    readFile("test.txt");   // 如果 readFile 抛异常,process 也抛出
}

// 或者
public void process() {
    try {
        readFile("test.txt");
    } catch (java.io.IOException e) {
        System.out.println("读取失败:" + e.getMessage());
    }
}

规则:

  • 重写的方法不能抛出比父类更宽泛的受检异常(即父类方法抛出的异常范围 >= 子类)。
  • throws 可以声明多个异常类型,用逗号分隔。

5. 自定义异常 —— 让你的错误更有“业务味”

有时候,JDK 自带的异常不足以描述业务层面的错误(比如“库存不足”、“转账金额不能为负数”)。这时,你可以创建自己的异常类。

自定义异常的步骤:

  1. 继承 Exception(如果是受检异常)或 RuntimeException(如果是非受检异常)。
  2. 提供构造方法(通常至少提供一个无参构造和一个带消息的构造)。
// 自定义受检异常
public class InsufficientStockException extends Exception {
    public InsufficientStockException() {
        super();
    }

    public InsufficientStockException(String message) {
        super(message);
    }

    // 还可以带其他参数
    public InsufficientStockException(String productName, int available, int requested) {
        super(String.format("商品 '%s' 库存不足,当前库存:%d,需要:%d", productName, available, requested));
    }
}

// 自定义非受检异常(继承 RuntimeException)
public class ValidationException extends RuntimeException {
    public ValidationException(String message) {
        super(message);
    }
}

使用自定义异常:

public class Product {
    private String name;
    private int stock;

    public void reduceStock(int quantity) throws InsufficientStockException {
        if (stock < quantity) {
            throw new InsufficientStockException(name, stock, quantity);
        }
        stock -= quantity;
    }

    public void setStock(int stock) {
        if (stock < 0) {
            throw new ValidationException("库存不能为负数:" + stock);
        }
        this.stock = stock;
    }
}

自定义异常能让你的 API 更加清晰,调用方可以精确捕获特定业务错误,而不是笼统地捕获 Exception。


6. 异常处理的最佳实践

① 不要“吞掉”异常
try {
    // ...
} catch (Exception e) {
    // 空的 catch 块:什么也不做
}

这是最危险的做法之一。你把异常吞掉了,程序虽然没崩溃,但错误也悄无声息地被忽略了,后续可能出现更奇怪的问题。至少要打印日志或输出错误信息。

② 尽可能使用具体的异常类型

不要总写 catch (Exception e)。应该捕获具体子类,这样你才能针对不同异常做不同处理。

try {
    // ...
} catch (NullPointerException e) {
    // 处理空指针
} catch (IllegalArgumentException e) {
    // 处理非法参数
}
③ 早抛出,晚捕获
  • 早抛出:在错误发生的地方立刻抛出异常,带上清晰的错误信息,便于定位问题。
  • 晚捕获:在合适的层(比如用户交互层或最外层)统一捕获并处理,不要在每个方法里都 catch 了又吞掉。让上层决策如何处理。
④ 使用 try-with-resources 管理资源

尽量使用 try-with-resources,避免手动 finally 关闭资源。代码更简洁,也不会遗漏。

⑤ 不要用异常来控制正常流程

异常的处理成本较高,不应被用于正常的业务逻辑分支(比如用异常来判断文件是否存在,应该用 Files.exists() 检查)。异常只应用于“意外”情况。

⑥ 文档化

如果方法抛出受检异常,一定要在 JavaDoc 中用 @throws 标签说明,让调用方知道需要注意什么。


7. 异常处理综合示例

我们来写一个包含多种异常处理方式的完整程序:一个简单的银行账户类,包含取款、存款、转账功能,其中会用到受检异常、非受检异常、自定义异常、try-catch 和 throws。

// ========== 自定义异常:余额不足(受检) ==========
public class InsufficientBalanceException extends Exception {
    public InsufficientBalanceException(String message) {
        super(message);
    }
}

// ========== 自定义异常:账户不存在(非受检) ==========
public class AccountNotFoundException extends RuntimeException {
    public AccountNotFoundException(String accountId) {
        super("账户不存在:" + accountId);
    }
}

// ========== 银行账户类 ==========
public class BankAccount {
    private String accountId;
    private String owner;
    private double balance;

    public BankAccount(String accountId, String owner, double balance) {
        this.accountId = accountId;
        this.owner = owner;
        this.balance = balance;
    }

    public String getAccountId() { return accountId; }
    public double getBalance() { return balance; }

    // 存款(不会抛出受检异常)
    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("存款金额必须大于0");
        }
        balance += amount;
        System.out.println("✅ 存入 " + amount + ",当前余额:" + balance);
    }

    // 取款(可能抛出受检异常)
    public void withdraw(double amount) throws InsufficientBalanceException {
        if (amount <= 0) {
            throw new IllegalArgumentException("取款金额必须大于0");
        }
        if (amount > balance) {
            throw new InsufficientBalanceException(
                "账户 " + accountId + " 余额不足,当前余额:" + balance + ",需要:" + amount
            );
        }
        balance -= amount;
        System.out.println("✅ 取出 " + amount + ",当前余额:" + balance);
    }

    // 转账:从当前账户转到目标账户
    public void transfer(BankAccount target, double amount) 
            throws InsufficientBalanceException {
        if (target == null) {
            throw new IllegalArgumentException("目标账户不能为空");
        }
        if (this == target) {
            throw new IllegalArgumentException("不能给自己转账");
        }
        // 先从当前账户取款(如果余额不足,会抛出 InsufficientBalanceException)
        this.withdraw(amount);
        // 再存入目标账户
        target.deposit(amount);
        System.out.println("🔄 转账 " + amount + " 从 " + this.accountId + " 到 " + target.accountId);
    }
}

// ========== 主程序(包含异常处理演示) ==========
public class Main {
    public static void main(String[] args) {
        // 创建两个账户
        BankAccount acc1 = new BankAccount("A001", "张三", 1000.0);
        BankAccount acc2 = new BankAccount("A002", "李四", 500.0);

        // ---- 1. 正常操作 ----
        System.out.println("=== 正常操作 ===");
        try {
            acc1.withdraw(200);        // 正常
            acc1.transfer(acc2, 300);  // 正常
        } catch (InsufficientBalanceException e) {
            System.out.println("❌ 错误:" + e.getMessage());
        }

        // ---- 2. 余额不足(受检异常) ----
        System.out.println("\n=== 余额不足 ===");
        try {
            acc1.withdraw(10000);      // 余额不足,抛出 InsufficientBalanceException
        } catch (InsufficientBalanceException e) {
            System.out.println("❌ 取款错误:" + e.getMessage());
        }

        // ---- 3. 非法参数(非受检异常) ----
        System.out.println("\n=== 非法参数 ===");
        try {
            acc1.deposit(-50);         // 抛出 IllegalArgumentException
        } catch (IllegalArgumentException e) {
            System.out.println("❌ 参数错误:" + e.getMessage());
        }

        // ---- 4. 空指针检查(非受检异常) ----
        System.out.println("\n=== 空转账 ===");
        try {
            acc1.transfer(null, 100);  // 抛出 IllegalArgumentException
        } catch (IllegalArgumentException | InsufficientBalanceException e) {
            System.out.println("❌ 错误:" + e.getMessage());
        }

        // ---- 5. 显示最终余额 ----
        System.out.println("\n=== 最终余额 ===");
        System.out.println("张三账户:" + acc1.getBalance());
        System.out.println("李四账户:" + acc2.getBalance());

        // ---- 6. try-with-resources 演示 ----
        System.out.println("\n=== try-with-resources 演示 ===");
        try (java.io.FileWriter writer = new java.io.FileWriter("log.txt", true)) {
            writer.write("程序运行完毕,时间:" + System.currentTimeMillis() + "\n");
            System.out.println("日志写入成功");
        } catch (java.io.IOException e) {
            System.out.println("❌ 写入日志失败:" + e.getMessage());
        }
    }
}

运行这个程序,你会看到各种异常被优雅地捕获和处理,程序没有因为任何错误而崩溃。


8. 异常与性能

异常的处理是有开销的。当异常发生时,JVM 需要创建异常对象、填充堆栈轨迹(fillInStackTrace()),这比较耗时。因此:

  • 不要用异常来控制正常的业务流程(比如循环中用异常来终止)。
  • 在性能敏感的场景,尽量减少异常的抛出。

但也要注意:不要为了“优化性能”而牺牲代码的正确性和可维护性。在合理的范围内使用异常,代码会更清晰、更可靠。


9. 今天的总结

今天我们系统地学习了 Java 异常处理:

  • 异常体系:Throwable → Error / Exception → RuntimeException(未受检)和 Checked Exception(受检)。
  • try-catch-finally:捕获并处理异常,finally 确保资源释放。
  • try-with-resources:自动关闭资源,JDK 7+ 引入,更简洁。
  • throw 和 throws:手动抛出异常和方法声明异常。
  • 自定义异常:继承 Exception 或 RuntimeException,携带业务信息。
  • 最佳实践:不吞异常、使用具体类型、早抛出晚捕获、用异常处理意外情况。

异常处理是程序健壮性的重要保障。学会它,你的程序就能在各种意外情况下依然保持“风度和体面”——即使出错,也是友好地告知用户,而不是留下一堆难以理解的红字。


动手试试

  1. 写一个 divide(int a, int b) 方法,如果 b == 0 抛出 ArithmeticException(可以用内置的),并调用方用 try-catch 处理。
  2. 定义一个 NegativeNumberException(受检异常),在 sqrt(double x) 方法中,如果 x < 0 抛出该异常,并捕获处理。
  3. 写一个 FileProcessor 类,用 try-with-resources 读取一个文本文件,统计文件中的行数,处理可能发生的 FileNotFoundException 和 IOException。
  4. (挑战)改造第 16 篇的计算器项目,为其添加异常处理。当用户输入非数字时,用异常处理提示“输入无效,请重新输入”,而不是让程序崩溃。同时,为除法添加自定义 DivisionByZeroException(受检),并捕获处理。

异常处理看似简单,但用得好与不好,差距很大。多练习,培养“预见错误”的思维习惯。

我们下一篇会介绍 Record 的深入用法——这是 JDK 21 中非常重要的特性,值得专门写一篇来讲解它的高级应用和模式匹配。

我们下一篇见。😃

📌 获取本系列示例代码请访问 GitCode。

Java Scanner类深度解析:从输入流原理到实战避坑指南 在Java编程中,输入流处理是程序与用户交互的基础,它负责将外部数据转换为程序可识别的格式。其核心原理是通过分隔符对原始字节流进行令牌化解析,将连续文本分割为独立的数据单元。这一机制为构建健壮的交互式应用提供了技术支撑,尤其在控制台程序、数据解析和用户输入验证等场景中至关重要。理解输入流的工作方式有助于开发者避免常见的陷阱,如换行符残留和类型匹配错误。本文聚焦Java Scanner类的深度应用,通过解析其底层机制和常见问题,帮助开发者掌握nextInt与nextLine的差异处理、自定义分隔符配置以及性能 阅读详情

相关推荐

前端转AI全栈:Java后端学习路径与Spring Boot实践指南

面向对象编程(OOP)是一种以对象为核心的程序设计范式,通过封装、继承和多态三大特性构建模块化、可复用的代码结构。其核心原理在于将数据与操作数据的方法绑定为对象,从而模拟现实世界实体。在工程实践中,OOP极大地提升了代码的可维护性和扩展性,是构建大型复杂系统的基石。在Java生态中,这一理念与Spring Boot框架深度结合,使得开发者能够快速搭建稳健的企业级后端服务。随着AI应用开发热潮的兴起,掌握Java后端技术成为实现AI全栈能力的关键一环,开发者可以运用Spring Boot高效构建RESTful

weixin_34293141的博客 1044

java字符串转换成整数安全做法

Java字符串转换成整数的安全做法 在Java编程中,字符串转换成整数的需求非常常见,如从用户输入、文件读取或API接收的数据中提取数字。然而,这一过程需要谨慎处理,因为在字符串格式不正确的情况下,可能会导致程序抛出异常或产生不可预知的结果。本文将探讨字符串转整数的安全做法,并附有代码示例和图示。 字符串转换成整数的基本方...

weixin_41476491的博客 211

Python自学路线图:从核心语法到实战项目,避开教程陷阱

编程语言学习的关键在于掌握核心概念与工程实践的有效结合。Python作为一门通用编程语言,其核心语法、数据结构与面向对象编程原理构成了技术栈的基础。理解这些基础概念的价值在于能够高效解决实际问题,例如通过列表推导式优化代码性能,或利用函数参数设计灵活接口。在应用场景上,Python广泛应用于数据分析、Web开发和自动化脚本等领域,这要求学习者不仅要懂语法,更要建立项目思维。本文围绕Python自学路径,重点探讨如何通过虚拟环境管理依赖、使用requests和BeautifulSoup4构建爬虫项目,从而打通

weixin_34259232的博客 342

Java课程04总结

1 package 异常处理; 2 3 import javax.swing.*; 4 5 class AboutException { 6 public static void main(String[] a) 7 { 8 int i=1, j=0, k; 9 k=i/j; 10 11 try 12 ...

weixin_30580341的博客 93

Java IO流核心原理与实战:从字节字符流到NIO性能优化

在Java编程中,输入输出(IO)是数据持久化、网络通信和系统交互的基石。其核心抽象“流”(Stream)将数据视为在源与目标间流动的字节或字符序列,通过装饰器模式灵活组合功能。理解字节流与字符流的根本区别——前者处理原始二进制数据,后者专为文本设计并涉及编码解码——是避免乱码和文件损坏的关键。缓冲流通过批量处理减少系统调用,是提升IO性能的通用实践。在需要处理海量数据或高并发连接时,Java NIO提供了基于通道(Channel)和缓冲区(Buffer)的非阻塞模型,有效解决了传统阻塞IO的线程瓶颈。本文

weixin_34212762的博客 558

经典算法之——解决全排列问题以及详解

回溯”指的是“状态重置”,可以理解为“恢复现场”,是在编码的过程中,是为了节约空间而使用的,而在递归或者深度优先中根据需要的场合来配合回溯法可以进一步对自己的代码进行优化。, n-1, n},方向都为向左。邻位对换法是全排列生成算法中的其中一种,它的换位是双向的,通过保存数字的“方向性”来快速得到下一个排列。最后以 3 开头的全排列为[3, 1, 2], [3, 2, 1];以 1 开头的全排列为[1, 2, 3], [1, 3, 2];以 2 开头的全排列为[2, 1, 3], [2, 3, 1];

m0_68987535的博客 8794

Java核心特点:跨平台与面向对象

跨平台性:基于 JVM 实现 “一次编写,到处运行”,是其最核心的优势;面向对象:纯粹的 OOP 设计,支持封装、继承、多态,代码易维护;安全 / 健壮 / 简单:自动 GC、强类型检查、异常处理等特性,降低开发风险,同时简化编程难度;(补充)内置多线程和动态性支持,适合开发高并发、灵活的大型应用。

m0_75050314的博客 250

PackML工业标准解析:统一机器状态管理与数据交换的实践指南

在工业自动化与智能制造领域,实现设备间的互联互通与高效协同是核心挑战。这背后依赖于一套标准化的机器行为与数据交换规范,其原理在于通过定义统一的状态模型与接口协议,消除不同厂商设备间的“语言”隔阂。这项技术的核心价值在于大幅降低系统集成复杂度、提升运维效率与生产透明度,是构建数字化工厂的基石。其典型应用场景包括包装机械、离散制造产线等需要多设备协同的领域。本文聚焦的PackML(包装机械语言)标准,正是这一理念的杰出实践,它通过一套严谨的**状态机模型**和**数据标签(PackTags)** 体系,为机器提

weixin_30070339的博客 399

JavaSE(简述版,待续)

锁的类型包括互斥锁、读写锁、悲观锁和乐观锁等。通过 Stream API,可以实现集合的过滤、映射、排序、归约等操作,并使用函数式编程的方式处理集合元素。线程池是一种用于管理和复用线程的机制,可以减少线程的创建和销毁开销,提高线程的利用率。垃圾回收的基本原理是通过标记清除、标记整理、复制和分代等算法来识别和回收不再使用的对象,从而释放内存空间。在 Java 中,可以使用 Class 类的方法获取类的信息,使用 Method、Field 和 Constructor 类的方法调用方法和操作字段。

qq_30657563的博客 823

鸿蒙OS开机动画背后的秘密:从代码到视觉的完整解析(附源码分析)

本文深入解析了鸿蒙OS开机动画的系统级实现原理。从bootanimation服务的启动配置、与Render Service的协同,到基于VSync信号的帧率同步与绘制流水线,结合OpenHarmony源码进行了逐行解读。文章揭示了其事件驱动的优雅退出机制,并探讨了视频支持、多屏适配等高级特性与定制化可能,为开发者理解鸿蒙图形子系统提供了硬核技术视角。

sony5的博客 969

【技术分享】ArcGIS Pro底图色彩优化实战:从DEM到山体阴影的进阶调色技巧

本文深入探讨了在ArcGIS Pro中优化地形底图色彩的进阶技巧。通过分析DEM与山体阴影的直方图,详细讲解了如何运用图层混合、亮度、对比度及伽马值等核心参数进行精细化调色,从而将灰暗平淡的地图转化为层次分明、视觉美观的专业成果。

5b6n7m8的博客 758

JAVA自定义异常

JAVA自定义异常

798

高通camera驱动 camx read xml 和 probe 流程 和 sensor I2C读写的波形图 (三)

Camx 刚接触的时候对于这个xml 一脸懵逼,实际上和mm-camera差不多就是以xml node节点的方式标准化了driver相关的code,exposure 和 gain的逻辑实现还是在同级目录的cpp中,并且将 xml 的解析工作放在了 out/target/<product>/gen/STATIC_LIBERARIES/libcamxgenerated_intermediates/generated/ 中主要是包含了: g_chromatix : tuning 相关xml的解析co

shangbolei的博客 1万+

java学习整理20170905

1.Java之所以安全的两个安全因素是没有指针且能自动管理内存。 2.面向过程编程:将程序视为一系列依次执行的指令。 3.Import导入目的是为了更好的使用某个类,不必使用某个类的全称。 4.primitive type: 数字类型 整型: byte:8 short:16 int: 32 long: 64 浮点型: float: 32 double: 64 字符类型

qiongjie_csdn的博客 250

MIKE水动力笔记3_岸线及水深数据之根据遥感影像绘制岸线的方法

通过遥感影像自己绘制岸线来制作岸线数据,这种方法获取的岸线及水深数据精度很高,且可以根据自己的研究需要进行灵活处理。

晏长街的博客 1万+

MyBatis-Plus 实战:敏感字段自动加解密支持模糊查询

本文基于MyBatis-Plus框架提出了一种全链路敏感字段加密方案。通过自定义TypeHandler实现数据入库自动加密和查询自动解密,结合重写LambdaQueryWrapper处理查询条件加密,并适配多种查询方式。方案核心包括:1)AESUtil工具类提供加解密基础能力;2)EncryptTypeHandler实现字段类型转换;3)实体类通过注解配置加密字段。该方案在保证数据安全的同时,对业务代码侵入性小,支持姓名、手机号等敏感信息的全流程加密处理,满足系统开发的安全需求。

蔡定努 595

Python基础语法进阶:函数、文件读写、异常处理与类入门

编程入门时,掌握变量和循环只是起点,真正让代码具备工程价值的是对基础语法的深度运用。Python 作为最受欢迎的语言之一,其函数封装、数据结构操作、文件读写、异常处理、模块化设计以及类与对象等机制,构成了构建结构化程序的核心能力。函数能提升代码复用性,列表推导式让数据处理更简洁,文件操作支撑数据持久化,异常处理增强程序健壮性,而模块与包则让项目可维护。这些技术广泛适用于数据分析、自动化脚本、Web 开发等场景。理解这些概念,能从“能写代码”进阶到“会设计代码”,为后续解决真实业务问题打下扎实基础。本文基于

weixin_34279246的博客 402

大数据数据埋点技术面试题及参考答案(持续更新)

事件:指的是用户执行的具体动作,如页面浏览、按钮点击、商品购买等。事件是触发数据记录的直接原因,是分析用户行为的关键点。属性:是与事件相关的额外信息,可以提供关于事件的更多上下文。例如,用户点击的按钮颜色、大小、页面位置等。属性有助于更细致地分析用户行为,理解事件发生的具体情境。事件和属性共同构成了数据埋点的数据模型,它们使得收集的数据具有可分析性,从而可以用于深入理解用户行为和优化产品。

大模型大数据攻城狮的专栏 2097

Java Scanner类深度解析:从核心原理到实战避坑指南

在Java编程中,输入输出(I/O)处理是基础且关键的技术环节,它涉及数据在程序与外部环境(如控制台、文件)间的流动。其核心原理基于流(Stream)和缓冲区(Buffer)机制,流负责数据的连续传输,而缓冲区则作为临时存储区域,用于提升读写效率。Scanner类作为Java SE标准库的一部分,正是构建在这一原理之上的高级文本解析工具,它封装了底层的流操作,提供了便捷的类型转换和模式匹配功能,极大简化了控制台和文本文件的输入处理。从技术价值看,Scanner不仅降低了I/O编程的门槛,其支持正则表达式的特

weixin_34379433的博客 427

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Python基础语法(下):条件判断、循环、函数与异常处理详解

编程逻辑的核心在于条件判断与循环,它们驱动程序做出决策并处理重复任务;函数则封装逻辑实现复用,数据结构负责组织信息,异常处理保障程序稳定运行。这些都是Python基础语法的重要组成部分,也是从简单脚本迈向完整应用的分水岭。本文从编程基础概念出发,系统讲解if/elif/else条件判断、for/while循环、函数定义与参数传递、列表切片与推导式、字典与集合操作,以及try/except异常处理机制。通过综合实战“学生成绩管理系统”,将语法知识与工程实践结合,帮助学习者掌握编写交互式脚本的能力,并为后续面向

weixin_34014555的博客 403

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Python基础快速入门:100分钟掌握核心语法与实战技巧

Python作为一门简洁高效的编程语言,其核心语法设计遵循可读性和易用性原则。通过理解变量类型、条件循环、函数定义等基础概念,开发者可以快速构建可运行的代码。在工程实践中,文件操作和异常处理是提升程序健壮性的关键技术,能够有效处理数据读写和错误排查。这些基础技能在数据分析、Web开发和自动化脚本等场景中具有广泛应用价值。本文以Python环境配置和代码调试为切入点,结合文本词频统计等实战案例,帮助学习者在100分钟内建立完整的知识框架。

weixin_30338497的博客 387

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Python零基础入门教程:从环境搭建到实战项目完整指南

Python作为一门高级、解释型、通用的编程语言,以其简洁的语法和强大的可读性,成为初学者入门编程和快速开发的首选。其核心原理在于解释执行和动态类型,这使得开发者能够用更少的代码表达复杂逻辑,显著提升开发效率。在技术价值层面,Python凭借丰富的标准库和庞大的第三方生态,极大地降低了各类应用的开发门槛。其典型应用场景广泛覆盖Web开发、数据分析、人工智能、自动化脚本和科学计算等领域。本文聚焦于Python入门学习,系统讲解了从环境搭建、基础语法到核心库使用的完整路径,并提供了pip包管理配置、VS Cod

cuizhu0832的博客 368

Python编程从入门到实践:核心语法、项目驱动与调试全攻略

编程语言的核心在于逻辑思维与问题解决能力,而Python以其简洁的语法和强大的生态成为初学者首选。理解变量、数据类型、流程控制等基础概念是构建程序的基石,而函数封装与复用则体现了代码组织的艺术。在工程实践中,虚拟环境管理依赖、使用requests等第三方库扩展功能,以及通过VSCode调试器定位逻辑错误,都是提升开发效率的关键。这些技术最终服务于数据分析、自动化办公等实际应用场景,而一个天气查询脚本的完整实现,正是Python从语法学习到项目实践的典型范例,涵盖了网络请求、JSON处理和异常处理等核心技能。

446

Python3零基础入门:从环境搭建到模块化编程的完整指南

编程语言作为人机交互的核心工具,其设计哲学与生态成熟度直接影响开发效率与学习曲线。Python以其简洁明了的语法和“用一种方法做一件事”的设计原则,降低了编程的认知门槛,同时通过强制缩进等规范培养了良好的代码组织习惯。这种平衡易用性与工程严谨性的特性,使其在数据分析、Web开发和人工智能等领域展现出极高的技术价值。对于初学者而言,理解虚拟环境的概念至关重要,它能创建独立的项目工作空间,避免依赖冲突,这是从编写脚本迈向管理真实项目的关键一步。同时,掌握列表、字典等核心数据结构以及函数的封装与复用,构成了处理复

weixin_34007906的博客 440

Python入门:从零到一,掌握核心语法与编程思维

编程语言的核心在于将逻辑转化为可执行的指令,其原理是通过语法规则和数据结构来组织代码。Python作为一门动态类型、解释型语言,以其简洁明确的语法和强大的标准库,在自动化脚本、数据分析、Web开发等领域展现出极高的技术价值。对于初学者而言,理解变量、函数、流程控制等基础概念是构建程序的第一步。本文聚焦于Python的核心语法,如缩进规则、动态类型特性,以及列表、字典等数据结构的操作,旨在帮助读者快速建立编程体感,并培养将实际问题分解为“输入-处理-输出”模型的编程思维。通过结合vscode环境配置等实践工具

lvwenwen 207
上一篇: 24. 【Java】枚举:更安全的常量
下一篇: 26. 【Java】Record:告别繁琐的 POJO
gugucoding
博客等级 码龄140天 7粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值