我下面有返回通用数组的通用方法:
public static <T> T[] genericMethod1(List<T> input) {
T[] res = (T[]) new Object[input.size()];
int i = 0;
for (T t : input) {
res[i] = t;
i++;
}
return res;
}
public static <T> T genericMethod2(List<T> input) {
return input.get(0);
}
但是稍后,当我尝试使用以下方法获取结果数组时:
LinkedList<Integer> list = new LinkedList<Integer>();
list.addFirst(1);
list.addFirst(1);
Integer[] i = (Integer[]) genericMethod1(list); // 1) Runtime error
Integer j = genericMethod2(list); // 2) works
对于情况1,我总是在运行时出错:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
谁能解释为什么以及如何正确返回通用数组?谢谢。
以下是我的理解,如果我写错了,请纠正我。
正如Tim所提到的,类型擦除是在编译时发生的,因此在字节码中,每个T对象只是Object类型,同时,编译器将“适当地”将Object的类型强制转换为T。
假设T是一个整数,其中T被声明为对象。对于引用位置,将其类型转换(隐式)为T。
除非声明了T []数组,否则为Object [],并且在引用该数组的位置保留为Object []。没有隐式转换为T []。
您看到的内容的解释是由于 类型擦除引起的 。这是编译器执行类型擦除 后 的genericMethod()
样子: __
public static Object[] genericMethod(List input) {
Object[] res = new Object[input.size()];
int i = 0;
for (Object t : input) {
res[i] = t;
i++;
}
return res;
}
换句话说,此方法将返回type数组Object
。无法将an转换Object[]
为an,Integer[]
因为它们不是同一类型。如果希望方法能够动态返回所需的类型,则可以使用Array.newInstance()
。这还需要传入想要的数组类型作为输入参数:
public static <T> T[] genericMethod(Class<T> clazz, List<T> input) {
@SuppressWarnings("unchecked")
T[] res = (T[]) Array.newInstance(clazz, input.size());
int i = 0;
for (T t : input) {
res[i] = t;
i++;
}
return res;
}
现在,您的代码段将运行而不会出现错误:
LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] i = genericMethod(Integer.class, list);
更新:
genericMethod2()
类型擦除后,您的第二种方法如下所示:
public static Object genericMethod2(List input) {
return input.get(0);
}
它将返回输入列表的第一个元素,强制转换为Object
。这是该方法的用法:
Integer j = genericMethod2(list);
编译器将尝试将输出强制转换genericMethod2()
为Integer
:
Integer j = (Integer)genericMethod2(list);
此强制转换是合法的,因为所有人Integer
也都是Object
,并且在这里成功,因为您传入了的集合Integer
。第二种方法与您为我们强调的第一种方法不同。
问题内容: 考虑以下示例(OOP书籍中的典型示例): 我有一Animal堂课,每个人Animal可以有很多朋友。 和子类喜欢Dog,Duck,Mouse等里面加如特定行为bark(),quack()等等。 这是Animal课程: 这是一些带有大量类型转换的代码片段: 有什么办法可以将泛型用于返回类型来摆脱类型转换,所以我可以说 这是一些带有返回类型的初始代码,这些代码作为从未使用过的参数传递给该方
问题内容: 这就是我想要做的。使用反射,我想获取所有方法及其返回类型(非泛型)。我一直在这样做。但是,当我遇到返回类型未知的方法时,我遇到了限制。 我如何知道方法的返回类型是否通用?我没有奢求在运行时拥有对象。我正在尝试使用Google 或使用抽象类来获取类型信息。我想关联到对象的方法。 有人认为Java不保留通用信息。在这种情况下,为什么第一次强制转换有效而第二次强制转换无效。 任何帮助表示赞赏
问题内容: 我有以下方法: 我想使其成为一种通用方法,这样我就不必为每个新的自定义类型编写新的代码。我可以这样做,这需要在调用update()之前实例化该对象: 出于好奇,我想知道是否有一种方法可以使用Java泛型来做到这一点: 有没有办法用Java做到这一点? 问题答案: 请注意,在这种情况下将可以修复。任一(其本身包括可从获得)或本身已得到通过。
我已经阅读了很多Java8可选版本,我确实理解这个概念,但在我的代码中尝试实现它时仍然会遇到困难。 虽然我在网上搜索了一些好的例子,但我没有找到一个解释得很好的例子。 我有下一个方法: 这个简单的方法通过传递文件路径来返回文件的md5。正如您所注意到的,如果文件路径不存在(或键入错误),将抛出NoSuchFileException,该方法返回Null。 我希望使用Optional,而不是返回nul
问题内容: 我对Java没有太多的经验。我不确定这个问题是否很愚蠢,但是我需要从Firebase实时数据库中获取一个用户名,并通过此方法返回该名称。因此,我想出了如何获得该值,但是我不明白如何通过此方法返回它。最好的方法是什么? 问题答案: 这是异步Web API的经典问题。您现在无法返回尚未加载的内容。换句话说,您不能简单地创建一个全局变量并在onDataChange()方法外部使用它,因为它将
问题内容: 我有一个对象,我想知道它的返回类型是否为。 我已经检查了Javadocs,并且有一个返回Class对象的方法。问题是,如果方法无效,他们不会说返回类型是什么。 谢谢! 问题答案: 快速样本: