簡體   English   中英

為什么數組不能分配給 Iterable?

[英]Why is an array not assignable to Iterable?

使用 Java5 我們可以這樣寫:

Foo[] foos = ...
for (Foo foo : foos) 

或者只是在 for 循環中使用 Iterable。 這非常方便。

但是,您不能像這樣為 iterable 編寫通用方法:

public void bar(Iterable<Foo> foos) { .. }

並使用數組調用它,因為它不是 Iterable:

Foo[] foos = { .. };
bar(foos);  // compile time error 

我想知道這個設計決定背后的原因。

數組可以實現接口( Cloneablejava.io.Serializable )。 那么為什么不Iterable呢? 我猜Iterable強制添加iterator方法,而數組不實現方法。 char[]甚至不覆蓋toString 無論如何,引用數組應該被認為不太理想——使用List s。 正如 dfa 評論的那樣, Arrays.asList將明確地為您進行轉換。

(話雖如此,您可以在數組上調用clone 。)

該數組是一個對象,但它的項目可能不是。 該數組可能包含像 int 這樣的原始類型,這是 Iterable 無法處理的。 至少我是這么認為的。

數組應該支持Iterable ,但他們只是不支持,原因與 .NET 數組不支持允許按位置進行只讀隨機訪問的接口(沒有定義為標准的接口)的原因相同。 基本上,框架中通常會有惱人的小漏洞,不值得任何人花時間去修復。 如果我們能夠以某種最佳方式自行修復它們並不重要,但通常我們做不到。

更新:為了公平起見,我提到了 .NET 數組不支持支持按位置隨機訪問的接口(另請參閱我的評論)。 但是在 .NET 4.5 中,確切的接口已經被定義並且被數組和List<T>類支持:

IReadOnlyList<int> a = new[] {1, 2, 3, 4};
IReadOnlyList<int> b = new List<int> { 1, 2, 3, 4 };

一切仍然不是很完美,因為可變列表接口IList<T>沒有繼承IReadOnlyList<T>

IList<int> c = new List<int> { 1, 2, 3, 4 };
IReadOnlyList<int> d = c; // error

這樣的更改可能存在向后兼容性問題。

如果在較新版本的 Java 中類似的事情有任何進展,我很想在評論中知道::)

不幸的是,數組不夠“ class ”。 他們不實現Iterable接口。

雖然數組現在是實現 Clonable 和 Serializable 的對象,但我認為數組不是正常意義上的對象,並且不實現接口。

您可以在 for-each 循環中使用它們的原因是因為 Sun 為數組添加了一些語法糖(這是一種特殊情況)。

由於數組從 Java 1 開始就是“幾乎是對象”,因此要使它們成為 Java 中的真正對象,變化太大了。

編譯器實際上將數組上的for each轉換為帶有計數器變量的簡單for循環。

編譯如下

public void doArrayForEach() {
    int[] ints = new int[5];

    for(int i : ints) {
        System.out.println(i);
    }
}

然后反編譯.class文件產生

public void doArrayForEach() {
    int[] ints = new int[5];
    int[] var2 = ints;
    int var3 = ints.length;

    for(int var4 = 0; var4 < var3; ++var4) {
        int i = var2[var4];
        System.out.println(i);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM