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,但它无法解决我的问题。
答案 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
为参数的函数。