Mark方法调用它总是返回非null结果

时间:2013-08-28 17:16:59

标签: scala nullable compiler-warnings notnull

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

对我来说没关系,但是我得到了太多误报,即假设我定义了记录器:

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 trait:

标记它
return new Foo() with NotNull.

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

我还检查了问题Library support for Scala's NotNull trait,但它无法解决我的问题。

1 个答案:

答案 0 :(得分: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]仍然是Logger,因此您可以在其上调用该类的任何方法,或将其传递给以Logger为参数的函数。

此类构造称为未装箱标记类型,非常有用,请参阅其他应用和讨论herehere