简体   繁体   English

是否可以有 Java arrays 的接口?

[英]Is it possible to have an interface for Java arrays?

Let's say we want to have a method in an interface that returns an array, like this:假设我们想在返回数组的接口中有一个方法,如下所示:

interface A {
    B[] findAllB();
}

But arrays are very low-level and implemented definitively.但是 arrays 是非常低级的并且是明确实施的。 Their implementation is final and cannot change, much like a final class.它们的实现是最终的,不能改变,就像最终的 class 一样。 It is not possible to return anything else other than an array if the return type in this interface is already an array.如果此接口中的返回类型已经是数组,则无法返回除数组以外的任何其他内容。 So when it is better to avoid having arrays as return types because it restricts the freedom of the implementing class to return whatever it wants to return.因此,最好避免将 arrays 作为返回类型,因为它限制了实现 class 的自由来返回它想要返回的任何内容。 So, we decide to use java.util.List :所以,我们决定使用java.util.List

interface A {
    List<B> findAllB();
}

But when implementing this interface, it might be extremely convenient for us to return an actual array, that in theory, does implement the List interface (eg with add and remove throwing UnsupportedOperationException s):但是在实现这个接口时,我们返回一个实际的数组可能非常方便,理论上它确实实现了 List 接口(例如, addremove抛出UnsupportedOperationException s):

class AImpl implements A {
    List<B> findAllB() {
        B[] array = ...;
        ...
        return array; // does not work
    }
}

But this does not work because you cannot return a B[] instead of List<B> .但这不起作用,因为您不能返回B[]而不是List<B>

I was wondering if there is an interface, (or if it even is possible to have an interface) that the low-level Java array implements, or, in other words, it is safe to return an array in its stead.我想知道是否存在低级 Java 数组实现的接口(或者甚至可能有接口),或者换句话说,可以安全地返回一个数组来代替它。

If this were possible, java.util.List could also extend it so we can return arrays or lists interchangeably behind the curtains.如果这是可能的, java.util.List也可以扩展它,这样我们就可以返回 arrays 或在窗帘后面互换列表。

I already suspect this is impossible, but in the world of computers anything is possible, so who knows.我已经怀疑这是不可能的,但在计算机的世界里,一切皆有可能,所以谁知道呢。

You could do it like this.你可以这样做。 Specify the array as the type parameter when implementing the interface.实现接口时指定数组作为类型参数。

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()));

prints印刷

[1, 2, 3, 4]

Sadly, as @Turing85 pointed out, arrays are "covariant", a feature that is deemed a mistake today :可悲的是,正如@Turing85 指出的那样, arrays 是“协变的”, 今天被认为是一个错误的功能:

Clearly this was considered a worthy compromise at the time.显然,这在当时被认为是值得妥协的。 Contrast that with today: many regard array covariance as a mistake, in retrospect.与今天的对比:回想起来,许多人认为数组协方差是一个错误。

This basically means assigning objects of the wrong type to them generates a runtime error rather than a compile-time error, which is undesirable.这基本上意味着将错误类型的对象分配给它们会产生运行时错误而不是编译时错误,这是不可取的。 Evidently Java's arrays are not as interchangeable with List s as I had assumed.显然,Java 的 arrays 不像我想象的那样与List互换。

The silver-lining however, is that even though this "design mistake" is probably not remediable given Java's prevalence, it has been fixed in Kotlin which is basically Java without all the old design flaws.然而,一线希望是,即使考虑到 Java 的流行,这种“设计错误”可能无法补救,但它已在 Kotlin 中得到修复,基本上是 Java,没有所有旧的设计缺陷。

Arrays in Kotlin are invariant . Kotlin 中的 Arrays 是不变的。 This means that Kotlin does not let us assign an Array<String> to an Array<Any> , which prevents a possible runtime failure这意味着 Kotlin 不允许我们将Array<String>分配给Array<Any> ,这可以防止可能的运行时故障

So I guess my only choices are to either wait for Java designers to remedy this (unlikely), adopt Kotlin (takes time), or use List<T> with Arrays.asList for the time being.所以我想我唯一的选择是要么等待 Java 设计师解决这个问题(不太可能),采用 Kotlin (需要时间),或者使用List<T>Arrays.asList

PS: None of these options solve my original problem which was to have an interface that generalizes both lists and arrays, such as Sequential : PS:这些选项都不能解决我最初的问题,即拥有一个通用列表和 arrays 的接口,例如Sequential

package java.util;

interface Sequential<T> {
    int getLength();
    T getAt(int index);
}

interface List<T> extends Collection<T>, Sequential<T> {
    ...
}

And allowing arrays to be implicitly casted to Sequential .并允许将 arrays 隐式转换为Sequential

This is not that crazy, Java language designers could easily do this without breaking backward compatibility.这并不是那么疯狂,Java 语言设计者可以轻松地做到这一点,而不会破坏向后兼容性。 They could even make Sequential<T> extend Iterable<T> .他们甚至可以让Sequential<T>扩展Iterable<T> If only...要是...

I don't have enough reputation to comment, so post it here.我没有足够的声誉来发表评论,所以在这里发布。 I agree with @WJS and you can have default method to get T's length like this: default int getLen(T t){ return Array.getLength(t); }我同意@WJS,您可以使用默认方法来获取 T 的长度,如下所示: default int getLen(T t){ return Array.getLength(t); } default int getLen(T t){ return Array.getLength(t); }

No, there is no such interface.不,没有这样的界面。 List is the interface that abstracts the idea of an array-like datastructure. List是抽象类数组数据结构概念的接口。

You can freely convert between List s and arrays via List.toArray , List.of and the ArrayList constructor.您可以通过List.toArrayList.ofArrayList构造函数在List和 arrays 之间自由转换。

Replace the last line (the one that "does not work") of替换最后一行(“不起作用”的那一行)

class AImpl implements A {
    List<B> findAllB() {
        B[] array = ...;
        ...
        return array; // does not work
    }
} 

by经过

 return Arrays.asList(array);

This is the simplest way to turn the array that you have into the List that you want.这是将您拥有的数组转换为您想要的列表的最简单方法。 The list is directly backed by the array (and is fixed size, no adds or removes).该列表直接由数组支持(并且大小固定,没有添加或删除)。

Documentation link 文档链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java中是否可以有没有方法的接口 - Is it possible to have an interface without a method in java 如果我们无法在Java中创建接口的实例,那么数组就是对象。 然后,如何创建接口数组? - If we cannot create an instance of an interface in Java and arrays are nothing but Objects. Then, How is it possible to create Array of interface? 是否可以拥有一个具有抽象和完整方法的Java接口? - Is it possible to have a Java interface that has abstract and full methods? 在java中,是否可以将Serializable接口添加到在运行时没有它的类? - In java, is it possible to add the Serializable interface to class that doesn't have it at runtime? 是否有可能在Java中包含包含数组和基元的数组? - Is it possible to have an array containing both arrays and primitives in Java? 是否可以在java中实例化一个接口? - Is it possible to instantiate an interface in java? Java,是否可以继承接口? - Java, Is it possible to inherit interface? 是否可以在java中创建接口的对象? - Is it possible to create an object of an interface in java? 是否可以在Java运行时实现接口? - Is it possible to implement an interface at runtime in Java? 如何在Java中生成具有N个可能元素(M&gt; N)的数组列表(都具有长度M)? - How to generate a list of arrays (all have the length M) with N possible elements (M > N) in Java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM