当前位置: 首页 > 知识库问答 >
问题:

如何跟踪Java异常

鱼征
2023-03-14

我做了很多年的Java开发人员,主要是使用spring开发MVC Web应用程序。我正在学习Kotlin和Android作为一个自我开发项目,并且大部分都很喜欢它。我通常只是把事情弄清楚,但我认为我在这里遗漏了一些重要的东西(因为我喜欢编写易于维护且不容易出现异常的代码)。我理解与Java的互操作性,我只是对我的Kotlin代码是如何编译的感到困惑,并且对Java方法调用抛出异常没有任何警告。

下面是一个非常简单的例子,我从Android教程中获得了一个关于如何编写一个演示这个问题的文件(来自Camera Intent教程)。file.createTempFile()在Java中抛出IO异常,但Kotlin允许我只调用这个方法,就好像什么都不抛出异常一样。如果我移除方法上的@throws注释,我不会得到任何警告,说明我调用的方法可能引发异常。

@Throws(IOException::class)
private fun createImageFile(): File {
    // Create an image file name
    val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
    ).apply {
        // Save a file: path for use with ACTION_VIEW intents
        currentPhotoPath = absolutePath
    }
}

我只是不知道应该如何跟踪引发异常的Java方法。我知道很多异常,这个例子中有一个异常,但我不知道(或者我可以知道)Java和/或Java库中每个方法调用的所有可能的异常。我是不是应该去查看我调用的每个方法的源代码,以确保我没有错过一个异常?在大规模的代码库上,这看起来非常乏味,而且开销很大。

尽管在Java中抛出了IO异常,但在我的代码中,没有@throws注释,这被称为Perfect fine。我如何知道Java方法是否抛出了一个我需要在编码时考虑的异常(不查看源代码)?

private fun createImageFile(): File {
    // Create an image file name
    val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
    ).apply {
        // Save a file: path for use with ACTION_VIEW intents
        currentPhotoPath = absolutePath
    }
}

我读过关于异常和Java互操作性的文档,我只是想知道是否有一种更简单的方法来判断Java方法是否抛出了异常,然后再看看源代码(也许我错过了什么)?

https://kotlinlang.org/docs/reference/java-interop.html https://kotlinlang.org/docs/reference/exceptions.html

//Checked Exceptions
//In Kotlin, all exceptions are unchecked, meaning that the compiler does not force you to catch any 
//of 
// them. So, when you call a Java method that declares a checked exception, Kotlin does not force you 
//to 
//do anything:
fun render(list: List<*>, to: Appendable) {
    for (item in list) {
        to.append(item.toString()) // Java would require us to catch IOException here
    }
}

共有2个答案

杭志泽
2023-03-14

由于Kotlin不支持检查异常,所以当您使用Java库时,您就不走运了。你只需要仔细查看你所调用的方法的文档。

如果您正在编写Kotlin库,您可以将结果装箱到封装成功结果或错误的类中。或者你可以用密封的类。例如:

sealed class QueryResult
class Success(val result: List<String>): QueryResult()
class IncorrectSyntaxError(val msg: String): QueryResult()
class ConnectionError(val msg: String): QueryResult()

然后您的函数可以返回上面的子类之一。然后,接收方可以使用when语句来处理结果:

var result: List<String>? = null
val query = doQuery()
when (query ) {
    is Success -> result = query.result
    is IncorrectSyntaxError -> showErrorMessage(query.msg)
    is ConnectionError -> showErrorMessage(query.msg)
}
贺玉石
2023-03-14

我建议你和Intellij联系一下。如果我在代码中使用抛出异常的方法,它会提示我。它还建议我包含抛出异常我的方法定义

考虑有3种方法,

A()throws Exception;
B(); //which calls A inside
C();// which calls B inside

这段代码将在Java编译,没有抱怨。但这不是最佳实践,throw exception与方法定义中的return type一样重要。特别是在多开发人员项目中。它改进了可用性和文档。

我是不是应该去查看我调用的每个方法的源代码,以确保我没有错过一个异常?

在使用外部库时,您不需要了解源代码,但必须参考文档以了解其行为。

  1. 该方法的目的是什么。
  2. 是否引发异常。如果是,我该处理还是不处理。
  3. 您显然知道的返回类型。

我正在一个由200名开发人员维护的存储库中工作。而我们也实践着上面的。

此外,Java反射具有method.getExceptionTypes()库,它将为您列出一个方法在运行时引发的所有异常。

注:我是Java开发人员,对Kotlin语法不太了解

 类似资料:
  • 异常对象的 printStackTrace() 方法用于打印异常的跟踪栈信息,根据 printStackTrace() 方法的输出结果,开发者可以找到异常的源头,并跟踪到异常一路触发的过程。 看下面用于测试 printStackTrace 的例子程序。 上面程序中 main 方法调用 firstMethod,firstMethod 调用 secondMethod,secondMethod 调用 t

  • 问题内容: 更新 :Intellij IDEA的最新版本完全实现了我想要的功能。问题是如何在IDE外部实现此功能(以便我可以将异步堆栈跟踪信息转储到日志文件中),理想情况下无需使用检测代理。 自从我将应用程序从同步模型转换为异步模型以来,调试故障一直遇到问题。 当我使用同步API时,我总是在异常stacktraces中找到我的类,因此我知道从哪里开始寻找问题。使用异步API,我得到的堆栈跟踪既不引

  • 问题内容: 这可能是一个非常幼稚的问题。 我曾经相信Java 中的a 总是 包含堆栈跟踪。这是正确的吗? 现在看起来我捕获了 没有 堆栈跟踪的异常。是否有意义?是否 可以 在没有堆栈跟踪的情况下捕获异常? 问题答案: 无需堆栈跟踪就可以捕获Java中的Throwable对象: 构造一个具有指定详细消息,原因,启用或禁用原因,启用或禁用 可写堆栈跟踪 的新throwable 。 填写执行堆栈跟踪。此

  • 现在看来,我在没有堆栈跟踪的情况下捕获异常。有道理吗?是否有可能在没有堆栈跟踪的情况下捕获异常?

  • 问题内容: 在程序快要结束时,我希望将类的所有实例中的特定变量加载到字典中。 例如: 假设实例数量会有所不同,我希望将Foo()的每个实例的x dict加载到新的dict中。我该怎么办? 我在SO中看到的示例假定一个已经具有实例列表。 问题答案: 跟踪实例的一种方法是使用类变量: 在程序结束时,您可以像下面这样创建字典: 只有一个列表:

  • 跟踪行为控制着 Entity Framework Core 是否会在其变更跟踪器里维持实体实例的信息。如果实体是被跟踪的,任何检测到的该实体的变更都将在 SaveChanges() 时持久化到数据库中。Entity Framework Core 还会对已跟踪的、之前已加载到 DbContext 实例中的查询和实体进行相互的导航属性装配。 提示 你可以在 GitHub 上查阅当前文章涉及的代码样例。