Java泛型:仅泛型返回类型,泛型同时返回类型和参数类型



从一个例子开始,

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

和,

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

两个代码段都编译良好。在第二个例子中,T被推导为哪种类型?

未指定的泛型类型被视为Object,因此返回的类型在这两种情况下都是正确的。那么使用哪种方法呢
事实上,最精确的匹配类型将首先被接受。在您的情况下,method(String str)作为"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

你应该查看这篇文章,了解更多关于过载优先级的详细信息

我很难回答这个问题,但无论如何。

在您的第一个示例中,返回类型由方法参数的传入类型确定(推断((即,在这种情况下为String(。考虑以下示例:

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

还有两个调用示例:

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

第一个工作正常,但第二个会产生错误,因为动态推断的返回类型是String,而我们试图将其存储为Integer变量。

现在,当您将两个值都分配给Object变量时,这种方法之所以能正常工作,是因为——如上所述——这是StringInteger的上界。事实上,在使用javap查看已分解的类文件时,您会发现方法的签名如下所示:

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

注意,由于Java的类型擦除,上述所有类型在编译后都将有效地成为Object类型。

另一方面,您的示例还将传入的参数强制转换为T,即冗余,因为这是由编译器推断类型的能力来处理的。

我建议你看看以下内容:

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

现在让我们考虑一下您的第二个例子:

在这个例子中,T将有效地达到Object类型——正如我上面提到的。这仍然是该方法的上限,但这里有一个警告。此方法是错误的,因为它接受String对象并试图将其强制转换(再次错误(为推断的类型。

例如,我可以这样做(编译正常(,但在运行时生成ClassCastException

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

这个电话:

Integer somethingOther = something2("sas");

如上所述,当分配给Object时,这之所以有效,是因为它是String和其他所有类的父类。

您案例中的第一个函数同时具有参数的数据类型和函数的返回类型T,这意味着它们都可以是任何类型。它们可以是字符串、整数、浮点、字符、数组或任何其他类型。此T类型的范围仅限于此特定函数。

第二个函数的数据类型参数为String,而返回类型为T,这意味着只有String类型的值可以传递给该函数。

例如,

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

上述函数可以具有a = func1("String")b = func1(2)或其他任何函数。a将是类型String并且b将是类型int。另一方面,

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

将在CCD_ 28上返回错误。

请参阅Oracle文档以详细了解泛型方法。

Edit to Comment:当调用函数时,Java编译器会自动从方法参数中推断出参数的类型。当我在示例中调用func1()时,我会编写func1("ABC")。Java编译器足够聪明,现在可以理解参数的T类型是String。类似地,我从func1返回一个String类型,所以编译器现在知道返回类型必须是String。

你也可以通过https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html学习更多。

最新更新