2017-08-12 33 views
-1

在Java 8的流庫中,我在java.util.stream.Stream的相同方法中發現了一個有趣的問題:爲什麼Java 8中的java.util.stream.Stream的empty()方法(不帶任何參數)包含類型參數?

  • static <T> Stream<T> empty()

我們可以看到,在方法簽名沒有參數。根據我的理解,在這種情況下不應該有類型參數 - <T> - 在可選說明符-static之後。例如,在方法Optional<T> findAny()中,沒有類型參數按照預期給出。

因此,任何人都可以解釋爲什麼static <T> Stream<T> empty()包含一個類型參數

+3

請參閱類型推斷:https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html –

+0

@ holi-java我不認爲這與類型推斷有很大關係...... – Eugene

+0

@Eugene嘿,[目標類型](https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html#target_types)部分完全描述了它。我認爲OP開始學習泛型,所以我希望他首先看到類型推斷。 :) –

回答

2

讓我們首先聲明自己的類型,以便更好地理解爲什麼:

static interface Stream<T> { 

    public static Stream<T> empty() { // will not compile here 
     return new Stream<T>() { 
     }; 
    } 

} 

因爲這些代碼,現在,它不會編譯,說can not make a static reference to the non-static type T,這使得IMO完整意義上的。發生這種情況是因爲靜態上下文完全獨立於類型參數(這應該回答你的第一個問題)。

爲了解決這個問題,我們需要的類型參數添加到方法:

public static <T> Stream<T> empty() { // notice the extra <T> 
    return new Stream<T>() { 
    }; 
} 

這將編譯就好了,但有一個隱藏的問題 - 類T和方法T完全獨立的,他們之間沒有任何關係

這也可以寫成這樣具有完全相同的效果(和更清潔的IMO):

public static <R> Stream<R> empty() { 
    return new Stream<R>() { 
    }; 
} 

,因爲你有這樣的:return new Stream<R>()...我們已經有效地做出RT等同,可能是這是原因爲什麼他們仍然在empty()的聲明中使用T而不是其他類型。

現在讓我們套用同樣的邏輯findAny

public <T> Optional<T> findAny(); 

,這將產生一個警告 - 你是隱藏了在類級別(Stream<T>)和一個在方法聲明的<T>。發生這種情況的原因是findAny不是 static,它使用已聲明的類型參數 - 通過引入另一個<T>來隱藏該類型參數,該類型參數與類級別的類型無關。

相關問題