当我尝试编译 Java 代码时,为什么会出现“异常;必须捕获或声明要抛出”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/908672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do I get "Exception; must be caught or declared to be thrown" when I try to compile my Java code?
提问by mmundiff
Consider:
考虑:
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;
}
}
I'm getting an unreported exception:
我收到一个未报告的异常:
java.lang.Exception; must be caught or declared to be thrown
byte[] encrypted = encrypt(concatURL);
As well as:
也:
.java:109: missing return statement
How do I solve these problems?
我该如何解决这些问题?
采纳答案by victor hugo
All your problems derive from this
你所有的问题都源于此
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
return encrypted;
Which are enclosed in a try, catch block, the problem is that in case the program found an exception you are not returning anything. Put it like this (modify it as your program logic stands):
它们包含在 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
}
}
For the second one you must catch the Exception from the encryptmethod call, like this (also modify it as your program logic stands):
对于第二个,您必须从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
}
}
The lessons you must learn from this:
你必须从中吸取教训:
- A method with a return-type must alwaysreturn an object of that type, I mean in all possible scenarios
- All checked exceptions must alwaysbe handled
- 具有返回类型的方法必须始终返回该类型的对象,我的意思是在所有可能的情况下
- 必须始终处理所有已检查的异常
回答by Bill the Lizard
The first error
第一个错误
java.lang.Exception; must be caught or declared to be thrown byte[] encrypted = encrypt(concatURL);
java.lang.Exception; 必须被捕获或声明被抛出 byte[] encrypted = encrypt(concatURL);
means that your encrypt
method throws an exception that is not being handled or declared by the actionPerformed
method where you are calling it. Read all about it at the Java Exceptions Tutorial.
意味着您的encrypt
方法抛出一个异常,该异常未被actionPerformed
您调用它的方法处理或声明。在Java Exceptions Tutorial阅读所有相关内容。
You have a couple of choices that you can pick from to get the code to compile.
您可以从几个选项中进行选择以编译代码。
- You can remove
throws Exception
from yourencrypt
method and actually handlethe exception insideencrypt
. - You can remove the try/catch block from
encrypt
and addthrows Exception
and the exception handling block to youractionPerformed
method.
- 您可以
throws Exception
从您的encrypt
方法中删除并实际处理内部的异常encrypt
。 - 您可以从方法中删除 try/catch 块,
encrypt
并将throws Exception
异常处理块添加到您的actionPerformed
方法中。
It's generally better to handle an exception at the lowest level that you can, instead of passing it up to a higher level.
通常最好在最低级别处理异常,而不是将其传递到更高级别。
The second error just means that you need to add a return statement to whichever method contains line 109 (also encrypt
, in this case). There is a return statement in the method, but if an exception is thrown it might not be reached, so you either need to return in the catch block, or remove the try/catch from encrypt
, as I mentioned before.
第二个错误仅意味着您需要向包含第 109 行(encrypt
在本例中也是)的任何方法添加 return 语句。方法中有一个 return 语句,但如果抛出异常,则可能无法到达它,因此您需要在 catch 块中返回,或者从 中删除 try/catch encrypt
,正如我之前提到的。
回答by Eddie
In actionPerformed(ActionEvent e)
you call encrypt()
, which is declared to throw Exception
. However, actionPerformed
neither catches this Exception (with try/catch around the call to encrypt()
) nor declares that it throws Exception
itself.
在actionPerformed(ActionEvent e)
你调用中encrypt()
,它被声明为 throw Exception
。但是,actionPerformed
既不捕获此异常(在对 的调用周围使用 try/catch encrypt()
)也不声明它Exception
自己抛出。
Your encrypt
method, however, does not truly throw Exception
. It swallows all Exceptions without even as much as logging a complaint. (Bad practice and bad style!)
encrypt
但是,您的方法并没有真正抛出Exception
. 它吞下了所有异常,甚至没有记录投诉。(糟糕的做法和糟糕的作风!)
Also, your encrypt
method does the following:
此外,您的encrypt
方法执行以下操作:
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
}
That is, if you do catch any Exception, you discard it silently and then fall off the bottom of your encrypt
method without actually returning anything. This won't compile (as you see), because a method that is declared to return a value must either return a value or throw an Exception for every single possible code path.
也就是说,如果你确实捕获了任何异常,你会默默地丢弃它,然后从你的encrypt
方法的底部掉下来,而实际上没有返回任何东西。这不会编译(如您所见),因为声明为返回值的方法必须为每个可能的代码路径返回一个值或抛出异常。
回答by AgileJon
In your 'encrypt' method, you should either get rid of the try/catch and instead add a try/catch around where you call encrypt (inside 'actionPerformed') or return null inside the catch within encrypt (that's the second error.
在您的 'encrypt' 方法中,您应该摆脱 try/catch,而是在调用 encrypt 的地方(在 'actionPerformed' 内部)添加一个 try/catch,或者在 encrypt 的 catch 内返回 null(这是第二个错误。
回答by harto
You'll need to decide how you'd like to handle exceptions thrown by the encrypt
method.
您需要决定如何处理该encrypt
方法抛出的异常。
Currently, encrypt
is declared with throws Exception
- however, in the body of the method, exceptions are caught in a try/catch block. I recommend you either:
目前,encrypt
声明为throws Exception
- 然而,在方法体中,异常在 try/catch 块中被捕获。我建议你:
- remove the
throws Exception
clause fromencrypt
and handle exceptions internally (consider writing a log message at the very least); or, - remove the try/catch block from the body of
encrypt
, and surround the calltoencrypt
with a try/catch instead (i.e. inactionPerformed
).
throws Exception
从encrypt
内部删除子句并处理异常(至少考虑写一条日志消息);或者,- 从体内除去try / catch块
encrypt
,并围绕呼叫到encrypt
与一个try / catch代替(即actionPerformed
)。
Regarding the compilation error you refer to: if an exception was thrown in the try
block of encrypt
, nothing gets returned after the catch
block finishes. You could address this by initially declaring the return value as null
:
关于您所指的编译错误:如果在try
块中抛出异常,encrypt
则catch
块完成后不会返回任何内容。您可以通过最初将返回值声明为null
:
public static byte[] encrypt(String toEncrypt) throws Exception{
byte[] encrypted = null;
try {
// ...
encrypted = ...
}
catch(Exception e){
// ...
}
return encrypted;
}
However, if you can correct the bigger issue (the exception-handling strategy), this problem will take care of itself - particularly if you choose the second option I've suggested.
但是,如果您可以纠正更大的问题(异常处理策略),这个问题就会自行解决——特别是如果您选择了我建议的第二个选项。
回答by OscarRyz
The problem is in this method:
问题出在这种方法中:
public static byte[] encrypt(String toEncrypt) throws Exception{
This is the method signaturewhich 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 throwan exception when invoked.
- 方法名称是什么:加密
- 它接收什么参数:一个名为toEncrypt的字符串
- 它的访问修饰符:public static
- 以及它在调用时是否可能抛出异常。
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.
所以编译器说:要么用 try/catch 构造包围它,要么声明方法( where is being used )自己抛出“异常”。
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 exceptionbetter 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.
Java 需要对加密包进行扩展,因此,异常被声明为“已检查”异常。供您在他们不在时处理。
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.
在这个小程序中,如果加密包不可用,您将无法执行任何操作,因此您可以在“开发”时进行检查。如果在您的程序运行时抛出这些异常是因为您在“开发”中做错了什么,那么 RuntimeException 子类更合适。
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.
最后一行不再需要 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???
If the code is to fail, it is better to Fail fast
如果代码要失败,最好快速失败
Here are some related answers:
以下是一些相关的答案: