问题描述
Scala编译器具有-Xcheck-null
,它试图检查运行时是否存在任何潜在的空指针取消引用.
Scala compiler has -Xcheck-null
which tries to check if there are any potential null pointer dereference in runtime.
我可以,但是我收到了很多误报,即假设我定义了logger:
It's ok for me, but I get too much false positives, i.e. suppose I define logger :
private final val LOGGER: Logger = LoggerFactory.getLogger(classOf[GenericRestImpl])
方法getLogger
从不返回null
.如何将这些知识传递给编译器,这样它就不会抱怨?
The method getLogger
never returns null
. How can I pass this knowledge to compiler so it will not complain?
[WARNING] TestImpl.scala:31: warning: potential null pointer dereference: LOGGER.debug
[WARNING] LOGGER.debug("Using {} for sort", sortParam)
创建新实例时,可以将其标记为NotNull
特性:
When I create new instance I can mark it with NotNull
trait:
return new Foo() with NotNull.
可以,但是如何处理从其他方法返回的对象?特别是如果它来自第三方图书馆?我不喜欢将所有变量都标记为Optional的想法,因为这会增加过多的开销.另外,我不喜欢创建隐式转换的想法(因为对于我要标记为NotNull的每个类,都需要额外的类.
That's ok, but what to do with objects returned from other methods? Especially if it is comming from 3rd party library? I don't like idea to mark all my variables as Optional, because it will add too much overhead. Also, I don't like idea to create implicit conversions (because it will require extra class for each class that I want to mark as NotNull.
我还检查了问题 Scala的NotNull特性的图书馆支持,但它没有不能解决我的问题.
I also checked question Library support for Scala's NotNull trait but it didn't help to solve my problem.
推荐答案
正如Jatin所说,NotNull
只是一个标记或标记,因此您可以使用NotNull
标记任何东西.这样做的技巧是强制转换基本类型with NotNull
.
As Jatin mentions, NotNull
is just a marker or tag, so you can use NotNull
to tag anything. The trick to do this is to forcing a cast your base type with NotNull
.
因此您可以编写类似"notnull".asInstanceOf[String with NotNull]
的内容.如果您确定它永远不会为空,那么这是一个安全的方法.
So you can write something like this "notnull".asInstanceOf[String with NotNull]
. It's a safe cast if you are sure it's never ever null.
在您的实际示例中,您可以这样写:
In your actual example, you can therefore write:
private final val LOGGER: Logger with NotNull =
LoggerFactory.getLogger(classOf[GenericRestImpl]).asInstanceOf[Logger with NotNull]
虽然不需要为此创建新类型,但是如果您需要做很多事情,则有点麻烦,因此您可以使用一些小工具来简化/阐明该符号:
While there is no need to create new types for this, it's a bit cumbersome if you have to do it a lot, so you could use some little utils to simplify/clarify the notation:
type NeverNull[T] = T with NotNull
def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull]
NeverNull
只是任何用NotNull
标记的T
类型的别名,而neverNull
是一个小包装程序,用于将任何现有的A
类型的值标记为永不为空.
NeverNull
is just an alias for any type T
tagged with NotNull
and neverNull
is a little wrapper to tag any existing value of type A
as being never null.
然后您可以将其用作:
private final val LOGGER: NeverNull[Logger] = neverNull {
LoggerFactory.getLogger(classOf[GenericRestImpl])
}
如果您确实确定自己在做什么,那么甚至可以将其转换为隐式转换:
You could even make this an implicit conversion, if you are really sure of what you are doing:
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
为参数的函数.
Note that NeverNull[Logger]
is still a Logger
, so you can call any method of that class on it, or pass it on to functions that take as parameter a Logger
.
这种构造称为未框标记的类型,非常有用,请参见其他应用程序和讨论此处和这里.
This kind of construct is called an unboxed tagged type and is pretty useful, see other applications and discussion here and here.
这篇关于标记方法调用,使其始终返回不为空的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!