如果我使用原始类型作为参数调用泛型方法,将使用什么类型参数?
我只是好奇将原始数据传递给 T 类型时生成的推断 T 类型是什么。它确实可以编译,但有一个警告。
public class GenericMethodInference {
static <T> void test5(List<T t>){} // clause (5)
public static void main(String [] args) {
List e = new ArrayList<Integer>();
test5(e); // clause (6) // ok but with warning.
}
I'm just curious what's the generated inferred T type when passing a raw to a T type. It does compile but with a warning.
public class GenericMethodInference {
static <T> void test5(List<T t>){} // clause (5)
public static void main(String [] args) {
List e = new ArrayList<Integer>();
test5(e); // clause (6) // ok but with warning.
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
将原始类型分配给泛型类型将假定没有泛型约束(默认为对象),但会删除任何可能存在的编译时类型安全保证。
这里对类型擦除存在一个根本性的误解。原始类型是泛型类型的最终结果。您指定了
List
,编译器会根据该类型信息进行验证,然后删除其中的
部分,根据需要从针对该类型的操作中插入对 Integer 的强制转换列表的原始类型。这意味着这两个检索操作完全相同。
例如,以下内容是合法的。这只会发出警告(而不是导致编译器错误或运行时错误),因为我们正在对 Object 进行操作,并且仍在所包含类型的适当范围内。
它将打印出 5。如果您尝试做这样的事情,类型系统会有所帮助。
它会给你一个编译器错误,指出存在类型不匹配。然而,直接使用原始类型将抛弃所有类型安全性,并且仅依赖于您对应该使用的正确类型的判断。如果你做错了,这会让你很容易搬起石头砸自己的脚。
Assigning a raw type to a generic type will assume no generic constraint (which will default to Object) but remove any compile-time type safety guarantees that might otherwise have existed.
It sounds like there is a fundamental misunderstanding of type erasure here. The raw type is the end result of a generic type. You specified
List<Integer>
, the compiler verifies against that type information and then removes the<Integer>
portion of that, inserting casts to Integer as appropriate from actions against the raw type of List.That means that these two retrieval operations are exactly the same.
For example, the following is legal. This only gives a warning (instead of causing a compiler error or runtime error) because we're acting on Object and are still within the appropriate bounds of the contained type.
It will print out 5. Where the type system helps is if you try to do something like this.
It will give you a compiler error stating that there is a type mismatch. Using the raw type directly, however, will throw all of that type safety away and rely solely on your judgement for the correct types that should be used. This allows you to easily shoot yourself in the foot if you get it wrong.
这样做是为了向后兼容。在泛型之前,
当泛型被引入时,他们需要泛化
List
和诸如test5()
之类的方法,而不询问诸如test5(e)
之类的所有用法被重写和重新编译。因此test5(e)
必须仍然有效。这是通过放宽类型推断规则和方法签名匹配规则来实现的。
推论:
List << List
这不能在子类型意义上保持;然而推理规则只是忽略它;T
没有约束,只是选择为Object
方法签名:
List e
不是方法参数类型的子类型List< ;Object>
,但是“方法调用转换”可以接受,它允许从List
到List
的“未经检查的转换”; “未经检查的转换”会触发强制编译器警告。这仅具有历史意义;今天没有程序员应该关心。由于显然
List
不可能成为List
的子类型,无论T
是什么,我们实际上应该将其视为错误,并且永远不要编写这样的代码(即使它可以编译)。列表 e
可以工作。This is done for backward compatibility. Before generics,
When generics was introduced, they need to generify
List
and methods liketest5()
, without asking all usages liketest5(e)
to be rewritten and recompiled. Sotest5(e)
must still be valid.This is achieved by relaxing type inference rules and method signature matching rules.
Inference:
List << List<T>
this can't hold in the subtyping sense; however inference rules just ignore it;T
has no constraints, and simply picked to beObject
Method signature:
List e
is is not subtype of the method parameter typeList<Object>
, however it is acceptable by "method invocation conversion", which allows "unchecked conversion" fromList
toList<Whatever>
; the "unchecked conversion" triggers the mandatory compiler warning.This is only of historical interest; no programmer today should care. Since obviously there's no way for
List
to be a subtype ofList<T>
whateverT
is, we should practically treat it as error, and never write code like that (even though it compiles). AList<?> e
would work.我想说推断的类型是 Object
I would say that the inferred type would be Object
这确认了推断的类型是 Object 类型。
This confirms that the type inferred is Object type.
T 是一个通用的。它可以接受任何对象。
T is a generic one. It can accept any object.