web-dev-qa-db-fra.com

Pourquoi est-ce que j'obtiens "Exception; doit être intercepté ou déclaré comme levé" lorsque j'essaie de compiler mon code Java?

Considérer:

import Java.awt.*;

import javax.swing.*;
import Java.awt.event.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import Java.security.*;
import Java.io.*;


public class EncryptURL extends JApplet implements ActionListener {

    Container content;
    JTextField userName = new JTextField();
    JTextField firstName = new JTextField();
    JTextField lastName = new JTextField();
    JTextField email = new JTextField();
    JTextField phone = new JTextField();
    JTextField heartbeatID = new JTextField();
    JTextField regionCode = new JTextField();
    JTextField retRegionCode = new JTextField();
    JTextField encryptedTextField = new JTextField();

    JPanel finishPanel = new JPanel();


    public void init() {

        //setTitle("Book - E Project");
        setSize(800, 600);
        content = getContentPane();
        content.setBackground(Color.yellow);
        content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));

        JButton submit = new JButton("Submit");

        content.add(new JLabel("User Name"));
        content.add(userName);

        content.add(new JLabel("First Name"));
        content.add(firstName);

        content.add(new JLabel("Last Name"));
        content.add(lastName);

        content.add(new JLabel("Email"));
        content.add(email);

        content.add(new JLabel("Phone"));
        content.add(phone);

        content.add(new JLabel("HeartBeatID"));
        content.add(heartbeatID);

        content.add(new JLabel("Region Code"));
        content.add(regionCode);

        content.add(new JLabel("RetRegionCode"));
        content.add(retRegionCode);

        content.add(submit);

        submit.addActionListener(this);
    }


    public void actionPerformed(ActionEvent e) {

        if (e.getActionCommand() == "Submit"){

            String subUserName = userName.getText();
            String subFName = firstName.getText();
            String subLName = lastName.getText();
            String subEmail = email.getText();
            String subPhone = phone.getText();
            String subHeartbeatID = heartbeatID.getText();
            String subRegionCode = regionCode.getText();
            String subRetRegionCode = retRegionCode.getText();

            String concatURL =
                "user=" + subUserName + "&f=" + subFName +
                "&l=" + subLName + "&em=" + subEmail +
                "&p=" + subPhone + "&h=" + subHeartbeatID +
                "&re=" + subRegionCode + "&ret=" + subRetRegionCode;

            concatURL = padString(concatURL, ' ', 16);
            byte[] encrypted = encrypt(concatURL);
            String encryptedString = bytesToHex(encrypted);
            content.removeAll();
            content.add(new JLabel("Concatenated User Input -->" + concatURL));

            content.add(encryptedTextField);
            setContentPane(content);
        }
    }

    public static byte[] encrypt(String toEncrypt) throws Exception{
        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(Exception e){
        }
    }


    public static byte[] decrypt(byte[] toDecrypt) throws Exception{
        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.DECRYPT_MODE, keyspec, ivspec);
        byte[] decrypted = cipher.doFinal(toDecrypt);

        return decrypted;
    }


    public static String bytesToHex(byte[] data) {
        if (data == null)
        {
            return null;
        }
        else
        {
            int len = data.length;
            String str = "";
            for (int i=0; i<len; i++)
            {
                if ((data[i]&0xFF) < 16)
                    str = str + "0" + Java.lang.Integer.toHexString(data[i]&0xFF);
                else
                    str = str + Java.lang.Integer.toHexString(data[i]&0xFF);
            }
            return str;
        }
    }


    public static String padString(String source, char paddingChar, int size)
    {
        int padLength = size-source.length() % size;
        for (int i = 0; i < padLength; i++) {
            source += paddingChar;
        }
        return source;
    }
}

Je reçois une exception non signalée:

Java.lang.Exception; must be caught or declared to be thrown
byte[] encrypted = encrypt(concatURL);

Aussi bien que:

.Java:109: missing return statement

Comment résoudre ces problèmes?

38
mmundiff

Tous vos problèmes en découlent

byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
return encrypted;

Qui sont enfermés dans un bloc try, catch, le problème est que si le programme a trouvé une exception, vous ne retournez rien. Mettez-le comme ceci (modifiez-le selon la logique de votre programme):

public static byte[] encrypt(String toEncrypt) throws Exception{
    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(Exception e){
        return null;            // Always must return something
    }
}

Pour le second, vous devez intercepter l'exception de l'appel de méthode encrypt , comme ceci (modifiez-le également en fonction de la logique de votre programme):

public void actionPerformed(ActionEvent e)
  .
  .
  .
    try {
        byte[] encrypted = encrypt(concatURL);
        String encryptedString = bytesToHex(encrypted);
        content.removeAll();
        content.add(new JLabel("Concatenated User Input -->" + concatURL));

        content.add(encryptedTextField);
    setContentPane(content);
    } catch (Exception exc) {
        // TODO: handle exception
    }
}

Les leçons que vous devez en tirer:

  • Une méthode avec un type de retour doit toujours retourner un objet de ce type, je veux dire dans tous les scénarios possibles
  • Toutes les exceptions vérifiées doivent toujours être traitées
32
victor hugo

Le problème est dans cette méthode:

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

C'est le signature de méthode qui dit à peu près:

  • quel est le nom de la méthode: encrypt
  • quel paramètre il reçoit: une chaîne nommée toEncrypt
  • son modificateur d'accès: public statique
  • et s'il peut ou non lever une exception lors de son appel.

