Вопрос-ответ

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

Почему я получаю "Исключение; должно быть перехвачено или объявлено выброшенным" при попытке скомпилировать свой Java-код?

Рассмотрим:

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

Я получаю незарегистрированное исключение:

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

А также:

.java:109: missing return statement

Как мне решить эти проблемы?

Переведено автоматически
Ответ 1

Все ваши проблемы проистекают из этого

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

Которые заключены в блок try, catch, проблема в том, что в случае, если программа обнаружила исключение, вы ничего не возвращаете. Сформулируйте это так (измените в соответствии с логикой вашей программы):

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

Для второго вы должны перехватить исключение из вызова метода encrypt, вот так (также измените его в соответствии с логикой вашей программы):

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

Уроки, которые вы должны извлечь из этого:


  • Метод с возвращаемым типом должен всегда возвращать объект этого типа, я имею в виду во всех возможных сценариях

  • Все проверенные исключения должны всегда обрабатываться

Ответ 2

Проблема в этом методе:

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

Это сигнатура метода, которая в значительной степени говорит:


  • как называется метод: encrypt

  • какой параметр он получает: строку с именем toEncrypt

  • его модификатор доступа: public static

  • и может ли он выдавать исключение при вызове или нет.

В этом случае сигнатура метода говорит, что при вызове этот метод "может" потенциально выдавать исключение типа "Exception".

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

Итак, компиляторы говорят: либо вы окружаете это конструкцией try / catch, либо вы объявляете метод (где используется), который сам создает "Exception".

Реальная проблема заключается в определении метода "encrypt". Ни один метод никогда не должен возвращать "Exception", потому что он слишком общий и может скрывать некоторые другие виды исключений, лучше иметь конкретное исключение.

Попробуйте это:

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

В принципе, в этом конкретном случае вы должны убедиться, что пакет cryptography доступен в системе.

Java нуждается в расширении для пакета cryptography, поэтому исключения объявляются как "проверенные" исключения. Чтобы вы могли обрабатывать, когда их нет.

В этой небольшой программе вы ничего не сможете сделать, если пакет cryptography недоступен, поэтому вы проверяете это во время "разработки". Если эти исключения возникают при запуске вашей программы, это потому, что вы сделали что-то не так при "разработке", поэтому подкласс RuntimeException более уместен.

В последней строке больше не нужен оператор return, в первой версии вы перехватывали исключение и ничего с ним не делали, это неправильно.

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

Если код обречен на сбой, лучше завершить работу быстро

Вот несколько связанных ответов:

Ответ 3

Первая ошибка


java.lang.Exception; должно быть перехвачено или объявлено выброшенным byte[] encrypted = зашифровать (объединить);


означает, что ваш encrypt метод выдает исключение, которое не обрабатывается или не объявляется actionPerformed методом, в котором вы его вызываете. Прочитайте все об этом в руководстве по Java Exceptions.

У вас есть несколько вариантов, из которых вы можете выбрать, чтобы заставить код скомпилироваться.


  • Вы можете удалить throws Exception из своего encrypt метода и фактически обработать исключение внутри encrypt.

  • Вы можете удалить блок try / catch из encrypt и добавить throws Exception и блок обработки исключений в свой actionPerformed метод.

Обычно лучше обрабатывать исключение на самом низком уровне, который вы можете, вместо того, чтобы передавать его на более высокий уровень.

Вторая ошибка просто означает, что вам нужно добавить оператор return к любому методу, который содержит строку 109 (также encrypt, в данном случае). В методе есть оператор return, но если генерируется исключение, оно может быть недоступно, поэтому вам нужно либо вернуться в блок catch, либо удалить try / catch из encrypt, как я упоминал ранее.

Ответ 4

Вам нужно решить, как вы хотели бы обрабатывать исключения, создаваемые методом encrypt.

В настоящее время encrypt объявляется с помощью throws Exception - однако в теле метода исключения перехватываются в блоке try / catch . Я рекомендую вам либо:


  • удалите throws Exception предложение из encrypt и обрабатывайте исключения внутренне (подумайте о написании, по крайней мере, сообщения журнала); или,

  • удалите блок try / catch из тела encrypt и вместо этого окружите вызов в encrypt с помощью try / catch (т. Е. в actionPerformed).

Что касается ошибки компиляции, на которую вы ссылаетесь: если исключение было сгенерировано в try блоке encrypt, после завершения работы catch блока ничего не возвращается. Вы могли бы решить эту проблему, изначально объявив возвращаемое значение как null:

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

Однако, если вы сможете исправить более серьезную проблему (стратегию обработки исключений), эта проблема решится сама собой - особенно если вы выберете второй вариант, который я предложил.

java exception