错误:未报告的异常错误,必须对其进行捕获或声明以便抛出

本文详细介绍了Java中的异常处理机制,包括异常的抛出与捕获流程,并提供了两种常见异常处理方式的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误:未报告的异常错误,必须对其进行捕获或声明以便抛出


出现错误:是因为没有对异常进行捕获或声明

javaNosuchElementException 

首先说一下Java 中throws的作用:

假如函数部分有不合法的异常,例如分母为0:

import java.util.Scanner;
public class Helloexcept{
    public static void main(String[] args)throws Exception{
        int c=1/0;
        System.out.println(c);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

编译之后,将会抛出异常:

这里写图片描述

在Java中,根据错误性质将运行错误分为两类:错误和异常。

在Java程序的执行过程中,如果出现了异常事件,就会生成一个异常对象。生成的异常对象将传递Java运行时系统,这一异常的产生和提交过程称为抛弃(throw)异常。当Java运行时系统得到一个异常对象时,它将会沿着方法的调用栈逐层回溯,寻找处理这一异常的代码。找到能够处理这类异常的方法后,运行时系统把当前异常对象交给这个方法进行处理,这一过程称为捕获(catch)异常。

解决:

方法一:

即在main函数的后面加入throws Exception的异常捕获

import java.util.Scanner;
public class ReadData{
    public static void main(String[] args)throws Exception{
        java.io.File file =new java.io.File("xixi.txt");
        Scanner input=new Scanner(file);
        while(input.hasNext()){
            String firstname=input.next();
            String mi=input.next();
            String lastname=input.nextt();
            int score=input.nextInt();
            System.out.println(firstname+" "+mi+" "+lastname+" "+score);
        }
        input.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

方法二:

利用try,catch

import java.util.Scanner;
public class Wrong2343{
    public static void main(String[] args){
        int c;
        try{
            c=1/0;
        }
        catch(Exception e){
            System.out.println("Wrong!");
        }
        System.out.println("Haha!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

需要注意,如果写Java的类名(文件名)带有Exception时,会出现这样的问题:

这里写图片描述

所以要注意类名不产生歧义


<think>我们遇到了编译错误报告异常错误java.security.NoSuchProviderException;必须对其进行捕获声明以便抛出这是因为在调用`MessageDigest.getInstance("SM3","BC")`时,该方法声明了`NoSuchProviderException`,这是一个受检异常,必须在方法上声明捕获。解决方案:1.在调用该方法的函数(`sm3Hash`)上声明抛出`NoSuchProviderException`,然后一直向上声明,直到被捕获。2.在`sm3Hash`方法内部捕获`NoSuchProviderException`,并处理(如转换为运行时异常进行重试)。考虑到我们之前已经注册了提供者,并且希望代码健壮,我们选择在`sm3Hash`方法中捕获并尝试重新注册,如果仍然失败,则抛出运行时异常。但是,为了满足编译器的要求,我们必须处理这个受检异常。我们可以有两种做法:a)在方法签名中声明`throws NoSuchProviderException`,并让调用者处理。b)在方法内部捕获并处理(比如重试后仍然失败,则抛出非受检异常)。我们之前已经设计了一个重试机制,因此我们可以在重试后仍然失败时抛出`RuntimeException`。修改后的`sm3Hash`方法: ```javaprivate staticbyte[]sm3Hash(byte[]data){try {//尝试获取SM3实例return MessageDigest.getInstance("SM3", "BC").digest(data);}catch (NoSuchProviderExceptione){System.err.println("Bouncy Castle提供者注册,尝试重新注册...");//重新注册提供者registerBouncyCastleProvider();try {returnMessageDigest.getInstance("SM3","BC").digest(data);} catch(NoSuchAlgorithmException |NoSuchProviderExceptionex){throw newRuntimeException("重新注册后仍无法获取SM3算法提供者",ex);}}catch (NoSuchAlgorithmExceptione){throw newRuntimeException("不支持SM3算法",e);}} ```这样,`sm3Hash`方法不再声明抛出受检异常,而是将任何异常转换为运行时异常。然后,我们需要修改`generateSignature`方法,去掉对`NoSuchProviderException`的声明,并捕获可能出现的运行时异常。但是,注意:`generateSignature`方法原本声明抛出了`NoSuchAlgorithmException`和`NoSuchProviderException`,现在我们可以去掉这些,改为在内部处理。因此,我们修改`generateSignature`方法: ```javapublic staticString generateSignature(StringopenCode, StringopenSecret, longtimestamp)throwsUnsupportedEncodingException{// ...其他代码不变byte[] hashBytes =sm3Hash(rawString.getBytes(StandardCharsets.UTF_8));//... }```同时,在`main`方法中,我们捕获异常时也要注意捕获`RuntimeException`。完整代码修改如下:```javaimportjava.io.UnsupportedEncodingException; importjava.net.URLEncoder;import java.nio.charset.StandardCharsets;import java.security.MessageDigest; importjava.security.NoSuchAlgorithmException; importjava.security.NoSuchProviderException; importjava.security.Provider; importjava.security.Security;import java.util.Formatter;import org.bouncycastle.jce.provider.BouncyCastleProvider; publicclass SM3SignatureGenerator {static{registerBouncyCastleProvider();}privatestatic voidregisterBouncyCastleProvider(){try {if(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)== null) {Security.addProvider(new BouncyCastleProvider());}}catch (SecurityExceptione){System.err.println("安全异常:无法注册Bouncy Castle提供者");e.printStackTrace();}}public staticString generateSignature(StringopenCode, StringopenSecret, longtimestamp)throwsUnsupportedEncodingException{StringencodedOpenCode =URLEncoder.encode(openCode, StandardCharsets.UTF_8.name());StringencodedOpenSecret =URLEncoder.encode(openSecret, StandardCharsets.UTF_8.name());StringencodedTimestamp= URLEncoder.encode(String.valueOf(timestamp), StandardCharsets.UTF_8.name());String rawString =String.format("open_code=%s&open_secret=%s&timestamp=%s",encodedOpenCode,encodedOpenSecret,encodedTimestamp);byte[] hashBytes =sm3Hash(rawString.getBytes(StandardCharsets.UTF_8));return bytesToHex(hashBytes);}privatestatic byte[] sm3Hash(byte[] data) {try{return MessageDigest.getInstance("SM3", "BC").digest(data);}catch (NoSuchProviderExceptione){System.err.println("Bouncy Castle提供者注册,尝试重新注册...");registerBouncyCastleProvider();try {returnMessageDigest.getInstance("SM3","BC").digest(data);} catch(NoSuchAlgorithmException |NoSuchProviderExceptionex){throw newRuntimeException("重新注册后仍无法获取SM3算法提供者",ex);}}catch (NoSuchAlgorithmExceptione){throw newRuntimeException("不支持SM3算法", e);}}private staticString bytesToHex(byte[] bytes) {StringBuilderhexString= newStringBuilder(bytes.length *2);try (Formatter formatter =new Formatter(hexString)) {for(byteb :bytes){formatter.format("%02x", b);}}return hexString.toString();}public staticvoid main(String[]args){try {StringopenCode= "app_12345";String openSecret ="sec@ret!key";long timestamp= System.currentTimeMillis()/1000;Stringsignature =generateSignature(openCode,openSecret, timestamp);System.out.println("输入参数:");System.out.println("open_code: "+ openCode);System.out.println("open_secret:" +openSecret);System.out.println("timestamp: "+ timestamp);System.out.println("\n签名结果:" +signature);System.out.println("\n签名长度: "+ signature.length()+ "字符");} catch(UnsupportedEncodingException e) {System.err.println("编码异常: "+ e.getMessage());e.printStackTrace();}catch (RuntimeExceptione){System.err.println("计算签名时发生运行时异常:" +e.getMessage());e.printStackTrace();}} }``` ###修改点说明:1.**`sm3Hash`方法**:-捕获`NoSuchProviderException`和`NoSuchAlgorithmException`。-当遇到`NoSuchProviderException`时,尝试重新注册提供者并重试。-重试失败后,抛出`RuntimeException`,包含原始异常信息。2.**`generateSignature`方法**:-移除了`throws NoSuchAlgorithmException,NoSuchProviderException`声明。-现在只抛出`UnsupportedEncodingException`(URL编码可能抛出)。3.**异常处理链**:-将受检异常转换为非受检异常,简化调用者代码。-在`main`方法中捕获`RuntimeException`并打印错误信息。 ###依赖不变: 仍然需要BouncyCastle依赖: ```xml<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.71</version> </dependency>``` ###测试验证:1. **正常情况**:提供者已注册,生成签名成功。 2. **异常情况**:移除Bouncy Castle依赖,运行时会抛出异常,提示重新注册后仍无法获取提供者。 ###其他注意事项:-如果重试后仍然失败,可能是由于依赖缺失安全策略限制,程序将终止并打印异常栈。 -在严格的企业环境中,可能需要配置安全策略文件(`java.policy`)来允许动态注册提供者。 §§相关问题§§: 1.在Java中如何处理其他类型的受检异常(CheckedException)? 2.如何为Java应用程序配置自定义安全策略文件? 3.在Java9及以上版本中,模块化系统如何影响安全提供者的注册?4.如何编写单元测试来验证SM3签名生成方法在各种异常情况下的行为?</think>您遇到了编译错误:"报告异常错误java.security.NoSuchProviderException; 必须对其进行捕获声明以便抛出"。这是因为Java要求处理所有受检异常(checked exceptions)。以下是完整的解决方案,包含异常处理的多种方法: ### 解决方案1:声明抛出异常(推荐) ```java import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Formatter; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class SM3SignatureGenerator { static { registerBouncyCastleProvider(); } private static void registerBouncyCastleProvider() { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } /** * 生成SM3签名(声明抛出所有可能异常) */ public static String generateSignature(String openCode, String openSecret, long timestamp) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchProviderException { String encodedOpenCode = URLEncoder.encode(openCode, StandardCharsets.UTF_8.name()); String encodedOpenSecret = URLEncoder.encode(openSecret, StandardCharsets.UTF_8.name()); String encodedTimestamp = URLEncoder.encode(String.valueOf(timestamp), StandardCharsets.UTF_8.name()); String rawString = String.format("open_code=%s&open_secret=%s&timestamp=%s", encodedOpenCode, encodedOpenSecret, encodedTimestamp); byte[] hashBytes = sm3Hash(rawString.getBytes(StandardCharsets.UTF_8)); return bytesToHex(hashBytes); } /** * 计算SM3哈希(声明抛出异常) */ private static byte[] sm3Hash(byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException { return MessageDigest.getInstance("SM3", "BC").digest(data); } // bytesToHex方法保持不变 } ``` ### 解决方案2:捕获并处理异常 ```java import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Formatter; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class SM3SignatureGenerator { static { registerBouncyCastleProvider(); } private static void registerBouncyCastleProvider() { try { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } catch (SecurityException e) { System.err.println("安全策略限制: " + e.getMessage()); } } /** * 生成SM3签名(捕获并处理所有异常) */ public static String generateSignature(String openCode, String openSecret, long timestamp) { try { String encodedOpenCode = URLEncoder.encode(openCode, StandardCharsets.UTF_8.name()); String encodedOpenSecret = URLEncoder.encode(openSecret, StandardCharsets.UTF_8.name()); String encodedTimestamp = URLEncoder.encode(String.valueOf(timestamp), StandardCharsets.UTF_8.name()); String rawString = String.format("open_code=%s&open_secret=%s&timestamp=%s", encodedOpenCode, encodedOpenSecret, encodedTimestamp); byte[] hashBytes = sm3Hash(rawString.getBytes(StandardCharsets.UTF_8)); return bytesToHex(hashBytes); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8编码不支持", e); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new RuntimeException("SM3算法提供者不可用", e); } } /** * 计算SM3哈希(捕获并处理异常) */ private static byte[] sm3Hash(byte[] data) { try { return MessageDigest.getInstance("SM3", "BC").digest(data); } catch (NoSuchProviderException e) { // 提供者注册,尝试修复 registerBouncyCastleProvider(); try { return MessageDigest.getInstance("SM3", "BC").digest(data); } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { throw new RuntimeException("无法获取SM3实例", ex); } } catch (NoSuchAlgorithmException e) { throw new RuntimeException("SM3算法不可用", e); } } // bytesToHex方法保持不变 } ``` ### 解决方案3:使用异常包装器(简洁版) ```java import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Formatter; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class SM3SignatureGenerator { static { Security.addProvider(new BouncyCastleProvider()); } /** * 生成SM3签名(简洁版,使用异常包装) */ public static String generateSignature(String openCode, String openSecret, long timestamp) { try { return generateSignatureInternal(openCode, openSecret, timestamp); } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchProviderException e) { throw new RuntimeException("签名生成失败", e); } } /** * 内部实现(声明抛出异常) */ private static String generateSignatureInternal(String openCode, String openSecret, long timestamp) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchProviderException { String encodedOpenCode = URLEncoder.encode(openCode, StandardCharsets.UTF_8.name()); String encodedOpenSecret = URLEncoder.encode(openSecret, StandardCharsets.UTF_8.name()); String encodedTimestamp = URLEncoder.encode(String.valueOf(timestamp), StandardCharsets.UTF_8.name()); String rawString = String.format("open_code=%s&open_secret=%s&timestamp=%s", encodedOpenCode, encodedOpenSecret, encodedTimestamp); MessageDigest md = MessageDigest.getInstance("SM3", "BC"); byte[] hashBytes = md.digest(rawString.getBytes(StandardCharsets.UTF_8)); return bytesToHex(hashBytes); } // bytesToHex方法保持不变 } ``` ### 异常处理最佳实践解释 1. **声明抛出异常 (throws)** - 适用于库函数API - 让调用者决定如何处理异常 - 示例: ```java public static String generateSignature(...) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchProviderException { // ... } ``` 2. **捕获并处理异常 (try-catch)** - 适用于最终用户接口UI层 - 提供有意义的错误信息 - 示例: ```java try { String signature = generateSignature(...); } catch (NoSuchProviderException e) { System.err.println("Bouncy Castle安装: " + e.getMessage()); // 提示用户安装依赖 } ``` 3. **包装为运行时异常** - 适用于不希望中断程序流程的场景 - 避免修改方法签名 - 示例: ```java try { MessageDigest.getInstance("SM3", "BC"); } catch (NoSuchProviderException e) { throw new RuntimeException("安全提供者不可用", e); } ``` ### 完整解决方案(推荐) ```java import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Formatter; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class SM3SignatureGenerator { static { // 确保只注册一次 if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } /** * 生成SM3签名(主入口) */ public static String generateSignature(String openCode, String openSecret, long timestamp) { try { return generateSignatureInternal(openCode, openSecret, timestamp); } catch (Exception e) { throw new SignatureGenerationException("SM3签名生成失败", e); } } /** * 内部实现(处理所有受检异常) */ private static String generateSignatureInternal(String openCode, String openSecret, long timestamp) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchProviderException { // 参数编码 String encodedOpenCode = URLEncoder.encode(openCode, StandardCharsets.UTF_8.name()); String encodedOpenSecret = URLEncoder.encode(openSecret, StandardCharsets.UTF_8.name()); String encodedTimestamp = URLEncoder.encode(String.valueOf(timestamp), StandardCharsets.UTF_8.name()); // 拼接字符串 String rawString = String.format("open_code=%s&open_secret=%s&timestamp=%s", encodedOpenCode, encodedOpenSecret, encodedTimestamp); // 获取SM3实例 MessageDigest md = MessageDigest.getInstance("SM3", "BC"); // 计算哈希 byte[] hashBytes = md.digest(rawString.getBytes(StandardCharsets.UTF_8)); // 转换为十六进制 return bytesToHex(hashBytes); } /** * 字节数组转十六进制字符串 */ private static String bytesToHex(byte[] bytes) { StringBuilder hexString = new StringBuilder(64); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) hexString.append('0'); hexString.append(hex); } return hexString.toString(); } /** * 自定义异常类 */ public static class SignatureGenerationException extends RuntimeException { public SignatureGenerationException(String message, Throwable cause) { super(message, cause); } } public static void main(String[] args) { try { String signature = generateSignature("app123", "secret@key", System.currentTimeMillis() / 1000); System.out.println("签名: " + signature); } catch (SignatureGenerationException e) { System.err.println("错误: " + e.getMessage()); e.printStackTrace(); // 提供解决方案 if (e.getCause() instanceof NoSuchProviderException) { System.err.println("\n解决方案:"); System.err.println("1. 添加Bouncy Castle依赖: bcprov-jdk15to18"); System.err.println("2. 检查类路径配置"); } } } } ``` ### 关键点解释 1. **异常处理策略**: - 使用自定义的`SignatureGenerationException`包装所有底层异常 - 在`main`方法中提供用户友好的错误信息和解决方案 2. **提供者注册**: ```java static { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } } ``` - 静态初始化块确保只注册一次 - 检查是否已注册避免重复添加 3. **方法设计**: - `generateSignature()`: 公共API,捕获所有异常抛出运行时异常 - `generateSignatureInternal()`: 内部实现,声明所有可能的受检异常 4. **错误恢复**: ```java // 在main方法中 if (e.getCause() instanceof NoSuchProviderException) { System.err.println("\n解决方案:"); System.err.println("1. 添加Bouncy Castle依赖: bcprov-jdk15to18"); } ``` - 根据异常类型提供具体解决方案 - 帮助用户快速解决问题 ### 依赖配置(Maven) ```xml <dependencies> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> <version>1.77</version> </dependency> </dependencies> ``` ### 使用示例 ```java public class MyApp { public static void main(String[] args) { try { String signature = SM3SignatureGenerator.generateSignature( "my_app_id", "my_secret_key", 1689321600L ); System.out.println("生成签名: " + signature); } catch (SM3SignatureGenerator.SignatureGenerationException e) { // 处理异常 } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值