java中的Varargs和泛型
考虑以下场景:java中的Varargs和泛型,java,generics,variadic-functions,Java,Generics,Variadic Functions,考虑以下场景: <T> void function(T...args){ ...code... } void函数(T…args){ …代码。。。 } 然后我用一个整数[]来调用它。编译器如何假定T是整数,而不是整数[]?(请注意,我很高兴情况如此,但我仍然觉得这种模糊性很奇怪) 此外,如果我希望T为Integer[],是否还有其他方法可以这样做(假设装箱/取消装箱不存在)?泛型适用于对象引用,因此将适用于类的对象引用int[]是一个引用int数组的类,而int是一个基元In
<T> void function(T...args){
...code...
}
void函数(T…args){
…代码。。。
}
然后我用一个整数[]
来调用它。编译器如何假定T
是整数
,而不是整数[]
?(请注意,我很高兴情况如此,但我仍然觉得这种模糊性很奇怪)
此外,如果我希望
T
为Integer[]
,是否还有其他方法可以这样做(假设装箱/取消装箱不存在)?泛型适用于对象引用,因此
将适用于类的对象引用int[]
是一个引用int
数组的类,而int
是一个基元Integer[]
是一个引用Integer
数组的类,其中Integer
是另一个类
在检查完这个之后,varargs参数T。。。args
需要一个对象引用数组,因此int[]
将是对象引用数组中的单个元素,而Integer[]
是一个对象引用数组
如果要将整数[]
作为varargs的每个元素发送,可以发送整数[]
。我写了一个例子:
public class SomeMain {
static <T> void foo(T...ts) {
for(T t : ts) {
System.out.println(t);
}
System.out.println();
}
public static void main(String[] args) {
int[] ints = { 1, 2, 3 };
Integer[] integers = { 1, 2, 3 };
foo(ints);
foo(integers);
//note, here each element in the varags will behave as Integer[]
foo(new Integer[][] { integers });
}
}
泛型适用于对象引用,因此
将适用于类的对象引用int[]
是一个引用int
数组的类,而int
是一个基元Integer[]
是一个引用Integer
数组的类,其中Integer
是另一个类
在检查完这个之后,varargs参数T。。。args
需要一个对象引用数组,因此int[]
将是对象引用数组中的单个元素,而Integer[]
是一个对象引用数组
如果要将整数[]
作为varargs的每个元素发送,可以发送整数[]
。我写了一个例子:
public class SomeMain {
static <T> void foo(T...ts) {
for(T t : ts) {
System.out.println(t);
}
System.out.println();
}
public static void main(String[] args) {
int[] ints = { 1, 2, 3 };
Integer[] integers = { 1, 2, 3 };
foo(ints);
foo(integers);
//note, here each element in the varags will behave as Integer[]
foo(new Integer[][] { integers });
}
}
寻找适用的方法分为三个阶段。在第一阶段,javac尝试精确匹配参数类型和方法参数类型。在这个阶段,方法的参数类型是
T[]
,参数类型是Integer[]
,在T
之后的两个匹配被推断为Integer
,因此选择该方法作为适用的方法(没有其他重载方法需要考虑)。没有进行进一步的阶段
如果第一阶段没有产生适用的方法,javac将继续到其他阶段。例如,如果将T
明确指定为Integer[]
,则该方法在第一阶段将不匹配(因为T[]
将不匹配Integer[]
)
在第三阶段,考虑了varargs;javac将使用尾随参数类型匹配T
,而不是T[]
这确实非常令人困惑,而且对我们的直觉来说似乎是模棱两可的。找到适用的方法有三个阶段。在第一阶段,javac尝试精确匹配参数类型和方法参数类型。在这个阶段,方法的参数类型是
T[]
,参数类型是Integer[]
,在T
之后的两个匹配被推断为Integer
,因此选择该方法作为适用的方法(没有其他重载方法需要考虑)。没有进行进一步的阶段
如果第一阶段没有产生适用的方法,javac将继续到其他阶段。例如,如果将T
明确指定为Integer[]
,则该方法在第一阶段将不匹配(因为T[]
将不匹配Integer[]
)
在第三阶段,考虑了varargs;javac将使用尾随参数类型匹配T
,而不是T[]
这确实非常令人困惑,而且对我们的直觉来说似乎是模棱两可的。Java编译器非常聪明,因为您给了它一个
Integer[]
,您的意思可能是T
是Integer
,而不是Integer[]
。我假设这是Java语言规范的一部分,它将…
定义为varargs
如果要指定T
是什么,可以使用以下语法:
Integer[] ary = { 1, 2, 3 };
myObj.function(ary); // T is Integer
myObj.<Integer>function(ary); // T is Integer
myObj.<Integer[]>function(ary); // T is Integer[]
<Integer>function(ary); // this is invalid; instead you could do...
this.<Integer>function(ary); // this if it's an instance method
MyClass.<Integer>function(ary); // or this if it's static
Integer[]ari={1,2,3};
myObj.函数(ari);//T是整数
myObj.函数(ari);//T是整数
myObj.函数(ari);//T是整数[]
函数(ary);//这是无效的;相反,你可以。。。
此函数(ary);//如果它是一个实例方法,那么
MyClass.function(ary);//或者这个,如果它是静态的
Java编译器非常聪明,因为您给了它一个整数[]
,所以您可能想让T
成为整数,而不是整数[]
。我假设这是Java语言规范的一部分,它将…
定义为varargs
如果要指定T
是什么,可以使用以下语法:
Integer[] ary = { 1, 2, 3 };
myObj.function(ary); // T is Integer
myObj.<Integer>function(ary); // T is Integer
myObj.<Integer[]>function(ary); // T is Integer[]
<Integer>function(ary); // this is invalid; instead you could do...
this.<Integer>function(ary); // this if it's an instance method
MyClass.<Integer>function(ary); // or this if it's static
Integer[]ari={1,2,3};
myObj.函数(ari);//T是整数
myObj.函数(ari);//T是整数
myObj.函数(ari);//T是整数[]
函数(ary);//这是无效的;相反,你可以。。。
此函数(ary);//如果它是一个实例方法,那么
MyClass.function(ary);//或者这个,如果它是静态的
请注意,泛型与问题并不完全相关。如果函数签名是void function(Object…args)
,则会出现完全相同的问题——如果传递类型为Integer[]
的表达式,则可以将其解释为使用数组作为args
,或作为args
的元素之一
答案是,基本上,如果可能的话,编译器更愿意使用参数作为args
。由于您传递的表达式具有“array of reference type”类型,因此它是兼容的
function((Object)myIntegerArray);