简体   繁体   English

编译器如何推断Java泛型中的类型

[英]how compiler infers the type in java generics

I have generic method which looks something like this. 我有看起来像这样的通用方法。

public static <T> T addAndReturn(T element, Collection<T> collection){
    collection.add(element);
    return element;
}

When I call 当我打电话

String stringElement = "stringElement";
List<Object> objectList = new ArrayList<Object>();
Object theElement = addAndReturn(stringElement, objectList); 

It infers the type as object. 它将类型推断为对象。

When I call 当我打电话

Object objectElement = new Object();
List<String> stringList = new ArrayList<String>();
Object theElement = addAndReturn(objectElement, stringList);

the compiler reports error. 编译器报告错误。

What are the rules behind this? 这背后的规则是什么?

In the first case, you are passing a List<Object> to the Collection<T> so T must be an Object type. 在第一种情况下,您要将List<Object>传递给Collection<T>因此T必须是Object类型。 A String stringElement is a sub-class of Object so this is allowed. String stringElementObject的子类,因此允许这样做。

In the second case, you are passing a List<String> to the Collection<T> so T can only be String . 在第二种情况下,您要将List<String>传递给Collection<T>因此T只能是String As Object objectElement is not a String type this is not allowed. 由于Object objectElement不是String类型,因此不允许这样做。

You can't add an Object to a List<String> which seems reasonable. 您不能将Object添加到似乎合理的List<String>中。

Generics can be difficult to grasp, I recommend you read up on it carefully. 泛型可能很难掌握,我建议您仔细阅读。

In your example, you have a type T which can be any one type. 在您的示例中,您有一个T类型,它可以是任何一种类型。 This type is "generic" in that it conforms to what type is put into it. 此类型是“泛型”的,因为它符合放入其中的类型。 So, when you pass an ArrayList<String> as the Collection<T> parameter, T becomes String in that instance. 因此,当您将ArrayList<String>作为Collection<T>参数传递时, T在该实例中成为String Therefore, the return type of the method becomes String . 因此,该方法的返回类型为String

Generics work on principle of Type inference. 泛型根据类型推断原理工作。 The compiler checks the type which from the generic class. 编译器检查泛型类中的类型。 Once the type is determined the compiler performs compile time type checking to make sure that all the type which are passed are correct. 确定类型后,编译器将执行编译时类型检查,以确保传递的所有类型都是正确的。 Generics also has type erasure at runtime but that is a different thing and we can skip it for this discussion. 泛型在运行时也具有类型擦除,但这是另一回事,在本讨论中我们可以跳过它。

To apply this principle on your questions: In the first case you are creating an object of type String which can be easily added to a ArrayList of type Object as String is a sub class of Object. 在您的问题上应用此原理:在第一种情况下,您将创建一个String类型的对象,由于String是Object的子类,因此可以轻松地将其添加到Object类型的ArrayList中。

For the second example you are now doing the exact opposite. 对于第二个示例,您现在正好相反。 You are trying to save a Object class object in a reference of String class which is not allowed. 您正在尝试将Object类对象保存在不允许的String类的引用中。

Thus if you notice the rules are exactly same even as that of a non generic code. 因此,即使您注意到规则,也与非通用代码完全相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM