假设我们希望在接口中有一个返回数组的方法,如下所示:
interface A {
B[] findAllB();
}
但是数组是非常低级的,并且是明确实现的。它们的实现是最终的,不能更改,就像最终类一样。如果此接口中的返回类型已经是数组,则不可能返回除数组之外的任何其他内容。因此,最好避免将数组作为返回类型,因为这限制了实现类返回其想要返回的任何内容的自由度。因此,我们决定使用java.util.List
:
interface A {
List<B> findAllB();
}
但是当实现这个接口时,我们可能非常方便地返回一个实际的数组,理论上它确实实现了List接口(例如,add
和remove
抛出UnsupportedOperationException
s(:
class AImpl implements A {
List<B> findAllB() {
B[] array = ...;
...
return array; // does not work
}
}
但这不起作用,因为不能返回B[]
而不是List<B>
。
我想知道底层Java数组是否实现了一个接口(或者是否有可能有一个接口(,或者换句话说,返回一个数组来代替它是安全的。
如果这是可能的,java.util.List
也可以扩展它,这样我们就可以在窗帘后面交换地返回数组或列表。
我已经怀疑这是不可能的,但在计算机的世界里,任何事情都是可能的,谁知道呢。
你可以这样做。在实现接口时,将数组指定为类型参数。
interface A<T> {
T findAllB();
}
class Tryit implements A<int[]> {
int[] test = {1,2,3,4};
public int[] findAllB() {
return test;
}
}
System.out.println(Arrays.toString(t.findAllB()));
打印
[1, 2, 3, 4]
可悲的是,正如@Turing85所指出的,数组是"协变";,一个今天被认为是错误的功能:
很明显,这在当时被认为是一个有价值的妥协。与今天相比:回想起来,许多人认为数组协方差是一个错误。
这基本上意味着将错误类型的对象分配给它们会产生运行时错误,而不是编译时错误,这是不可取的。显然,Java的数组与List
的互换性不如我所设想的那样。
然而,一线希望是,尽管;设计错误";考虑到Java的流行,它可能是不可修复的,它已经在Kotlin中得到了修复,Kotlin基本上是Java,没有所有旧的设计缺陷。
Kotlin中的数组是不变的。这意味着Kotlin不允许我们将
Array<String>
分配给Array<Any>
,这可以防止可能的运行时故障
所以我想我唯一的选择是要么等待Java设计者解决这个问题(不太可能(,要么采用Kotlin(需要时间(,要么暂时将List<T>
与Arrays.asList
一起使用。
PS:这些选项都不能解决我最初的问题,那就是要有一个既概括列表又概括数组的接口,比如Sequential
:
package java.util;
interface Sequential<T> {
int getLength();
T getAt(int index);
}
interface List<T> extends Collection<T>, Sequential<T> {
...
}
并且允许将数组隐式地广播到Sequential
。
这并没有那么疯狂,Java语言设计者可以在不破坏向后兼容性的情况下轻松地做到这一点。它们甚至可以使Sequential<T>
扩展Iterable<T>
。要是…就好了
我没有足够的声誉发表评论,所以把它发布在这里。我同意@WJS,您可以使用java.lang.reflect.Array类来访问T,例如使用t.getClass().isArray()
来确定T是否为数组,或者使用默认方法来获取T的长度,如下所示:default int getLen(T t){ return Array.getLength(t); }
,还可以通过索引使用Array.get(Object Array,int index(方法从t中获取元素。
不,没有这样的接口。List
是抽象类数组数据结构思想的接口。
您可以通过List.toArray
、List.of
和ArrayList
构造函数在List
和数组之间自由转换。
替换的最后一行("不起作用"的行(
class AImpl implements A {
List<B> findAllB() {
B[] array = ...;
...
return array; // does not work
}
}
通过
return Arrays.asList(array);
这是将现有数组转换为所需列表的最简单方法。该列表由数组直接支持(并且是固定大小的,没有添加或删除(。
文档链接