Java泛型和数组类型,不是您所想的(例如,泛型类型中的数组)

Java泛型和数组类型,不是您所想的(例如,泛型类型中的数组),java,generics,Java,Generics,我试图指定泛型类必须是一个数组,或者更好的是一个基本数组。到目前为止,我的工作就是: interface Foo<T> { void process( T data ); } public class Moo implements Foo<int[]> { void process( int[] data ) { // do stuff here } } 接口Foo{ 空洞过程(T数据); } 公共类Moo实现了Foo{ 无效进程(int[]数据

我试图指定泛型类必须是一个数组,或者更好的是一个基本数组。到目前为止,我的工作就是:

interface Foo<T> {
  void process( T data );
}

public class Moo implements Foo<int[]> {
  void process( int[] data ) {
     // do stuff here
  }
}
接口Foo{
空洞过程(T数据);
}
公共类Moo实现了Foo{
无效进程(int[]数据){
//在这里做事
}
}
这都是完全有效的Java代码,因为基本数组扩展了对象。请注意,这个问题与我一直在寻找的所有其他Java数组通用问题完全不同。在这种情况下,人们希望用泛型类型创建数组

问题是类型T可以是扩展对象的任何东西。我想做的是:

<T extends ONLY ARRAYS>

可能吗


编辑:最终目标是对传入的数组类型添加编译时检查。现在,任何旧对象都可以传入,它可以很好地编译。只有在抛出类强制转换异常时,才会在运行时发现错误。事实上,这就是Java中泛型的全部要点,即添加更强的编译时类型检查。

您不能这样做。没有类可以扩展数组,因此永远不会有满足泛型参数
T extends Object[]
的类型。(除了
Object[]
本身之外,您不会使用泛型。)

你可以这样做:

public interface Foo<T extends Number> {
    public void process(T[] data);
}
公共接口Foo{
公开作废流程(T[]数据);
}
但是,您可能会在装箱时遇到性能问题。

不行。对于基元数组,不存在“有趣”接口或任何超类型,但存在对象:

public class SOTEST {    
    public static void main(String[] args) throws Exception {
        int[] arr = new int[] {};
        Class c = arr.getClass();
        for(Class clazz:c.getInterfaces()) {
            System.out.println(clazz.getName());
        }

        System.out.println(c.getSuperclass().toString());
    }
}

在Java中,类型参数可以受子类型关系的约束,以及所有数组
对象
可克隆
可序列化
的唯一公共超类型。最接近的方法是约束到
Object[]
,它是所有具有非基本组件类型的数组的超类型,或者约束到
Number[]
,它是
Integer[]
Long[]

即使Java确实支持这样的约束,您如何使用该数组做任何有用的事情?无法读取单个元素,因为无法声明用于保存结果的变量;也无法写入单个元素,因为无法写入可分配给数组元素的表达式

也就是说,我要将类型变量绑定到组件类型,而不是数组类型:

interface Foo<T extends Whatever> {
    void process(T[] data );
}
接口Foo{
无效过程(T[]数据);
}
因为您可以参考
T[]
知道
T
,但是知道
T扩展对象[]
不允许您直接参考组件类型


编辑:Jeffrey正确地指出数组类型不能在类型边界中使用,即
未编译,因此您一定要按照我的建议声明
,并使用
T[]
引用数组类型。

X的数组没有类型层次结构。整数[]不是数字[]的子类


要获得所需的内容,请使用数组组件类型作为类型参数T,并将参数和返回类型声明为T的数组。

为什么需要这样做?我同意“应该”是可能的。我的直觉告诉我,除了对象之外,并没有其他超类型的基元类数组。(类上有一个isArray())一个用于处理具有不同基元类型数据的图像的单一接口。另一种选择是为每种类型提供不同的接口,这是一个更糟糕的难题。例如,Foo_S32、Foo_U8、Foo_F32等等。由于您不能在Java中对任何数组类型进行子类型划分,您到底在追求什么?@PeterAbeles,但如果不进行反射或转换到特定类型,您仍然无法读取数组元素。此外,原语包括似乎不适合的
char
。和
boolean
,它每个元素占用一个字节,并且没有等效的crumb或nibble类型。不完全正确,特定类型的数组,如String[]可以分配给Object[]。但这对基本数组没有帮助。@StevenSchlansker我给出的示例毫无意义,数组不能用作类型参数绑定。你是对的,替代方法会破坏性能。在做了更多的搜索之后,我找不到任何允许我想要的约束类型的特殊语言异常。选择此作为解决方案,因为您是第一个给出正确答案的人。添加约束的目的不是为了编写一个通用类来操作数组,而是为了使API更易于使用。现在没有编译时检查,只会在运行时捕获错误。-1对于错误信息:
Integer[]
Number[]
的子类型。例如,
Number[]numbers=newinteger[]{1,2,3}编译得很好…好吧-这是胡说八道,它是java类型系统中的一个漏洞。这个整数[]ints=新的整数[]{1,2,3};数字[]数字=整数;数字[1]=新浮点数(4);for(int x:int){System.out.println(x);}编译并在运行时抛出ArrayStoreException。是的,数组的协方差确实违反了liskov可替换性(除非我们像JLS一样将ArrayStoreException作为数组契约的一部分)。但是,运行时检查确保Java在运行时保持类型安全。至于它是“疯子”,你当然有权发表你的意见,但我认为只关注打字系统中的漏洞是一个相当狭隘的观点。数组是协变的,并在运行时进行检查。泛型必须在每个使用站点上都是协变的,并且在运行时不进行检查(实际上启用了堆损坏)。哪个设计更好?
interface Foo<T extends Whatever> {
    void process(T[] data );
}