Java Basics Part 19/20 - Exceptions

Java异常处理详解
本文深入讲解Java中的异常处理机制,包括异常的分类、捕获、处理及自定义异常等内容,并通过实例演示如何有效利用异常处理确保程序的健壮性和稳定性。

Java Basics Part 19/20 - Exceptions

目录


异常(Exception) 是运行期出现错误带来的问题。当程序发生异常的时候,会不正常终止,而这不是程序员想看到,所以就引入了 异常机制,来处理运行期抛出的异常。

异常可以由很多因素导致,下面是一些常见的异常场景:

  • 用户输入非法数据
  • 需要打开的文件不存在
  • 在通信过程中网络断开或者是 JVM 内存溢出了

一些异常由用户错误导致,还有一些有程序员导致,还有一些是物理资源导致。

基于上述原因种类不同,我们可以给异常分类:

  • Checked exceptions:checked exception 是在编译期间出现的异常,这些异常也叫作编译期异常。它们在编译期不能忽略,程序员应该把这些异常处理掉。
    比如,如果使用 FileReader 类读取一个文件,如果文件不存在,那么就会抛出 FileNotFoundException,编译期会提示程序员解决。

    import java.io.File;
    import java.io.FileReader;
    
    public class FilenotFound_Demo {
    
       public static void main(String args[]){      
          File file=new File("E://file.txt");
          FileReader fr = new FileReader(file); 
       }
    
    }
    
    // output
    FilenotFound_Demo.java:8: error: unreported exception     FileNotFoundException; must be caught or declared to be thrown
      FileReader fr = new FileReader(file);
  • Unchecked exceptions:Unchecked exceptions 是运行期会发生的异常,又叫做运行期异常,这些异常包括程序 bug,比如逻辑错误,API 的错误使用等等这些在编译器会忽略的异常。

    public class Unchecked_Demo {   
        public static void main(String args[]){
            int num[]={1,2,3,4};
            System.out.println(num[5]);
         }
    }
    // output
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
    at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
  • Errors: 这些不是异常,而是一些程序员无法控制的问题。比如,栈溢出。


Exception Hierarchy

所有的 Exception 都是 java.lang.Exception 的子类。Exception 同时也是 Throwable 的子类。除了 Exception 之外,还有 Error 类也是 Throwable 的子类。

Exception 类有两个子类:IOException 和 RuntimeException。

Exception

这里有常见的 java 内置 Exception.


Exceptions Methods

下面列出了 Throwable 类的一些很重要的方法。

SNMethods with Description
1public String getMessage():异常发生时返回的错误信息,这个信息在异常类构造器中初始化的。
2public Throwable getCause():返回异常的原因
3public String toString():返回类名+getMessage()
4public void printStackTrace():打印 toString() 的结果,输出到 System.err
5public StackTraceElement [] getStackTrace():返回调用栈元素的集合
6public Throwable fillInStackTrace()

Catching Exceptions

可以使用 trycatch 来捕获异常。语法如下:

try {
   //Protected code
}catch(ExceptionName e1) {
   //Catch block
}

举例:

// File Name : ExcepTest.java
import java.io.*;
public class ExcepTest{

