我做了很多年的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
}
}
由于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)
}
我建议你和Intellij联系一下。如果我在代码中使用抛出异常的方法,它会提示我。它还建议我包含抛出异常
我的方法定义
考虑有3种方法,
A()throws Exception;
B(); //which calls A inside
C();// which calls B inside
这段代码将在Java编译,没有抱怨。但这不是最佳实践,throw exception
与方法定义中的return type一样重要。特别是在多开发人员项目中。它改进了可用性和文档。
我是不是应该去查看我调用的每个方法的源代码,以确保我没有错过一个异常?
在使用外部库时,您不需要了解源代码,但必须参考文档以了解其行为。
我正在一个由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 上查阅当前文章涉及的代码样例。