如何在 Try/Catch 块内抛出异常?

Car*_*ine 1 java spring-boot

我有以下 Java 方法:

public Class createClass(Class class) {
    try {
        // retrieve the professor of the class and check if he exists
        Professor professorFound = professorRepository.findById(class.getProfessorId());
        if (professorFound != null) {
           // if the professor exists, then check if he already has a class
           // with the same id
           List<Class> classes = professorFound.getClasses();
           List<Class> classFound = classes.stream().... // loop to find the class... 

           // if he has, throw an exception
           if(!classFound.isEmpty()) {
                throw new ClassAlreadyRegisteredException();

           } else {
                // if he does not have, then create the class
                Class class = new Class();
                professorFound.getClasses().add(class);
                return professorRepository.save(professorFound);
           }
        } else {
           // if the professor does not exist, throw an exception
           throw new ProfessorNotFoundException();
    } catch (Exception e) {
        // if there is any other error during the communication with the database, 
        // throw a generic IOException
        throw new ClassIOException();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我需要的是抛出特定的异常(如果在请求中通知的教授不存在,或者教授已经有一个具有相同 id 的类),或者IOException如果在与数据库。

但是,按照我开发的方式,如果Exception抛出任何特定内容,try 块将捕获异常并抛出通用 IOException。

我怎么解决这个问题?

我很想了解在这种情况下什么是最佳实践。 我应该分别捕获每个特定的异常并抛出它们两次吗? 这是一个好习惯吗?

编辑:

这是我的ClassAlreadyRegisteredException样子:

public class ClassAlreadyRegisteredException extends ApiException {

    private static final long serialVersionUID = 1L;

    public ClassAlreadyRegisteredException(String code, String message, String developerMessage, String origin, HttpStatus status) {
        super(code,message,developerMessage,origin, status);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的ApiException样子:

@Data
@AllArgsConstructor
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ApiException extends RuntimeException{
    
    private static final long serialVersionUID = 1L;
    
    private String code;
    private String userMessage;
    private String developerMessage;
    private String origin;
    private HttpStatus status;
}
Run Code Online (Sandbox Code Playgroud)

提前致谢。

J.B*_*kus 5

接住并重新投掷。

try {
   ... same as before ...
} catch (ClassAlreadyRegisteredException | ProfessorNotFoundException e) {
    throw e;
} catch (Exception e) {
    // if there is any other error during the communication with the database, 
    // throw a generic IOException
    throw new ClassIOException();
}
Run Code Online (Sandbox Code Playgroud)

或者,请记住稍后抛出的异常。

 Exception fail = null;

 try {
      ….
     // save exception in place of existing throws
     // for example:
     fail = new ClassAlreadyRegisteredException();
     …
 } catch (Exception ex) {
     ...same as original...
 }

 if (fail != null) {
     throw fail;
 }
Run Code Online (Sandbox Code Playgroud)

我使用这两种技术;选择取决于在任何给定情况下哪个更简单。两者都无可争议地更好。

对于 catch 和 re-throw 方法,您必须使捕获并重新抛出的异常列表与您在 try 子句中实际抛出的异常保持一致。在更大的情况下,我会通过使用异常层次结构来避免这个问题,这样我就可以捕获公共基类。

对于 save-and-throw 方法,您必须安排控制流,以便在检测到失败后不会做任何重要的事情,因为您没有立即的“throw”命令来退出 try 子句。尽管如此,在某些情况下它还是很简单的;最初的例子就是这样。