dfa*_*dfa 176 java language-design
用Java5我们可以写:
Foo[] foos = ...
for (Foo foo : foos)
Run Code Online (Sandbox Code Playgroud)
或者只是在for循环中使用Iterable.这非常方便.
但是你不能像这样为iterable编写泛型方法:
public void bar(Iterable<Foo> foos) { .. }
Run Code Online (Sandbox Code Playgroud)
并使用数组调用它,因为它不是Iterable:
Foo[] foos = { .. };
bar(foos); // compile time error
Run Code Online (Sandbox Code Playgroud)
我想知道这个设计决定背后的原因.
Tom*_*ine 73
数组可以实现接口(Cloneable和java.io.Serializable).那为什么不Iterable呢?我想Iterable强制添加一个iterator方法,并且数组不实现方法.char[]甚至没有覆盖toString.无论如何,引用数组应该被认为不太理想 - 使用Lists.正如dfa评论,Arrays.asList将明确地为您进行转换.
(话虽如此,你可以调用clone数组.)
小智 57
该数组是一个Object,但它的项可能不是.该数组可能包含像int这样的基本类型,Iterable无法应对.至少那是我认为的.
Dan*_*ker 16
数组应该支持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 };
Run Code Online (Sandbox Code Playgroud)
所有仍然不是很完美,因为可变列表接口IList<T>不继承IReadOnlyList<T>:
IList<int> c = new List<int> { 1, 2, 3, 4 };
IReadOnlyList<int> d = c; // error
Run Code Online (Sandbox Code Playgroud)
也许这种变化可能会产生向后兼容性.
如果在较新版本的Java中类似的东西有任何进展,我会有兴趣在评论中知道!:)
jjn*_*guy 14
不幸的是,数组不是" 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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后反编译 .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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
46389 次 |
| 最近记录: |