如何处理 Java 中的多个已检查异常?
How do I handle multiple checked exceptions in Java?
我写了这个方法,我想处理UnexpectedFormatExceptions
:更具体地说,一个MissingFieldException
、一个EmptyFieldException
、一个UnknownCardTypeException
、一个UnknownSpellCardException
.
问题是我没有完全理解异常处理的思路。现在,我用构造函数等制作了 class UnexpectedFormatExceptions
(如前所述)和 subclasses。我是否应该只添加一个 try
块来获取整个代码并为每个异常添加 catch
块?正确的做法是什么?
public ArrayList<Card> loadCardsFromFile(String path) throws IOException, FileNotFoundException, UnexpectedFormatException {
String currentLine = "";
FileReader fileReader = new FileReader(path);
@SuppressWarnings("resource")
BufferedReader br = new BufferedReader(fileReader);
String[] currentsplit;
ArrayList<Card> temp = new ArrayList<Card>();
while ((currentLine = br.readLine()) != null) {
currentsplit = currentLine.split(",");
if (currentsplit[0].equals("Monster")) {
MonsterCard x = new MonsterCard(currentsplit[1], currentsplit[2], Integer.parseInt(currentsplit[5]),Integer.parseInt(currentsplit[3]), Integer.parseInt(currentsplit[4]));
temp.add(x);
}
else {
if (currentsplit[1].equals("Card Destruction")) {
CardDestruction x = new CardDestruction(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Change Of Heart")) {
ChangeOfHeart x = new ChangeOfHeart(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Dark Hole")) {
DarkHole x = new DarkHole(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Graceful Dice")) {
GracefulDice x = new GracefulDice(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Harpie's Feather Duster")) {
HarpieFeatherDuster x = new HarpieFeatherDuster(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Heavy Storm")) {
HeavyStorm x = new HeavyStorm(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Mage Power")) {
MagePower x = new MagePower(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Monster Reborn")) {
MonsterReborn x = new MonsterReborn(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Pot of Greed")) {
PotOfGreed x = new PotOfGreed(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Raigeki")) {
Raigeki x = new Raigeki(currentsplit[1], currentsplit[2]);
temp.add(x);
}
}
}
return temp;
}
"But I don't fully understand the idea of handling exceptions."
Exception就是无法按照正常的程序流程进行。
因此,如果无法遵循正常流程,使用异常处理可以让您对 "not normal" 流程采取行动。
FileNotFoundException
是一种简单的尝试说明:
所以
try {
...statements to open a file and read its contents...
} catch (FileNotFoundException fnfe) {
// maybe print out an error message to the user
// or set a flag
// etc
}
如果您不希望某个方法处理异常,则可以将异常处理委托给 'outer' 方法或调用者,方法是在代码中使用 'throw the Exception',但是在某个地方你需要做 try/catch 来处理它,就像我上面展示的那样。
But I don't fully understand the idea of handling exceptions.
打个比方:
正常代码流:
一列火车 运行 在轨道上。
异常流程:
火车脱轨(脱轨)
异常处理:
让火车回到正轨。
Should I just add a try block to take the whole code and catch blocks
for each exception? or what should I do?
只捕获最后一个语句块的适当异常。尽量保持 try-catch 块尽可能小,并且只用适当的 try-catch 块围绕必要的代码块。
您也可以选择使用这个新语法 (Java 7):
try {
// statements
} catch (MissingFieldException|EmptyFieldException|UnknownCardTypeException|UnknownSpellCardException ex) {
logger.log(ex);
throw ex;
}
异常是一个相当棘手的话题,至少在 IMO 看来,它很难掌握。经常会有关于抛出什么异常、在哪里处理它们或是否抛出它们(等等)的分歧。如果你想掌握它们,你可能需要大量阅读,尤其是用糟糕的异常方法来烧毁自己。有时我会相当通用,将很多设计决策留给您。但是,我针对您的代码提出了一些意见和建议。
Should I just add a try
block to take the whole code and catch
blocks for each exception?
No. No, no, no, NO!当您试图找出您的代码的哪一部分实际上抛出了 Exception
时,这可能会让您的生活变得艰难。但不仅如此。在 Google / 此处搜索 "try catch everything" 或类似内容以查看其他参数 - 我的回答已经足够长了。
就我个人而言,我会将您的方法分为三个:我有一个从文件读取并将内容放入 ArrayList<String>
的方法,然后我将传递 ArrayList<String>
对于这种方法,我会尝试为 ArrayList
中的每个 String
创建一个 Card
*。将它们分开也会使您的方法更容易进行(单元)测试。这是结构
public ArrayList<String> loadRowsFromFile(String path) throws IOException, FileNotFoundException {
// whatever
}
// up to you if you want this to throw UnexpectedFormatException
public ArrayList<Card> loadCardsFromFile(ArrayList<String> cardsList) throws UnexpectedFormatException {
// whatever
}
public Card buildCardFromString(String card) throws MissingFieldException, EmptyFieldException, UnknownCardTypeException, UnknownSpellCardException {
// whatever
}
我认为如果您考虑一下您的方法契约会有所帮助:我的方法需要什么作为输入以及我的方法基于该输入产生什么?它应该与 any 输入一起使用吗?它是否应该只处理一些输入并抛出异常并让调用代码处理它们?如果 card
或 cardsList
是 null
(或空),您可能想要抛出一个 IllegalArgumentException
或提供一些默认行为,具体取决于您的需要 - 您需要考虑它们.从 null
/ 空 String
中生成 Card
有意义吗?从 null
/ 空 cardsList
中得到 ArrayList<Card>
有意义吗?如果答案是 "No",一定要抛出(相关的)异常。不要为错误的输入发明解决方法。它会让你的代码成为一场噩梦。
这样分析最容易的是loadRowsFromFile
。这是一种预期从文件中生成行列表的方法。但是如果 path
是无效的,那么继续下去就没有意义了,因为它不能履行它的合同:从无效的文件/路径中产生什么 ArrayList<Card>
是最明智的?一般来说,大概none。因此,抛出相关异常是有意义的。调用它的代码需要处理这个异常,或者,如果它不是预期的,或者如果处理这个异常没有多大意义,它应该将它抛到调用堆栈的更深处。
有特定的异常(如 MissingFieldException
、EmptyFieldException
等)可能会清理您的代码并帮助调试和异常解决,但同样,这实际上取决于您想要在哪里或如何处理它们。例如,一层可能需要特定的异常,然后它将它们重新抛出到更高的地方,那里有一个 catch
用于更一般的异常。
*您可能真的想查看 factory method pattern.
我写了这个方法,我想处理UnexpectedFormatExceptions
:更具体地说,一个MissingFieldException
、一个EmptyFieldException
、一个UnknownCardTypeException
、一个UnknownSpellCardException
.
问题是我没有完全理解异常处理的思路。现在,我用构造函数等制作了 class UnexpectedFormatExceptions
(如前所述)和 subclasses。我是否应该只添加一个 try
块来获取整个代码并为每个异常添加 catch
块?正确的做法是什么?
public ArrayList<Card> loadCardsFromFile(String path) throws IOException, FileNotFoundException, UnexpectedFormatException {
String currentLine = "";
FileReader fileReader = new FileReader(path);
@SuppressWarnings("resource")
BufferedReader br = new BufferedReader(fileReader);
String[] currentsplit;
ArrayList<Card> temp = new ArrayList<Card>();
while ((currentLine = br.readLine()) != null) {
currentsplit = currentLine.split(",");
if (currentsplit[0].equals("Monster")) {
MonsterCard x = new MonsterCard(currentsplit[1], currentsplit[2], Integer.parseInt(currentsplit[5]),Integer.parseInt(currentsplit[3]), Integer.parseInt(currentsplit[4]));
temp.add(x);
}
else {
if (currentsplit[1].equals("Card Destruction")) {
CardDestruction x = new CardDestruction(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Change Of Heart")) {
ChangeOfHeart x = new ChangeOfHeart(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Dark Hole")) {
DarkHole x = new DarkHole(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Graceful Dice")) {
GracefulDice x = new GracefulDice(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Harpie's Feather Duster")) {
HarpieFeatherDuster x = new HarpieFeatherDuster(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Heavy Storm")) {
HeavyStorm x = new HeavyStorm(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Mage Power")) {
MagePower x = new MagePower(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Monster Reborn")) {
MonsterReborn x = new MonsterReborn(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Pot of Greed")) {
PotOfGreed x = new PotOfGreed(currentsplit[1], currentsplit[2]);
temp.add(x);
}
if (currentsplit[1].equals("Raigeki")) {
Raigeki x = new Raigeki(currentsplit[1], currentsplit[2]);
temp.add(x);
}
}
}
return temp;
}
"But I don't fully understand the idea of handling exceptions."
Exception就是无法按照正常的程序流程进行。
因此,如果无法遵循正常流程,使用异常处理可以让您对 "not normal" 流程采取行动。
FileNotFoundException
是一种简单的尝试说明:
所以
try {
...statements to open a file and read its contents...
} catch (FileNotFoundException fnfe) {
// maybe print out an error message to the user
// or set a flag
// etc
}
如果您不希望某个方法处理异常,则可以将异常处理委托给 'outer' 方法或调用者,方法是在代码中使用 'throw the Exception',但是在某个地方你需要做 try/catch 来处理它,就像我上面展示的那样。
But I don't fully understand the idea of handling exceptions.
打个比方:
正常代码流:
一列火车 运行 在轨道上。
异常流程:
火车脱轨(脱轨)
异常处理:
让火车回到正轨。
Should I just add a try block to take the whole code and catch blocks for each exception? or what should I do?
只捕获最后一个语句块的适当异常。尽量保持 try-catch 块尽可能小,并且只用适当的 try-catch 块围绕必要的代码块。
您也可以选择使用这个新语法 (Java 7):
try {
// statements
} catch (MissingFieldException|EmptyFieldException|UnknownCardTypeException|UnknownSpellCardException ex) {
logger.log(ex);
throw ex;
}
异常是一个相当棘手的话题,至少在 IMO 看来,它很难掌握。经常会有关于抛出什么异常、在哪里处理它们或是否抛出它们(等等)的分歧。如果你想掌握它们,你可能需要大量阅读,尤其是用糟糕的异常方法来烧毁自己。有时我会相当通用,将很多设计决策留给您。但是,我针对您的代码提出了一些意见和建议。
Should I just add a
try
block to take the whole code andcatch
blocks for each exception?
No. No, no, no, NO!当您试图找出您的代码的哪一部分实际上抛出了 Exception
时,这可能会让您的生活变得艰难。但不仅如此。在 Google / 此处搜索 "try catch everything" 或类似内容以查看其他参数 - 我的回答已经足够长了。
就我个人而言,我会将您的方法分为三个:我有一个从文件读取并将内容放入 ArrayList<String>
的方法,然后我将传递 ArrayList<String>
对于这种方法,我会尝试为 ArrayList
中的每个 String
创建一个 Card
*。将它们分开也会使您的方法更容易进行(单元)测试。这是结构
public ArrayList<String> loadRowsFromFile(String path) throws IOException, FileNotFoundException {
// whatever
}
// up to you if you want this to throw UnexpectedFormatException
public ArrayList<Card> loadCardsFromFile(ArrayList<String> cardsList) throws UnexpectedFormatException {
// whatever
}
public Card buildCardFromString(String card) throws MissingFieldException, EmptyFieldException, UnknownCardTypeException, UnknownSpellCardException {
// whatever
}
我认为如果您考虑一下您的方法契约会有所帮助:我的方法需要什么作为输入以及我的方法基于该输入产生什么?它应该与 any 输入一起使用吗?它是否应该只处理一些输入并抛出异常并让调用代码处理它们?如果 card
或 cardsList
是 null
(或空),您可能想要抛出一个 IllegalArgumentException
或提供一些默认行为,具体取决于您的需要 - 您需要考虑它们.从 null
/ 空 String
中生成 Card
有意义吗?从 null
/ 空 cardsList
中得到 ArrayList<Card>
有意义吗?如果答案是 "No",一定要抛出(相关的)异常。不要为错误的输入发明解决方法。它会让你的代码成为一场噩梦。
这样分析最容易的是loadRowsFromFile
。这是一种预期从文件中生成行列表的方法。但是如果 path
是无效的,那么继续下去就没有意义了,因为它不能履行它的合同:从无效的文件/路径中产生什么 ArrayList<Card>
是最明智的?一般来说,大概none。因此,抛出相关异常是有意义的。调用它的代码需要处理这个异常,或者,如果它不是预期的,或者如果处理这个异常没有多大意义,它应该将它抛到调用堆栈的更深处。
有特定的异常(如 MissingFieldException
、EmptyFieldException
等)可能会清理您的代码并帮助调试和异常解决,但同样,这实际上取决于您想要在哪里或如何处理它们。例如,一层可能需要特定的异常,然后它将它们重新抛出到更高的地方,那里有一个 catch
用于更一般的异常。
*您可能真的想查看 factory method pattern.