Java 什么是通用方法,如何<;T>;在这种情况下有约束力吗?
前言:我了解泛型以及它们是如何在类级别声明的(例如Java 什么是通用方法,如何<;T>;在这种情况下有约束力吗?,java,generics,Java,Generics,前言:我了解泛型以及它们是如何在类级别声明的(例如类MyClass),但我从未见过它在静态方法级别声明,并且没有任何显式绑定(例如类MySubclass扩展MyClass) 我在正在开发的一个应用程序中发现了这个代码片段(这部分不是我写的)。我从未见过这样声明的方法未在类中的任何其他位置定义Intent.getExtras().get()返回一个对象,该对象实际上可能是字符串,布尔值…等等 private static <T> T getItemExtra(final Intent
类MyClass
),但我从未见过它在静态方法级别声明,并且没有任何显式绑定(例如类MySubclass扩展MyClass
)
我在正在开发的一个应用程序中发现了这个代码片段(这部分不是我写的)。我从未见过这样声明的方法<代码>未在类中的任何其他位置定义Intent.getExtras().get()
返回一个对象
,该对象实际上可能是字符串
,布尔值
…等等
private static <T> T getItemExtra(final Intent intent, final String extraName) {
T item = null;
if(intent != null && intent.getExtras() != null) {
item = (T) intent.getExtras().get(extraName);
}
return item;
}
JVM如何知道用于
的类型?(是的,此方法编译并执行成功)。T
是一种类型接口。在本例中,返回类型是一个类型接口,因此只要说getItemExtra(…)
将返回一个String
或Uri
就足以让编译器知道此方法将返回该对象。尽管如此,这并不是最好的类型接口示例,所以这里有一个更简单的示例
ArrayList
是使用类型接口实现的,除非您告诉ArrayList它将包含什么对象类型,除非他们使用的不是T
,而是E
,这很好,因为只要您在整个实现过程中使用相同的字符,字符就是任意的
以下是一段来自实际案例的相关片段:
公共类ArrayList扩展了AbstractList
实现列表、随机访问、可克隆、java.io.Serializable
{
因此,如果您声明
ArrayList
,编译器将在编译时用String
替换E
。ArrayList
也是如此,它将在整个实现过程中用YourCustomObject
替换E
。这在Java中被称为a。T-in表示一种类型,您可以使用通常指定。然后,编译器将用您替换的类型替换T的任何实例。如果不指定,编译器将尝试从可用信息推断正确的类型
您应该阅读Java教程以获得更深入的解释
JVM如何知道用于
的类型
基本答案是,它不是。在Java中,泛型类型由类型检查器在编译时使用,但在程序实际运行时从程序中删除。例如,在项=(t)intent.getExtras().get(extraName)中转换为t
在运行时实际上不做任何事情:它实际上是对对象的强制转换,无论调用方希望t
是什么类型。(这与对正常类型的强制转换不同,如String
,如果您尝试强制转换错误的内容,程序将立即失败并出现异常。)
不需要检查就可以强制转换到T
,这是Java类型系统中的一个漏洞,可能会导致奇怪的类强制转换异常
String s = getItemExtra(...);
s.toLowerCase();
但是getItemExtra
不返回字符串,那么第二行会出现异常,告诉您s
不是字符串,即使该行上没有强制转换。因此,当Java编译器看到对t
的强制转换时,它会生成一个未经检查的强制转换警告,告诉您它无法检查您的typecast是合法的,您可能会遇到这样的问题。事实上,您在第一行得到一个异常,因为第一行变成了String s=(String)getItemExtra(…)
。这不是另一个问题的重复。@Nilish我问的是泛型方法,不是泛型类。我已经更新了这个问题以反映这一点。@OliverGondža是的,我必须承认这是重复的。我的问题是关于泛型方法,不是泛型类。这是同一件事,一件事,你在构造函数中指定,另一件你在调用该方法。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
String s = getItemExtra(...);
s.toLowerCase();