Java 对泛型方法中的强制转换列表感到困惑吗? A类{ 私人INTA; } 公共静态列表listStrToListT(字符串str){ 字符串[]idStrs=str.replace(“,”).split(“,”); List uids=new ArrayList(); 用于(字符串idStr:idStrs){ uids.add((T)idStr); } 返回UID; } 公共静态void main(字符串[]args){ List
请记住,Java中的泛型只是编译时的事情。在运行时,所有泛型参数都被删除为非泛型类型 从编译器的角度来看,Java 对泛型方法中的强制转换列表感到困惑吗? A类{ 私人INTA; } 公共静态列表listStrToListT(字符串str){ 字符串[]idStrs=str.replace(“,”).split(“,”); List uids=new ArrayList(); 用于(字符串idStr:idStrs){ uids.add((T)idStr); } 返回UID; } 公共静态void main(字符串[]args){ List,java,debugging,generics,collections,casting,Java,Debugging,Generics,Collections,Casting,请记住,Java中的泛型只是编译时的事情。在运行时,所有泛型参数都被删除为非泛型类型 从编译器的角度来看,listStrToListT可以返回调用者想要的任何类型的List,而不仅仅是List。您通过(1)使listStrToListT泛型和(2)将idStr强制转换为T,让编译器相信了这一事实“我确信当它运行时,这个cast会工作的。别担心,编译器!”这个cast确实有点可疑,不是吗?如果t是A 无论如何,现在List lst=liststrotlistt(“1,2,3”);编译,因为list
listStrToListT
可以返回调用者想要的任何类型的List
,而不仅仅是List
。您通过(1)使listStrToListT
泛型和(2)将idStr
强制转换为T
,让编译器相信了这一事实“我确信当它运行时,这个cast会工作的。别担心,编译器!”这个cast确实有点可疑,不是吗?如果t
是A
无论如何,现在List lst=liststrotlistt(“1,2,3”);
编译,因为liststrotlistt
“可以像前面提到的那样返回任何类型的List
”。您可以想象T
被推断为A
,并且您的强制转换liststrotlistt
在运行时会失败,但事实并非如此
现在是运行时,所有泛型类型都将被删除,使您的代码如下所示:
class A {
private int a;
}
public static <T> List<T> listStrToListT(String str) {
String[] idStrs = str.replace(" ", "").split(",");
List<T> uids = new ArrayList<>();
for (String idStr : idStrs) {
uids.add((T) idStr);
}
return uids;
}
public static void main(String[] args) {
List<A> lst = listStrToListT("1,2,3");
System.err.println(lst);
}
请注意,对T
的转换将成为对对象的转换,这在这里是多余的
打印列表只需要在每个对象上调用toString
,因此不会在那里执行强制转换
请注意,编译时的“腥味”在编译时是完全有效的。腥味强制转换成了对对象的完全有效(且冗余)强制转换!强制转换到哪里去了
强制转换只会在必要时插入。这正是泛型在Java中的工作方式。因此,让我们创建这样一种情况。假设在a
中,字段a
有一个getter,而不是打印整个列表,而是打印第一个元素的a
:
public static List listStrToListT(String str) {
String[] idStrs = str.replace(" ", "").split(",");
List uids = new ArrayList();
for (String idStr : idStrs) {
uids.add((Object)idStr);
}
return uids;
}
// main method:
List lst = listStrToListT("1,2,3");
System.out.println(lst);
否则,lst.get(0)
将属于Object
类型,并且Object
s没有getA
方法
此时您的程序将崩溃。请记住,Java中的泛型只是编译时的事情。在运行时,所有泛型参数都会被擦除为非泛型类型
从编译器的角度来看,listStrToListT
可以返回调用者想要的任何类型的List
,而不仅仅是List
。您通过(1)使listStrToListT
泛型和(2)将idStr
强制转换为T
,让编译器相信了这一事实。您的意思是“我确信当它运行时,这个cast会工作的。别担心,编译器!“这个cast确实有点可疑,不是吗?如果t
是A
无论如何,现在List lst=liststrotlistt(“1,2,3”);
编译,因为liststrotlistt
“可以像前面提到的那样返回任何类型的List
”。您可以想象T
被推断为A
,并且您的强制转换liststrotlistt
在运行时会失败,但事实并非如此
现在是运行时,所有泛型类型都将被删除,使您的代码如下所示:
class A {
private int a;
}
public static <T> List<T> listStrToListT(String str) {
String[] idStrs = str.replace(" ", "").split(",");
List<T> uids = new ArrayList<>();
for (String idStr : idStrs) {
uids.add((T) idStr);
}
return uids;
}
public static void main(String[] args) {
List<A> lst = listStrToListT("1,2,3");
System.err.println(lst);
}
请注意,对T
的转换将成为对对象的转换,这在这里是多余的
打印列表只需要在每个对象上调用toString
,因此不会在那里执行强制转换
请注意,编译时的“腥味”在编译时是完全有效的。腥味强制转换成了对对象的完全有效(且冗余)强制转换!强制转换到哪里去了
强制转换只会在必要时插入。这正是泛型在Java中的工作方式。因此,让我们创建这样一种情况。假设在a
中,字段a
有一个getter,而不是打印整个列表,而是打印第一个元素的a
:
public static List listStrToListT(String str) {
String[] idStrs = str.replace(" ", "").split(",");
List uids = new ArrayList();
for (String idStr : idStrs) {
uids.add((Object)idStr);
}
return uids;
}
// main method:
List lst = listStrToListT("1,2,3");
System.out.println(lst);
否则,lst.get(0)
将属于Object
类型,并且Object
s没有getA
方法
此时您的程序将崩溃。非常感谢您的详细解释。我对java中的泛型方法感到困惑。非常感谢您的详细解释。我对java中的泛型方法感到困惑。