6

Scala 编译器-Xcheck-null尝试检查运行时是否存在任何潜在的空指针取消引用。

对我来说没问题,但是我得到了太多误报,即假设我定义了 logger :

private final val LOGGER: Logger = LoggerFactory.getLogger(classOf[GenericRestImpl])

该方法getLogger永远不会返回null。我怎样才能将这些知识传递给编译器,这样它就不会抱怨?

[WARNING] TestImpl.scala:31: warning: potential null pointer dereference: LOGGER.debug
[WARNING]       LOGGER.debug("Using {} for sort", sortParam)

当我创建新实例时,我可以用NotNull特征标记它:

return new Foo() with NotNull.

没关系,但是如何处理从其他方法返回的对象呢?特别是如果它来自 3rd 方库?我不喜欢将所有变量都标记为可选的想法,因为它会增加太多开销。另外,我不喜欢创建隐式转换的想法(因为它需要为每个我想标记为 NotNull 的类提供额外的类。

我还检查了对 Scala 的 NotNull 特征的问题库支持,但它无助于解决我的问题。

4

1 回答 1

5

正如 Jatin 所提到的,NotNull它只是一个标记或标签,所以你可以NotNull用来标记任何东西。这样做的诀窍是强制转换您的基本类型with NotNull

所以你可以写这样的东西"notnull".asInstanceOf[String with NotNull]。如果您确定它永远不会为空,这是一个安全的演员表。

因此,在您的实际示例中,您可以编写:

private final val LOGGER: Logger with NotNull = 
   LoggerFactory.getLogger(classOf[GenericRestImpl]).asInstanceOf[Logger with NotNull]

虽然不需要为此创建新类型,但如果你必须做很多事情会有点麻烦,所以你可以使用一些小工具来简化/澄清符号:

type NeverNull[T] = T with NotNull
def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull]

NeverNull只是任何T标记为的类型的别名,NotNull并且neverNull是一个小包装器,用于将任何现有的类型值标记A为从不为空。

然后,您可以将其用作:

private final val LOGGER: NeverNull[Logger] = neverNull {
       LoggerFactory.getLogger(classOf[GenericRestImpl])
}

如果您真的确定自己在做什么,您甚至可以将其设为隐式转换:

implicit def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull]

private final val LOGGER: NeverNull[Logger] = LoggerFactory.getLogger(classOf[GenericRestImpl])

请注意,NeverNull[Logger]它仍然是 a Logger,因此您可以在其上调用该类的任何方法,或将其传递给以 a 作为参数的函数Logger

这种构造称为未装箱标记类型,非常有用,请参阅此处此处的其他应用程序和讨论。

于 2013-09-04T02:33:16.797 回答