本文介绍了标记方法调用,使其始终返回不为空的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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.

这篇关于标记方法调用,使其始终返回不为空的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-20 07:04