如何修复关于 asInstanceOf 用法的警告
How to fix a warning on asInstanceOf usage
我正在使用 scapegoat 进行 Scala 静态代码分析,我在一段代码上收到警告。这是完整的警告
Warning Use of asInstanceOf com.sksamuel.scapegoat.inspections.unsafe.AsInstanceOf
asInstanceOf used near cursor.next().asInstanceOf[com.mongodb.casbah.Imports.BasicDBObject]. Consider using pattern matching.
警告指向的行是
obj = cursor.next().asInstanceOf[BasicDBObject]
属于这段代码
val q = QueryBuilder.start(fieldName.toString()).is(value)
val cursor = collectionMongo(ARTGROUP_COLLECTION_NAME).find(q.get)
var obj = new BasicDBObject
try {
while (cursor.hasNext) {
obj = cursor.next().asInstanceOf[BasicDBObject]
log.debug(" obj.tostring" + obj.toString())
retunedList += parseArtGroup(obj)
}
} catch {
}
如何在上面的代码中使用模式匹配?
Scala 非常强调类型安全,比大多数广泛使用的语言都更加强调,这就是为什么转换通常被视为代码异味的原因。出于同样的原因,语言设计者决定使用类似命名的 isInstanceOf[T]
和 asInstanceOf[T]
来在运行时查询类型并进行转换。
为了克服这个问题,同时仍然能够与不太安全的库交互,通常建议使用模式匹配。
这是您使用模式匹配而非转换的代码片段:
val q = QueryBuilder.start(fieldName.toString()).is(value)
val cursor = collectionMongo(ARTGROUP_COLLECTION_NAME).find(q.get)
var obj = new BasicDBObject
try {
while (cursor.hasNext) {
cursor.next() match { // HERE
case basicDbObj: BasicDBObject => // HERE
obj = basicDbObj // HERE
}
log.debug(" obj.tostring" + obj.toString())
retunedList += parseArtGroup(obj)
}
} catch {
}
模式匹配是 Scala 的一项功能,它允许您在其他语言中应用类似于 switch/case
构造的东西,但具有更具表现力的语义。
模式匹配还允许您以有意义的方式解构您的输入,例如:
List(1, 2, 3, 4) match {
case head :: tail =>
println(s"The first element is $head and then comes $tail")
}
值得一提的是,如果您没有涵盖所有可能的情况,您可能会收到不同的警告,因为如果没有满足匹配的子句,您可能会抛出 MatchError
。
如果您不能完全涵盖所有可能的情况,您可能需要考虑象征通配符 catch all 模式的 _
标记,如下例所示:
cursor.next() match {
case basicDbObj: BasicDBObject =>
obj = basicDbObj
case _ => // default case
??? // probably some error handling
}
您可以阅读有关 Scala 中模式匹配的更多信息 in the official documentation。这是一份写得很好的文档,您将学到很多关于 Scala 的这个非常强大的特性。
此时我想补充的一件好事是 Scala 的 try/catch
构造使用了类似的语法。
try {
throw new RuntimeException("kaboom :)")
} catch {
case e: RuntimeException =>
println(e.getMessage) // prints "kaboom :)"
}
如果您不确定要捕获什么,Scala 附带了一个非常有用的函数来解构非致命异常:
import scala.util.control.NonFatal
try {
throw new RuntimeException("kaboom again!")
} catch {
case NonFatal(e) =>
println(e.getMessage) // prints "kaboom again!"
}
引用 the official documentation:
Extractor (note: more on extractors here) of non-fatal Throwables
. Will not match fatal errors like VirtualMachineError
(for example, OutOfMemoryError
and WhosebugError
, subclasses of VirtualMachineError
), ThreadDeath
, LinkageError
, InterruptedException
, ControlThrowable
.
您可能希望在您的代码中使用与此类似的内容。
另一方面,在您的代码中,您似乎正在解析迭代器中的对象并将它们添加到列表中。这超出了你的问题,但我想提供一个小建议。
您可能需要考虑使用类似以下的方法来做到这一点:
import scala.util.Try
Try(cursor.collect { case o: BasicDBObject => parseArtGroup(o) }).foreach(returnedList ++= _)
实际上您可能不需要将结果附加到 returnedList
,但我会让您自己判断,因为我不知道您的代码。如果您认为这种方法有道理,您可以在 Try
here and learn about the collect
method here.
上阅读更多内容
我正在使用 scapegoat 进行 Scala 静态代码分析,我在一段代码上收到警告。这是完整的警告
Warning Use of asInstanceOf com.sksamuel.scapegoat.inspections.unsafe.AsInstanceOf
asInstanceOf used near cursor.next().asInstanceOf[com.mongodb.casbah.Imports.BasicDBObject]. Consider using pattern matching.
警告指向的行是
obj = cursor.next().asInstanceOf[BasicDBObject]
属于这段代码
val q = QueryBuilder.start(fieldName.toString()).is(value)
val cursor = collectionMongo(ARTGROUP_COLLECTION_NAME).find(q.get)
var obj = new BasicDBObject
try {
while (cursor.hasNext) {
obj = cursor.next().asInstanceOf[BasicDBObject]
log.debug(" obj.tostring" + obj.toString())
retunedList += parseArtGroup(obj)
}
} catch {
}
如何在上面的代码中使用模式匹配?
Scala 非常强调类型安全,比大多数广泛使用的语言都更加强调,这就是为什么转换通常被视为代码异味的原因。出于同样的原因,语言设计者决定使用类似命名的 isInstanceOf[T]
和 asInstanceOf[T]
来在运行时查询类型并进行转换。
为了克服这个问题,同时仍然能够与不太安全的库交互,通常建议使用模式匹配。
这是您使用模式匹配而非转换的代码片段:
val q = QueryBuilder.start(fieldName.toString()).is(value)
val cursor = collectionMongo(ARTGROUP_COLLECTION_NAME).find(q.get)
var obj = new BasicDBObject
try {
while (cursor.hasNext) {
cursor.next() match { // HERE
case basicDbObj: BasicDBObject => // HERE
obj = basicDbObj // HERE
}
log.debug(" obj.tostring" + obj.toString())
retunedList += parseArtGroup(obj)
}
} catch {
}
模式匹配是 Scala 的一项功能,它允许您在其他语言中应用类似于 switch/case
构造的东西,但具有更具表现力的语义。
模式匹配还允许您以有意义的方式解构您的输入,例如:
List(1, 2, 3, 4) match {
case head :: tail =>
println(s"The first element is $head and then comes $tail")
}
值得一提的是,如果您没有涵盖所有可能的情况,您可能会收到不同的警告,因为如果没有满足匹配的子句,您可能会抛出 MatchError
。
如果您不能完全涵盖所有可能的情况,您可能需要考虑象征通配符 catch all 模式的 _
标记,如下例所示:
cursor.next() match {
case basicDbObj: BasicDBObject =>
obj = basicDbObj
case _ => // default case
??? // probably some error handling
}
您可以阅读有关 Scala 中模式匹配的更多信息 in the official documentation。这是一份写得很好的文档,您将学到很多关于 Scala 的这个非常强大的特性。
此时我想补充的一件好事是 Scala 的 try/catch
构造使用了类似的语法。
try {
throw new RuntimeException("kaboom :)")
} catch {
case e: RuntimeException =>
println(e.getMessage) // prints "kaboom :)"
}
如果您不确定要捕获什么,Scala 附带了一个非常有用的函数来解构非致命异常:
import scala.util.control.NonFatal
try {
throw new RuntimeException("kaboom again!")
} catch {
case NonFatal(e) =>
println(e.getMessage) // prints "kaboom again!"
}
引用 the official documentation:
Extractor (note: more on extractors here) of non-fatal
Throwables
. Will not match fatal errors likeVirtualMachineError
(for example,OutOfMemoryError
andWhosebugError
, subclasses ofVirtualMachineError
),ThreadDeath
,LinkageError
,InterruptedException
,ControlThrowable
.
您可能希望在您的代码中使用与此类似的内容。
另一方面,在您的代码中,您似乎正在解析迭代器中的对象并将它们添加到列表中。这超出了你的问题,但我想提供一个小建议。
您可能需要考虑使用类似以下的方法来做到这一点:
import scala.util.Try
Try(cursor.collect { case o: BasicDBObject => parseArtGroup(o) }).foreach(returnedList ++= _)
实际上您可能不需要将结果附加到 returnedList
,但我会让您自己判断,因为我不知道您的代码。如果您认为这种方法有道理,您可以在 Try
here and learn about the collect
method here.