Java - 应该在何处以及如何使用异常?

hyp*_*ube 10 java exception-handling exception

我正在阅读有关Java中异常处理的一些内容,以便能够编写更好的代码.好吧,我承认,我很内疚; 我已经使用了太多的try-catch {}块,我已经ex.printStackTrace()在catch中使用了,甚至没有使用正确的记录器(实际上System.out并且System.err被重定向到a PrintWriter,因此生成了日志).然而,经过几个小时的阅读,我发现自己处在一个陌生的地方:未知.如果异常被设计为传递有关流的异常状态的信息,那么如何知道WHERE是用该信息做某事的适当级别?

例如,当发生数据库错误时,是应该返回空值还是错误代码,还是抛出异常?如果抛出,那么应该处理该异常?据我所知,如果你不能对它做任何事情,那么记录异常是没用的.但是,在GUI应用程序中,这可能很容易杀死你的GUI(我使用SWT而且我经常看到这个),即使对于menuShown()方法的情况(ArrayIndexOutOfBounds如果不处理,例外将关闭应用程序).这个例子可以永远持续下去,但这里是问题摘要:

  1. 使用try-catch()过度地对性能产生负面影响吗?
  2. 使用特定的异常类型更好吗?如果我错过了可能发生的X类异常之一怎么办?
    坦率地说,我听说并且仅用了10%,我认为在2 - 3年内会出现Java标准异常.是的,有人说,如果来电者不知道如何处理抛出的异常,他就没有权利调用投掷方法.是对的吗?
  3. 我读过Anders Hejlsberg的这篇文章,说检查过的例外情况很糟糕.这是否表明在某些情况下建议进行方便的吞咽异常?
  4. 一张图片价值1000字; 我想一些例子在这里会有很多帮助.

我知道这个主题是永恒的,但实际上我期待着根据你的建议审查一个150个班级的中型项目.非常感谢.

Jef*_*rey 7

异常的一般经验法则是,如果你可以对它做些什么,抓住它并处理它,如果你不能,重新将它扔到下一个方法.要了解您的一些细节:

  1. 不,使用过多的try/catch不会对性能产生影响
  2. 使用最具体的异常类型即可.例如,如果可以避免,则通常不应抛出异常.通过抛出特定类型,您可以让用户知道可能出现的问题.但是,您可以将其重新抛出为更通用的内容,因此不关心特定异常的调用者不需要知道它(例如,GUI不关心它是否是IOException与ArrayIndexOutOFBoundsException).
  3. 你会发现更喜欢检查异常的人,你会发现更喜欢未经检查的人.一般情况下,我尝试使用未经检查的异常,因为对于大多数已检查的异常,您通常没有太多可以做的事情,并且您仍然可以处理未经检查的异常,而您不必这样做.我经常发现自己重新抛出已检查的异常,因为我对它们做不了多少(另一种策略是捕获已检查的异常并将其重新抛出为未经检查的,因此链中较高的类如果不需要则不需要捕获它).

我通常喜欢在捕获它们的位置记录异常 - 即使我不能对它做任何事情,它也有助于诊断问题.如果您不熟悉它,还要查看Thread.setDefaultUncaughtExceptionHandler方法.这允许您处理未被任何人捕获的异常并对其执行某些操作.这对于GUI应用程序特别有用,因为否则可能看不到异常.

举几个例子:

