我有一个班级Test
和一个方法testMethod
。我尝试将int
和类型为T
的数组传递给该方法,它应该返回数组的int
'元素。
public class Test {
public static void main(String[] args) {
System.out.println(testMethod(1, new int[] {1,2,4}));
}
public static <T> T testMethod(int rank, T[] elements) {
return elements[rank];
}
}
但是我得到_method testMethodin class Test cannot be applied to given types_
,T extends Object declared in method <T>testMethod(int,T[])
。
我想问题是数组是基本类型int
。我尝试将其更改为Integer
并且有效。
有没有办法让它工作,同时仍然使用基本数字类型,如int
或double
或float
?
答案 0 :(得分:4)
您必须重载testMethod(int, T[])
方法才能传递int[]
数组:
public static int testMethod(int rank, int[] elements) {
return elements[rank];
}
否则,您需要满足T[]
,T extends Object
(拒绝基本类型)的要求并传递Integer[]
数组:
public static <T> T testMethod(int rank, T[] elements) {
return elements[rank];
}
现在您可以传递int[]
或Integer[]
:
final Integer i1 = testMethod(1, new Integer[]{1, 2, 4});
final int i2 = testMethod(1, new int[]{1, 2, 4});
有没有办法让它工作,同时仍然使用基本的数字类型,如int或double或float?
不幸的是,只能通过方法重载。看看Arrays.binarySearch
方法(那里有18个不同的签名)。大多数签名的设计仅涵盖所有类型。
重载是否只需要从主函数复制代码?
我很害怕,是的(小型和命名更改)。找出差异:)
public static void parallelSort(long[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
int n = toIndex - fromIndex, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
else
new ArraysParallelSortHelpers.FJLong.Sorter
(null, a, new long[n], fromIndex, n, 0,
((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g).invoke();
}
public static void parallelSort(float[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
int n = toIndex - fromIndex, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0); // 1
else
new ArraysParallelSortHelpers.FJFloat.Sorter // 2
(null, a, new float[n], fromIndex, n, 0, // 3
((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g).invoke();
}
将这些代码稍加修改的粘贴复制到多个函数中是不错的做法?
绝对不是。但我们还有另一种方式吗?
你可以说原始拳击可能是一个选择:
final int[] ints = {1, 2, 4};
final Integer i3 = testMethod(1, Arrays.stream(ints).boxed().toArray(Integer[]::new));
但一个好的API 会强制用户转换他们的数据以适应给定的签名吗?
答案 1 :(得分:1)
您不能使用基本类型代替泛型类型参数。
您可以改为传递Integer
数组:
System.out.println(testMethod(1, new Integer[] {1,2,4}));
答案 2 :(得分:1)
您不能在Generic类型中使用原语,因为这不是继承Object
。在Why don't Java Generics support primitive types?
中查看更多相关信息。要在您的情况下转换为Integer
数组,您可以使用Streamn
API执行装箱:
public static Integer[] boxed(int[] array){
return IntStream.of(array).boxed().toArray(Integer[]::new);
}
它基本上与迭代数组并将值装入另一个实例相同。
每次要在泛型方法中使用原始数组时都需要这样做...不完美但这样可以转换每个现有数组而无需更改现有变量的类型({{ 1}}可以Integer
添加其他问题。)
null
编辑:
无需更改通话,只需覆盖原始int[] array = {1,2,4};
System.out.println(testMethod(1, boxed(array)));
的方法:
int
注意:对于某些类型,您可能会被迫简单地使用循环构建数组...这将更加冗长。
答案 3 :(得分:0)
我认为你已经提到了使这段代码在你的问题中起作用的解决方案..我们唯一的就是我们必须使用Integer而不是int ..
public static void main(String[] args) {
System.out.println(testMethod(1, new Integer[] {1,2,4}));
}
public static <T> T testMethod(int rank, T[] elements) {
return elements[rank];
}
如果你想使用int,你不能使用T []而必须使用int []而不是..