如何在Java中处理多个已检查的异常?

时间:2015-04-14 00:37:26

标签: java exception-handling

我写了这个方法,我想处理UnexpectedFormatExceptions:更具体地说,是MissingFieldExceptionEmptyFieldExceptionUnknownCardTypeExceptionUnknownSpellCardException

问题是我不完全理解处理异常的想法。现在,我创建了一个类UnexpectedFormatExceptions(如前所述)和子类与构造函数等。我是否应该添加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;
}

3 个答案:

答案 0 :(得分:1)

  

但我并不完全理解处理例外的想法。

类比:

正常代码流程

火车正在赛道上运行。

例外流程

火车离开赛道(出轨)

异常处理:

让火车回到正轨。


  

我是否应该添加一个try块来获取整个代码并捕获块   每个例外?或者我该怎么办?

仅为最后一个语句块捕获适当的异常。尽量保持try-catch块尽可能小,并且只使用适当的try-catch块包围必要的代码块。

您也可以选择使用这种新语法(Java 7):

try {
    // statements
} catch (MissingFieldException|EmptyFieldException|UnknownCardTypeException|UnknownSpellCardException ex) {
    logger.log(ex);
    throw ex;
}

答案 1 :(得分:0)

“但我不完全理解处理异常的想法。”

异常只是无法遵循正常的程序流程。

因此,如果无法遵循正常流程,则使用异常处理可以对“非正常”流程采取措施。

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
}

如果您不希望某个方法处理Exeption,那么您可以将Exception处理委托给“外部”方法或调用者,方法是让代码“抛出异常”,但是在某个地方“我需要做try / catch来处理它,就像我上面所示。

答案 2 :(得分:0)

例外是一个非常棘手的话题 - 至少IMO-很难掌握。很多时候会出现关于抛出什么异常,在哪里处理它们或者是否抛弃它们(等等)的分歧。如果你想掌握它们,你可能需要大量的阅读,特别是用坏的异常方法来焚烧自己。我有时会相当通用,给你留下很多设计决定。但是我对你的代码做了一些评论和建议。

  

我是否应该添加try块来获取每个例外的整个代码和catch块?

No. No, no, no, NO!当您试图找出代码的哪一部分实际上抛出了Exception时,它可能会让您的生活变得艰难。但不仅如此。在Google /这里搜索“尝试抓住一切”或类似的内容以查看其他参数 - 我的答案已经足够长了。

就个人而言,我将你的方法分成三个:我有一个从文件中读取并将内容放入ArrayList<String>的方法,然后我将ArrayList<String>传递给它方法,对于String中的每个ArrayList,我会尝试创建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
}

我认为如果你考虑一下你的方法合同会有所帮助:我的方法需要什么作为输入?我的方法根据输入产生什么?它应该与任何输入一起使用吗?它是否只能用于某些输入并抛出异常并让调用代码处理它们?如果cardcardsListnull(或为空),您可能需要抛出IllegalArgumentException或提供一些默认行为,具体取决于您的需求 - 您需要考虑它们。从Card /空null中生成String是否有意义?从[{1}} /空ArrayList<Card>中获得null是否有意义?如果答案是“否”,则无论如何抛出(相关)异常。不要为糟糕的输入创建变通方法。它会让你的代码变成一场噩梦。

最容易分析的是cardsList。这是一种预期会从文件中生成行列表的方法。但是如果loadRowsFromFile无效,那么继续进行是没有意义的,因为它无法履行其合同:path从无效文件/路径生成出来最明智的是什么?一般来说,可能没有。因此,抛出相关的异常是有意义的。调用它的代码需要处理这个异常,或者,如果没有预期,或者处理这个异常没有意义,它应该把它放到调用堆栈的上方。

有特定的例外(例如ArrayList<Card>MissingFieldException等)可以清理代码并帮助调试和解决异常,但同样,它实际上取决于你想要处理它们的位置或方式。例如,一个图层可能需要特定的例外情况,然后它会将它们重新抛出更高的位置,而EmptyFieldException表示更常见的例外情况。

*您可能真的想查看factory method pattern