简体   繁体   English

Java泛型:仅通用返回类型和通用返回类型和参数类型

[英]Java Generics: Generic Return Type Only and Generic both Return Type and Parameter Type

To start with an example,从一个例子开始,

public static <T> T method(T str){
    return (T)str;
}
// T is deduced to be a String
// This fails at compile time
Integer integer = method("Trial");
//Object obj = method("Trial"); // Old example

and,和,

public static <T> T method(String str){
    return (T)str;
}
// What type does T gets deduced to in this case?
// This compiles but gives an error at run-time.
Integer integer = method("Trial");
//Object obj = method("Trial"); // Old example

Both code snippets compile fine.两个代码片段都可以很好地编译。 Which type does T get deduced to in the second example?在第二个例子中 T 被推导出为哪种类型?

Non specified Generic Type is considered as Object so returned type is correct in both cases.未指定的通用类型被视为Object因此在两种情况下返回的类型都是正确的。 So which method is used ?那么使用哪种方法呢?
In fact, the most precise matching type will be accepted first.事实上,最精确的匹配类型将首先被接受。 In your case method(String str) as "Trial" is a String .在你的情况下method(String str) as "Trial"是一个String

// Will rename for understanding
// method(T str) => method1
// method(String str) => method2 
public static <T> T method1(T str){
    return (T)str;
}
public static <T> T method2(String str){
    return (T)str;
}
// This is your implementation
Object obj = <Object> //as undefined
    method2("Trial"); // as mentionned above

// BUT
Object obj = <Object> // as undefined
    method1(1); // as 1 is an int upperbounded to Object

// AND
Object obj = <String> 
    method2("Trial");
Object obj = <String>
    method(1); // will not compile

You should check this post for more details about overloading priorities您应该查看此帖子以获取有关重载优先级的更多详细信息

I am having a bit of a hard time following the question but anyways.我在回答这个问题时有点困难,但无论如何。

In your first example the return type is determined (inferred) by the passed in type of the method parameter (ie String in that case).在您的第一个示例中,返回类型由方法参数的传入类型确定(推断)(即在这种情况下为String )。 Consider the following example:考虑以下示例:

public static <T> T something(T something) {
    return something;
}

And two calling examples:以及两个调用示例:

String something = something("string");
Integer someOther = something("something");

The first one works OK but the second produces an error as the dynamically inferred return type is String whereas we attempt to store it an Integer variable.第一个工作正常,但第二个产生错误,因为动态推断的返回类型是String而我们尝试将其存储为Integer变量。

Now the reason why this works fine when you assign both values to an Object variable is -- as mentioned above -- the fact that this is the upper bound of both String and Integer .现在,当您将两个值都分配给一个Object变量时,这可以正常工作的原因是 - 如上所述 - 这是StringInteger的上限的事实。 In fact in you take a look a the disassembled class file using javap you'll see that your method's signature looks like this:事实上,在您使用javap查看反汇编的类文件时,您会看到您的方法的签名如下所示:

public static <T extends java.lang.Object> T something(T)

Note that all the above will effectively end up being Object types after compilation due to Java's type erasure.请注意,由于 Java 的类型擦除,上述所有内容将在编译后有效地最终成为Object类型。

On another sidenote, your example also casts the passed in parameter to T which is redundant as this is handled by compiler's ability to infer types.在另一个旁注中,您的示例还将传入的参数强制转换为T ,这是多余的,因为这是由编译器推断类型的能力处理的。

I suggest you take a look at the following:我建议您查看以下内容:

https://www.baeldung.com/java-type-erasure https://www.tutorialspoint.com/java_generics/java_generics_type_inference.htm https://www.baeldung.com/java-type-erasure https://www.tutorialspoint.com/java_generics/java_generics_type_inference.htm

Now let's take into consideration your second example:现在让我们考虑你的第二个例子:

In that one, T will effectively and up to an Object type -- as I mentioned above.在那种情况下, T将有效地成为Object类型——正如我上面提到的。 This is still the upper bound for the method but there is a caveat here.这仍然是该方法的上限,但这里有一个警告。 This method is wrong as it accepts the String object and attempts to cast it (wrong again) to the inferred type.此方法是错误的,因为它接受String对象并尝试将其(再次错误)转换为推断类型。

So for example I can do this (which compiles OK) but produces a ClassCastException on runtime:因此,例如我可以这样做(编译正常)但在运行时产生ClassCastException

public static <T> T something2(String something) {
    return (T) something;
}

and this call:这个电话:

Integer somethingOther = something2("sas");

Now as mentioned above the reason why this works when assigning to Object is that it is the parent classes of String and everything else.现在如上所述,在分配给Object时这样做的原因是它是String和其他所有东西的父类。

The first function in your case has both data type of parameter and return type of function as T , which means both of them can be of any type.您的情况下的第一个函数具有参数的数据类型和函数的返回类型为T ,这意味着它们都可以是任何类型。 They can be string, integer, float, character, array, or anything else.它们可以是字符串、整数、浮点数、字符、数组或其他任何东西。 The scope of this T type is restricted to this particular function only.T类型的范围仅限于此特定功能。

The second function has a data type of parameter as String , while the return type is T , meaning that only String type of values can be passed to this function.第二个函数的参数数据类型为String ,而返回类型为T ,这意味着只能将 String 类型的值传递给该函数。

For example,例如,

public static <T> T func1 (T var)
{
     return var;
}

The above function can have a = func1("String") or b = func1(2) or anything else.上面的函数可以有a = func1("String")b = func1(2)或其他任何东西。 a will be of type String , and b will be of type int . a 的类型为String , b 的类型为int On the other hand,另一方面,

public static <T> T func2 (String var)
{
     return var;
}

will return an error on func2(2) .将在func2(2)上返回错误。

Refer to Oracle Docs to get a detailed insight into Generic Methods.请参阅Oracle 文档以详细了解泛型方法。

Edit to Comment : When a function is being called, the Java compiler automatically infers the type of the parameter from the method arguments.编辑评论:当一个函数被调用时,Java 编译器会自动从方法参数中推断参数的类型。 When I invoke func1() in my example, I write func1("ABC") .当我在示例中调用func1()时,我写的是func1("ABC") The Java compiler is intelligent enough to now understand the T type of the argument is String. Java 编译器足够智能,现在可以理解参数的T类型是 String。 Similarly, I return a String type from func1 , so the compiler will now know that the return type has to be String.类似地,我从func1返回一个 String 类型,所以编译器现在知道返回类型必须是 String。

You can also go through https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html to study more.你也可以通过https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html来学习更多。

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

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