提问人:theutonium.18 提问时间:10/19/2023 更新时间:10/19/2023 访问量:104
== 在泛型类型中的行为
Behaviour of == with Generic types
问:
请考虑以下代码片段:
List<Object> objs1 = Arrays.asList("one", "two");
List<String> strs1 = (List<String>)(List<?>)objs1;
assert strs1 == objs1; //compile error
既然只比较对象身份 - 为什么当它只是强制转换的问题时,它会产生编译错误。==
在考虑以下片段时 - 这里的断言不会失败:
String str = "this is it";
Object oo = str;
assert str == oo; //asserts true
再说一遍 - 我们正在做同样的事情,但它工作正常。
- 为什么即使所持有的对象相同,运算符也会根据持有对象的引用类型行事?
==
答:
0赞
pdem
10/19/2023
#1
由于类型擦除,您可以在运行时设置和比较不兼容的引用。
泛型出现在 Java 5(此时命名为 1.5)中,在后台,JVM 仍然设法在运行时使用。
编译器说的是,即使你操作相同的引用,也无法与之相提并论。
事实上,从语义上讲,a 不能包含 a,所以你陷入了一个不合逻辑的境地List<Object>
List<Object>
List<String>
List<Object>
List<String>
事实上,“边缘情况”是你用双重强制转换
欺骗了编译器,而不是不应该分配的。在第二行,编译器允许您使用不应该可能的强制转换:List<String> strs = (List<String>)(List<?>)objs;
List<Object>
List<String>
List<Object> objs = Arrays.asList("one", "two");
List<String> strs = (List<String>)(List<?>)objs;// incompatible type affectation with no errors at runtime because of type erasure
// this compares 2 differents type that the compiler will refuse System.out.println(strs == objs);
如果你想要一个两者的超类型,它必须是,那么代码对于编译器和运行时都是正确的。List<String>
List<Object>
List<? extends Object>
这有效且语义正确
List<? extends Object> objs = Arrays.asList("one", "two");
List<String> strs = (List<String>)(List<?>)objs;
System.out.println(strs == objs);
现在说到类型擦除,它可能会导致类似的问题:
List<? extends Object> objs = Arrays.asList("one", "two");
List<Integer> ints = Arrays.asList((Integer.valueOf(1),Integer.valueOf(2));
List<String> strs = (List<String>)objs; // this shouldn't work on runtime but does because of type erasure
System.out.println(strs == objs);
在这里,我可以影响 List of String 变量中的 List of Integer,并且由于类型擦除,我没有得到 classCastException。如果类型保护是完美的,我应该不能 1.将 A 转换为 2。在运行时影响此值。List<Integer>
List<String>
评论
0赞
pdem
10/19/2023
@user85421 你是对的,类型推断也使用左侧操作数,在你的情况下,对象不编译。我会进行修改List<Object> objs = Arrays.<String>asList("one", "two");
0赞
pdem
10/19/2023
@user85421感谢已经完成,我(错误地)期望 Arrays.asList(T) 在 T 类型作为参数传递时始终返回 List<T>。
0赞
user85421
10/19/2023
请记住,A 也是一个 - 所以可以两者兼而有之 - 通常编译器会采用更具体的类型,但这不是一个选项,因为赋值会失败String
Object
T
0赞
pdem
10/19/2023
@User85421 这就是陷阱 String 是 Object,但 List String 不是 List Object,正如我所说,它的列表是 ?extends 对象是 String 列表的超类 参见泛型中 extends 和 super 的用法,这是一个复杂的注释问题:stackoverflow.com/questions/4343202/...
0赞
pdem
10/20/2023
是的,我明白这一点,我更新了我的答案,明确表示这种演员阵容不应该是不可能的,这就是问题的根源。编译器拒绝比较不兼容的类型,这不是问题。List<String> strs = (List<String>)(List<?>)objs
评论
if
assert
if( strs1 == objs1 ) ; //compile error
str == oo
可能有效,因为 String IS_A Object(String extends Object)。但 a 不是 a ( 不是 的子类型List<String>
List<Object>
List<String>
List<Object>
)