2014-03-31 154 views
1

我發現使用@Nullable和@Nonnull註釋參數和返回值非常方便。@Nullable Eclipse分析無法正常工作

然而,Eclipse分析似乎有點片面。我覺得follwing情況是真的很煩人:

public class SomeEntity { 
    private SomeObj someObj; 

    public void setSomeObj(@Nullable SomeObj someObj) { 
    this.someObj = someObj; 
    } 

    @Nullable public SomeObj getSomeObj() { 
    return someObj; 
    } 

    public boolean hasNewSomeObj() { 
    return someObj != null; 
    } 
} 

現在,當我提出以下稱它給了我下面的Eclipse警告爲錯誤: 「潛在的空指針訪問:該方法getZuordnenMitDatenuebernahme()可能返回null 「

if(someEntity.hasNewSomeObj()) { 
    someOperator.doStuff(someEntity.getSomeObj().getSomething()); 
} 

即使如此,Null檢查也被前面的方法調用覆蓋。

有沒有人有如何處理這個問題的好建議?我真的想保留我的註釋返回值。

的Eclipse:朱諾第1版

的Java:1.6

JSR305實現:com.google.findbugs.jsr305 2.0.1

+0

這是Java 7還是Java 8(Eclipse在處理這些Java 8的方式上有變化)? –

+0

你所能做的就是使用'getSomeObj'方法並測試null。 –

+0

這將是一種恥辱,這種情況已經被大大降低了。還有其他一些情況有點複雜。 – dngfng

回答

1

if(someEntity.hasNewSomeObj()) { 
    someOperator.doStuff(someEntity.getSomeObj().getSomething()); 
} 

someEntity.getSomeObj()調用可能當您聲明@Nullable時仍然返回null,因此調用getSomething()將導致NPE。

+0

如果someEntity.hanNewSomeObj()返回true,getSomeObj()如何返回null? – dngfng

+3

我不知道確切的代碼,但是如果這個運行多線程,第二個線程可以在if(someEntity.hasNewSomeObj())和someEntity.getSomeObj()之間調用'someEntity.setSomeObj(null)'。getSomething )'。 – thr0wable

+0

不夠公平,但我沒有問過關於多線程。這僅僅是@Nullable/@ Nonnull Annoations未被正確評估的一個例子,因爲簡單的空檢查會使錯誤標記消失。 – dngfng

2

其實@ thr0wable提供了一個很好的答案。

Eclipse編譯器不可能保證,someEntity.getSomeObj()在調用someEntity.hasNewSomeObj()之後不會返回null,因爲多個線程可以隨時訪問和修改someEntity

出於同樣的原因,下面的代碼也將產生很好的理由編譯時錯誤:

if(someEntity.getSomeObj() != null) { 
    someOperator.doStuff(someEntity.getSomeObj().getSomething()); 
} 

保證的唯一方法,該對象實際上是不爲空,是通過執行以下操作:

SomeObj o = someEntity.getSomeObj(); 
if(o != null) { 
    someOperator.doStuff(o.getSomething()); 
} 

UPDATE

與Java 8,你應該考慮使用Optional ,它提供完全的功能,你需要:

static class SomeEntity { 
    private Optional<Object> someObj; 

    public void setSomeObj(Object someObj) { 
     this.someObj = Optional.ofNullable(someObj); 
    } 

    public Optional<Object> getSomeObj() { 
     return someObj; 
    } 
} 

那麼你的示例代碼可以簡化爲這一點,使用lambda表達式時:

someEntity.getSomeObj().ifPresent(o -> System.out.println(o)); 

我不知道,如果編譯時檢查已經在最新的JDT Java 8 build中實現了,但是一旦它被髮布,我認爲如果你沒有首先檢查Optional#isPresent()而試圖訪問一個Optional對象,那麼你肯定會得到編譯時警告/錯誤。