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