考虑以下情况:
<T> void function(T...args){
...code...
}
然后我使用Integer[]
来调用它。编译器如何假设T
是Integer
而不是Integer[]
? (注意,我很高兴这种情况,但我仍然觉得模糊不清)。
此外,如果我希望T
为Integer[]
,那么我是否仍然可以这样做(假设不存在装箱/拆箱)?
答案 0 :(得分:2)
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
答案 1 :(得分:1)
泛型适用于对象引用,因此<T>
将适用于类的对象引用。 int[]
是一个引用int
数组的类,而int
是一个基元。 Integer[]
是一个引用Integer
数组的类,其中Integer
是另一个类。
在审查之后,varargs参数T ... args
需要一个对象引用数组,因此int[]
将是对象引用数组中的单个元素,而Integer[]
是一个数组对象引用。
如果您希望发送Integer[]
作为varargs的每个元素,则可以发送Integer[][]
。我写了一个例子:
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 });
}
}
输出(每次运行时数组的哈希码都会改变):
[I@8dc8569
1
2
3
[Ljava.lang.Integer;@45bab50a
答案 2 :(得分:1)
找到适用的方法有三个阶段。在第一阶段,javac尝试精确匹配参数类型和方法参数类型。该阶段的方法参数类型为T[]
,参数类型为Integer[]
,推断T
之后的两个matche为Integer
,因此选择方法作为 适用的方法(没有其他重载方法可以考虑)。没有进一步的阶段。
如果第一阶段没有产生适用的方法,javac将继续其他阶段。例如,如果T
明确指定为Integer[]
,则该方法在第一阶段将不匹配(因为T[]
与Integer[]
不匹配)
在第三阶段,考虑varargs; javac将匹配T
,而不是T[]
与尾随参数类型。
这确实令人困惑,而且似乎对我们的直觉含糊不清。
答案 3 :(得分:0)
请注意,泛型与问题并不完全相关。如果函数签名为void function(Object... args)
,则完全相同的问题将适用 - 如果传递类型为Integer[]
的表达式,则可以将其解释为使用数组作为args
,或者作为其中一个args
的元素。
答案是,基本上,如果可能,编译器更愿意将参数用作args
。由于您传递的表达式具有“引用类型数组”类型,因此它与args
兼容,因此,该解释占优势。
此外,如果我想要T为Integer [],那么无论如何我都可以 这样做(假设不存在装箱/拆箱)?
由于它是通用方法,因此您可以在调用时this.<Integer[]>function(...)
显式指定type参数。
但回到函数签名为void function(Object... args)
的更一般的问题。您可以自己显式创建参数数组:
function(new Integer[][]{ myIntegerArray });
或(更简单)您可以将表达式强制转换为不再是引用类型数组的类型:
function((Object)myIntegerArray);