try {
   // some database operation
}
catch (IOException ex) {
   // retry the database operation. then if an IO exception occurs rethrow it. this shows an example doing something other than just catch, logging and/or rethrowing.       
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,我会很乐意扩展其中的任何部分.


Naw*_*Man 1

例外是存在的,因此任务的程序员不必自己处理问题。(1):如果问题对于他来说在任务中处理不合逻辑。从流中读取字符串的任务不应该处理磁盘错误,不是吗?但如果数据不包含字符串,处理起来应该是非常合乎逻辑的。

(2): 他无法自己处理它(没有足够的信息)从文件中读取字符串且未找到文件的任务可能会要求用户选择另一个文件,但是现在该任务如何才能该文件可能在哪个文件夹中文件的扩展名可能是。如果不知道这一点,任务如何创建一个 GUI 来重新询问这一点。

(3):没有逻辑(或可管理)的方法来区分不同的回报。如果任务无法读取文件并返回 null。如果文件格式错误,也返回null怎么办?这两者有何不同?可以使用异常来区分这一点。这就是为什么它被称为异常:-D。

(4):有许多类似的任务需要类似的处理和编写,所有任务都很难维护。为所有访问编写句柄代码可能会很混乱,因为您可能需要多次重复。


interface DBAccess {
    public Result accessDB();
}

class DBOperation {
    static public void DoOperation(DBAccess pAccess) {
        try { return DBAccess.accessDB(); }
        catch(InvalidDBPasswordException IPE) {
             // Do anything about invalid password
        }
        catch(DBConnectionLostException DBCLE) {
             // Do anything about database connection lost
        }
        // Catch all possible DB problem
    }
}

...

private User[] ShowUserList_and_ReturnUsers() {
    // Find the used.

    // Show user list

    if (Users.count() == 0)
         return null;
    else return Users;

    // No need to handle DB connection problem here
}
private User[] GetUserProfile() {
    // Find the used and return
    // No need to handle DB connection problem here
}
...

/** An onClick event to show user list */ {
    DBOperation.DoOperation(new DBAccess() {
        public Result accessDB() {
            return ShowUserList_and_ReturnUsers();
        }
    });
}
/** An onClick event to show a user profile */ {
    DBOperation.DoOperation(new DBAccess() {
        public Result accessDB() {
            return GetUserProfile();
        }
    });
}
... Many more DB access
Run Code Online (Sandbox Code Playgroud)

(5):编写所有错误检查会使任务复杂化或减慢。上述问题应该表明它如何帮助减少并发症。以下是如何帮助您不放慢速度。



for(int i = 0; i < Users.length; i++) {
    User aUser = Users[i];
    // Do something with user
}

Replaced with

try {
  for(int i = 0; ; i++) {
      User aUser = Users[i];
      // Do something with user
  }
}
catch(ArrayOutOfBoundException AOBE) {}
Run Code Online (Sandbox Code Playgroud)

如果用户数量较多,替换代码的性能会更好。


当数据库发生错误时,应该返回空值和错误代码还是抛出异常?答:取决于什么样的错误。就像如果您找不到用户,那不是错误。但是,如果密码错误或连接断开,这些都是错误,因为尝试以正常方式处理它会使程序变得复杂。

(1). 使用过多的try-catch()会对性能产生负面影响?Ans:据我所知,根据《Effective Java》,它的效果非常非常小(只是在循环中效果不好)(我现在没有带这本书)。

(2)。使用特定的异常类型更好?答:用户特定的最好避免解决错误的问题。

如果我错过了可能发生的 X 种异常类型之一怎么办?坦率地说,在 2-3 年内,我听说过并使用过的 Java 标准异常只有 10%。Ans:就像如果你无一例外地处理错误一样,你也可能会错过它。当您发现这一点时,只需将其添加进去即可。

是的,有人说,如果调用者不知道如何处理抛出的异常,他就不应该有权调用抛出的方法。是对的吗?Ans:不,如果我不知道如何处理某些异常,请重新抛出它。

(3)。我读过 Anders Hejlsberg 的这篇文章,他说检查异常很糟糕。这是否表明在某些情况下建议方便的异常吞咽?答:我认为他正在谈论“检查异常”作为编译器的一项功能,以确保应处理某些异常。例外的想法。

(4)。一张图片胜过 1000 个单词……我想一些例子在这里会有很大帮助。答:上面的代码。

我现在开始跑步了……抱歉……:-p(马上就到,亲爱的!!)