Dans ce cas, la signature de la méthode indique que lorsqu'elle est invoquée, cette méthode "pourrait" potentiellement lever une exception de type "Exception".

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

Donc les compilateurs disent: Soit vous entourez cela avec une construction try/catch, soit vous déclarez la méthode (où est utilisée) pour se lancer "Exception" elle-même.

Le vrai problème est la définition de la méthode "encrypt". Aucune méthode ne devrait jamais retourner "Exception", car elle est trop générique et peut masquer d'autres types d'exceptions mieux vaut avoir une exception spécifique.

Essaye ça:

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.
  }

Fondamentalement, dans ce cas particulier, vous devez vous assurer que le package de cryptographie est disponible dans le système.

Java a besoin d'une extension pour le paquet de cryptographie, donc les exceptions sont déclarées comme exceptions "vérifiées". A vous de les gérer lorsqu'ils ne sont pas présents.

Dans ce petit programme, vous ne pouvez rien faire si le package de cryptographie n'est pas disponible, vous devez donc vérifier cela au moment du "développement". Si ces exceptions sont levées lorsque votre programme est en cours d'exécution, c'est parce que vous avez fait quelque chose de mal dans le "développement", donc une sous-classe RuntimeException est plus appropriée.

La dernière ligne n'a plus besoin d'une instruction de retour, dans la première version, vous interceptiez l'exception et ne faites rien avec, c'est faux.

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???

Si le code échoue, il vaut mieux échec rapide

Voici quelques réponses connexes:

6
OscarRyz

La première erreur

Java.lang.Exception; doit être intercepté ou déclaré jeté octet [] encrypted = encrypt (concatURL);

signifie que votre méthode encrypt lève une exception qui n'est pas gérée ou déclarée par la méthode actionPerformed où vous l'appelez. Lisez tout à ce sujet dans le Java Exceptions Tutorial .

Vous avez deux choix parmi lesquels choisir pour obtenir le code à compiler.

  • Vous pouvez supprimer throws Exception à partir de votre méthode encrypt et gère réellement l'exception à l'intérieur de encrypt.
  • Vous pouvez supprimer le bloc try/catch de encrypt et ajouter throws Exception et le bloc de gestion des exceptions à votre méthode actionPerformed.

Il est généralement préférable de gérer une exception au niveau le plus bas possible, au lieu de la passer à un niveau supérieur.

La deuxième erreur signifie simplement que vous devez ajouter une instruction de retour à la méthode qui contient la ligne 109 (également encrypt, dans ce cas). Il y a une déclaration de retour dans la méthode, mais si une exception est levée, elle pourrait ne pas être atteinte, vous devez donc soit retourner dans le bloc catch, soit supprimer le try/catch de encrypt, comme je l'ai mentionné précédemment .

5
Bill the Lizard

Vous devrez décider comment vous souhaitez gérer les exceptions levées par la méthode encrypt.

Actuellement, encrypt est déclaré avec throws Exception - cependant, dans le corps de la méthode, les exceptions sont interceptées dans un bloc try/catch. Je vous recommande soit:

  • retirer le throws Exception clause de encrypt et gérer les exceptions en interne (pensez au moins à écrire un message de log); ou,
  • supprimez le bloc try/catch du corps de encrypt, et entourez l'appel à encrypt avec un try/catch à la place (ie dans actionPerformed).

En ce qui concerne l'erreur de compilation à laquelle vous faites référence: si une exception a été levée dans le bloc try de encrypt, rien n'est renvoyé après la fin du bloc catch. Vous pouvez résoudre ce problème en déclarant initialement la valeur de retour comme null:

public static byte[] encrypt(String toEncrypt) throws Exception{
  byte[] encrypted = null;
  try {
    // ...
    encrypted = ...
  }
  catch(Exception e){
    // ...
  }
  return encrypted;
}

Cependant, si vous pouvez corriger le problème le plus important (la stratégie de gestion des exceptions), ce problème prendra soin de lui-même - en particulier si vous choisissez la deuxième option que j'ai suggérée.

1
harto

Dans actionPerformed(ActionEvent e) vous appelez encrypt(), qui est déclaré pour lancer Exception. Cependant, actionPerformed ne capture pas cette exception (avec try/catch autour de l'appel à encrypt()) ni ne déclare qu'elle jette Exception elle-même.

Cependant, votre méthode encrypt ne lance pas vraiment Exception. Il avale toutes les exceptions sans même consigner une plainte. (Mauvaise pratique et mauvais style!)

De plus, votre méthode encrypt effectue les opérations suivantes:

public static byte[] encrypt(String toEncrypt) throws Exception {
  try{
    ....
    return encrypted; // HERE YOU CORRECTLY RETURN A VALUE
  } catch(Exception e) {
  }
  // YOU DO NOT RETURN ANYTHING HERE
}

C'est-à-dire que si vous interceptez une exception, vous la jetez en silence puis tombez du bas de votre méthode encrypt sans réellement retourner quoi que ce soit. Cela ne se compilera pas (comme vous le voyez), car une méthode déclarée pour renvoyer une valeur doit soit renvoyer une valeur, soit lever une exception pour chaque chemin de code possible.

0
Eddie

Dans votre méthode `` encrypt '', vous devez soit vous débarrasser du try/catch et ajouter à la place un try/catch à l'endroit où vous appelez encrypt (à l'intérieur de 'actionPerformed') ou renvoyer null à l'intérieur du catch dans encrypt (c'est la deuxième erreur.

0
AgileJon