2013-08-28 70 views
6

Scala編譯器有-Xcheck-null它試圖檢查是否有任何潛在的空指針在運行時解引用。Mark方法調用它總是返回非空結果

這沒關係,我,但我得到了太多的假陽性,即假設我定義記錄:

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性狀標記它:

return new Foo() with NotNull. 

這是確定的,但做什麼用的對象從其他方法返回?特別是如果它來自第三方圖書館?我不喜歡將所有變量標記爲可選,因爲這會增加太多開銷。此外,我不喜歡創建隱式轉換的想法(因爲它需要額外的類,我想標記爲NotNull的每個類。

我也檢查了問題Library support for Scala's NotNull trait,但它沒有幫助解決我的問題。

+0

你確實理解正確,NotNull特徵只是一個標記。它什麼也沒做。 – Jatin

回答

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] 

雖然沒有必要爲這個新的類型,這是一個有點麻煩,如果你必須這樣做了很多,所以你可以使用一些小utils的簡化/澄清符號:

type NeverNull[T] = T with NotNull 
def neverNull[A](a: A): NeverNull[A] = a.asInstanceOf[A with NotNull] 

NeverNull僅僅是具有標記NotNullneverNull任何類型T別名是一個小包裝標記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