   public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

// output
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block

Multiple catch Blocks

一个 try,后面可以接多个 catch:

try {
   //Protected code
}catch(ExceptionType1 e1) {
   //Catch block
}catch(ExceptionType2 e2) {
   //Catch block
}catch(ExceptionType3 e3) {
   //Catch block
}

举例:

try
{
   file = new FileInputStream(fileName);
   x = (byte) file.read();
}catch(IOException i)
{
   i.printStackTrace();
   return -1;
}catch(FileNotFoundException f) //Not valid!
{
   f.printStackTrace();
   return -1;
}

Catching multiple type of exceptions

从 Java 7 开始,一个 catch 语句块可以捕获多个异常。比如:

catch (IOException|FileNotFoundException ex) {
   logger.log(ex);
   throw ex;

The throws/throw Keywords

如果方法本身不会处理一个 checked exception,那么方法必须使用 throws 抛出这个异常。throws 关键字总是出现在方法签名的末尾。

方法中也可以使用 throw 关键字抛出一个异常。

throwsthrow 的区别:
throws 用来推迟 checked exception 的处理,throw 用来显示的触发一个异常。

下面这个例子,抛出了一个 RemoteException:

import java.io.*;
public class className
{
   public void deposit(double amount) throws RemoteException
   {
      // Method implementation
      throw new RemoteException();
   }
   //Remainder of class definition
}

方法也可以一次抛出多个异常。

import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

The finally block

finally 块紧跟在 try…catch 后面。finally 块中的语句总是会执行,即使有异常发生。

通常使用 finally 语句块来做一些资源清理的工作。

语法如下:

try
{
   //Protected code
}catch(ExceptionType1 e1)
{
   //Catch block
}catch(ExceptionType2 e2)
{
   //Catch block
}catch(ExceptionType3 e3)
{
   //Catch block
}finally
{
   //The finally block always executes.
}

举例:

public class ExcepTest{

   public static void main(String args[]){
      int a[] = new int[2];
      try{
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      finally{
         a[0] = 6;
         System.out.println("First element value: " +a[0]);
         System.out.println("The finally statement is executed");
      }
   }
}

// output
Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

注意:

  • 无 try 不 catch
  • finally 不必在
  • 无 catch 或 finally 不 try
  • try catch finally 之间无代码

The try-with-resources

通常我们会使用一些资源(流,连接等等),使用完成后要关掉这些资源,如下所示,使用 FileReader,然后关闭它:

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

代码比较多,使用 try-with-resources 句法后(Java 7 引进),try 中打开的资源会自动释放。
语法:

try(FileReader fr=new FileReader("file path")) {
   //use the resource
}catch(){
      //body of catch 
    }
}

举例:

import java.io.FileReader;
import java.io.IOException;

public class Try_withDemo {

   public static void main(String args[]){

      try(FileReader fr=new FileReader("E://file.txt")){
         char [] a = new char[50];
         fr.read(a); // reads the contentto the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }   
   }
}

下面这些要点要谨记:

  • 使用 try-with-resources 打开的类,必须实现 AutoCloseable接口,运行期会自动调用close()
  • 在 try-with-resources 中可用声明多个类
  • try 中声明的多个类会以相反的顺序关闭
  • 除了资源的声明之外,其他与 try/catch 无异
  • try 中声明的资源在 try 开始之前被初始化。
  • try 中声明的资源隐式的被修饰为 final 的

User-Define Exceptions

用户可以创建自己的异常类。自定义的时候注意以下几点:

  • 所有的异常都是 Throwable 的子类
  • 如果想写一个 checked exception,需要继承 Exception
  • 如果想写一个 runtime exception,需要继承 RuntimeException

举例:

// File Name InsufficientFundsException.java
import java.io.*;

public class InsufficientFundsException extends Exception
{
   private double amount;
   public InsufficientFundsException(double amount)
   {
      this.amount = amount;
   } 
   public double getAmount()
   {
      return amount;
   }
}

使用上述定义的异常:

// File Name CheckingAccount.java
import java.io.*;

public class CheckingAccount
{
   private double balance;
   private int number;

   public CheckingAccount(int number)
   {
      this.number = number;
   }

   public void deposit(double amount)
   {
      balance += amount;
   }

   public void withdraw(double amount) throws InsufficientFundsException
   {
      if(amount <= balance)
      {
         balance -= amount;
      }
      else
      {
         double needs = amount - balance;
         throw new InsufficientFundsException(needs);
      }
   }

   public double getBalance()
   {
      return balance;
   }

   public int getNumber()
   {
      return number;
   }
}

使用上述定义的类:

// File Name BankDemo.java
public class BankDemo
{
   public static void main(String [] args)
   {
      CheckingAccount c = new CheckingAccount(101);
      System.out.println("Depositing $500...");
      c.deposit(500.00);

      try
      {
         System.out.println("\nWithdrawing $100...");
         c.withdraw(100.00);
         System.out.println("\nWithdrawing $600...");
         c.withdraw(600.00);
      }catch(InsufficientFundsException e)
      {
         System.out.println("Sorry, but you are short $" + e.getAmount());
         e.printStackTrace();
      }
    }
}

// output
Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
        at CheckingAccount.withdraw(CheckingAccount.java:25)
        at BankDemo.main(BankDemo.java:13)

Common Exceptions

Java 中,可以定义两种 Exceptions 和 Errors:

  • JVM Exceptions: 由 JVM 抛出的异常,例如:NullPointerException,ArrayIndexOutOfBoundsException,ClassCastException
  • Programmatic exceptions: 应用或者是API设计者抛出的异常,例如:IllegalArgumentException,IllegalStateException
<think>好的,我现在需要帮助用户解决BasicsR库中train_pipeline函数调用时的Traceback错误。首先,我得仔细分析用户提供的错误信息和引用内容,看看有没有相关的线索。 用户提到的错误信息是之前运行pybullet时遇到的numpy版本不兼容的问题,引用[1]中的错误显示numpy的API版本不匹配。这可能意味着当前环境中安装的numpy版本与BasicsR或其依赖库所需的版本不一致。虽然用户现在的问题是关于BasicsR的,但版本冲突的可能性仍然存在,特别是因为很多深度学习库对依赖项版本有严格要求。 接下来,引用[2]和引用[3]提到了train_test_split的使用和MindSpore的安装验证,这可能与用户当前的问题关联不大,但说明用户可能在处理数据或使用特定框架时遇到问题。不过,用户现在的焦点是BasicsR库中的train_pipeline函数报错,所以需要集中在这个库及其依赖上。 首先,我需要考虑常见的错误原因。通常,Traceback错误可能由以下几个原因导致: 1. 版本不兼容:比如numpy、PyTorch或其他依赖库的版本不符合BasicsR的要求。 2. 环境配置问题:CUDA版本与PyTorch不匹配,或者缺少必要的系统库。 3. 代码错误:用户可能在调用train_pipeline时参数配置不正确,或者文件路径有误。 4. 依赖缺失:BasicsR可能依赖某些特定的库没有安装。 根据用户之前遇到的numpy问题,首先应该检查当前环境中的库版本是否符合BasicsR的要求。BasicsR通常基于PyTorch,因此需要确认PyTorch和CUDA的版本是否兼容。此外,BasicsR可能有自己的安装要求,可能需要从源码安装或安装特定版本的依赖。 接下来,建议用户检查错误日志的具体内容,因为Traceback会指出错误发生的具体位置。例如,如果是ImportError,可能是某个模块缺失;如果是RuntimeError,可能是CUDA相关的问题。 另外,用户可能没有正确安装BasicsR或其依赖项。比如,BasicsR可能需要安装mmcv、mmdet等库,这些库的版本需要与PyTorch版本对应。如果用户通过pip安装,可能需要指定版本号或从源码编译。 此外,环境变量设置错误也可能导致问题,比如CUDA_HOME未正确设置,或者GPU驱动不兼容。用户需要确认CUDA版本与PyTorch版本匹配,例如PyTorch 1.10需要CUDA 11.3,而PyTorch 2.0可能需要CUDA 12.x。 如果用户的环境是conda管理的,建议创建一个干净的新环境,按照BasicsR的官方文档逐步安装依赖,确保所有库的版本一致。有时候,依赖冲突会导致难以预料的问题,新建环境可以避免这种情况。 最后,建议用户提供具体的Traceback信息,以便更准确地定位问题。比如,错误是否发生在导入阶段,还是在训练过程中,具体的错误信息是什么,这些都能帮助进一步诊断问题。</think>针对BasicsR库中$train\_pipeline$函数调用出现的Traceback错误,以下是分步解决方案: ### 1. 检查版本兼容性 - **PyTorch与CUDA匹配**:BasicsR依赖PyTorch,需确保: $$ \text{PyTorch版本} \propto \text{CUDA版本} $$ 例如PyTorch 1.10对应CUDA 11.3,PyTorch 2.0对应CUDA 12.1。使用`conda list`或`pip show torch`验证版本 - **numpy版本冲突**:类似引用[1]的numpy API不兼容错误,建议使用: ```bash pip install numpy==1.23.5 # 常见稳定版本 ``` ### 2. 验证依赖安装 BasicsR需要完整安装以下组件: ```bash # 必需依赖 pip install mmcv-full==1.7.0 -f https://download.openmmlab.com/mmcv/dist/{cu_version}/{torch_version}/index.html # 示例:CUDA11.3+PyTorch1.10 pip install mmcv-full==1.7.0 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html ``` ### 3. 检查配置文件 $train\_pipeline$的常见错误配置场景: ```yaml # 错误示例:通道数不匹配 train_pipeline: - type: 'LoadImageFromFile' key: 'lq' # 必须与数据标注匹配 - type: 'Flip' keys: ['lq', 'gt'] # 多任务需统一键值 ``` ### 4. 环境隔离方案 使用conda创建纯净环境: ```bash conda create -n basicsr python=3.8 -y conda activate basicsr git clone https://github.com/xinntao/BasicSR.git cd BasicSR pip install -r requirements.txt python setup.py develop ``` ### 5. 典型错误处理 | 错误类型 | 解决方案 | |---------|----------| | `ImportError: cannot import name 'container_abcs'` | 降级torchvision到0.9.0 | | `RuntimeError: CUDA out of memory` | 减小batch_size或使用`--auto-resume` | | `KeyError: 'xxx is not in the models registry'` | 检查配置文件中的模型名称拼写 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值