Why do I get “Exception; must be caught or declared to be thrown” when I try to compile my Java code?

后端 未结 6 724
粉色の甜心
粉色の甜心 2020-11-22 08:46

Consider:

import java.awt.*;

import javax.swing.*;
import java.awt.event.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
impor         


        
6条回答
  •  执念已碎
    2020-11-22 09:26

    The problem is in this method:

      public static byte[] encrypt(String toEncrypt) throws Exception{
    

    This is the method signature which pretty much says:

    • what the method name is: encrypt
    • what parameter it receives: a String named toEncrypt
    • its access modifier: public static
    • and if it may or not throw an exception when invoked.

    In this case the method signature says that when invoked this method "could" potentially throw an exception of type "Exception".

        ....
        concatURL = padString(concatURL, ' ', 16);
        byte[] encrypted = encrypt(concatURL); <-- HERE!!!!!
        String encryptedString = bytesToHex(encrypted);
        content.removeAll();
        ......
    

    So the compilers is saying: Either you surround that with a try/catch construct or you declare the method ( where is being used ) to throw "Exception" it self.

    The real problem is the "encrypt" method definition. No method should ever return "Exception", because it is too generic and may hide some other kinds of exception better is to have an specific exception.

    Try this:

    public static byte[] encrypt(String toEncrypt) {
        try{
          String plaintext = toEncrypt;
          String key = "01234567890abcde";
          String iv = "fedcba9876543210";
    
          SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
          IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
    
          Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
          cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);
          byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
    
          return encrypted;
        } catch ( NoSuchAlgorithmException nsae ) { 
            // What can you do if the algorithm doesn't exists??
            // this usually won't happen because you would test 
            // your code before shipping. 
            // So in this case is ok to transform to another kind 
            throw new IllegalStateException( nsae );
        } catch ( NoSuchPaddingException nspe ) { 
           // What can you do when there is no such padding ( whatever that means ) ??
           // I guess not much, in either case you won't be able to encrypt the given string
            throw new IllegalStateException( nsae );
        }
        // line 109 won't say it needs a return anymore.
      }
    

    Basically in this particular case you should make sure the cryptography package is available in the system.

    Java needs an extension for the cryptography package, so, the exceptions are declared as "checked" exceptions. For you to handle when they are not present.

    In this small program you cannot do anything if the cryptography package is not available, so you check that at "development" time. If those exceptions are thrown when your program is running is because you did something wrong in "development" thus a RuntimeException subclass is more appropriate.

    The last line don't need a return statement anymore, in the first version you were catching the exception and doing nothing with it, that's wrong.

    try { 
        // risky code ... 
    } catch( Exception e ) { 
        // a bomb has just exploited
        // you should NOT ignore it 
    } 
    
    // The code continues here, but what should it do???
    

    If the code is to fail, it is better to Fail fast

    Here are some related answers:

    • Catching Exceptions in Java

    • When to choose checked and unchecked exceptions

    • Why don’t you have to explicitly declare that you might throw some built in exceptions in Java?

    • Exception other than RuntimeException

提交回复
热议问题