uth*_*ark 6 scala nullable compiler-warnings notnull
Scala编译器-Xcheck-null尝试检查运行时是否存在任何潜在的空指针取消引用.
这对我来说没问题,但是我得到了太多误报,即假设我定义了记录器:
private final val LOGGER: Logger = LoggerFactory.getLogger(classOf[GenericRestImpl])
Run Code Online (Sandbox Code Playgroud)
该方法getLogger永远不会返回null.我怎样才能将这些知识传递给编译器,这样它就不会抱怨?
[WARNING] TestImpl.scala:31: warning: potential null pointer dereference: LOGGER.debug
[WARNING] LOGGER.debug("Using {} for sort", sortParam)
Run Code Online (Sandbox Code Playgroud)
当我创建新实例时,我可以用NotNull特征标记它:
return new Foo() with NotNull.
Run Code Online (Sandbox Code Playgroud)
没关系,但是如何处理从其他方法返回的对象呢?特别是如果它来自第三方图书馆?我不喜欢将我的所有变量标记为Optional,因为它会增加太多的开销.另外,我不喜欢创建隐式转换的想法(因为对于我想要标记为NotNull的每个类,它需要额外的类.
我还检查了Scala的NotNull特征的问题库支持,但它没有帮助解决我的问题.
正如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]
Run Code Online (Sandbox Code Playgroud)
虽然没有必要为此创建新类型,但如果你必须做很多事情,那就有点麻烦,所以你可以使用一些小工具来简化/澄清符号:
type NeverNull[T] = T with NotNull
def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull]
Run Code Online (Sandbox Code Playgroud)
NeverNull只是T标记为的任何类型的别名,NotNull并且neverNull是一个小包装器,用于将任何类型的现有值标记A为永不为null.
然后,您可以将其用作:
private final val LOGGER: NeverNull[Logger] = neverNull {
LoggerFactory.getLogger(classOf[GenericRestImpl])
}
Run Code Online (Sandbox Code Playgroud)
如果你真的确定自己在做什么,你甚至可以将其作为隐式转换:
implicit def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull]
private final val LOGGER: NeverNull[Logger] = LoggerFactory.getLogger(classOf[GenericRestImpl])
Run Code Online (Sandbox Code Playgroud)
请注意,NeverNull[Logger]它仍然是一个Logger,因此您可以在其上调用该类的任何方法,或将其传递给作为参数a的函数Logger.
这种构造称为未装箱的标记类型,非常有用,请参阅此处和此处的其他应用程序和讨论.