java泛型运行时类型
有一个非常实用的方法来确定Java类类型参数的运行时类。它超越了快速版本的几个步骤:java泛型运行时类型,java,generics,reflection,runtime,Java,Generics,Reflection,Runtime,有一个非常实用的方法来确定Java类类型参数的运行时类。它超越了快速版本的几个步骤: ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass(); Class<?> c = (Class<?>) pt.getActualTypeArguments()[0] ParameteredType pt=(ParameteredType)this.getClass().getGe
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
Class<?> c = (Class<?>) pt.getActualTypeArguments()[0]
ParameteredType pt=(ParameteredType)this.getClass().getGenericSuperclass();
类c=(类)pt.getActualTypeArguments()[0]
对于从抽象参数化父类(class Foo extends Bar
)继承的参数化子类,或者参数化抽象类(new Foo(){}
)的匿名实例,并用具体类型实例化的参数化子类,这两种方法都很有魅力
我失败的地方是尝试对通过类型参数实例化的其他对象执行相同的操作。相关类对象包括:
public class Foo {/* code omitted for brevity */}
public class MyFoo extends Foo {/* code omitted for brevity */}
public abstract class AbstractLoader<T extends Foo> {/* code omitted for brevity */}
public abstract class AbstractReader<T extends Foo> {/* code omitted for brevity */}
public class MyReader<T extends Foo> extends AbstractReader<T> {/* code omitted for brevity */}
public class Loader<T extends Foo> extends AbstractLoader<T> {
/* code omitted for brevity */
public MyReader<T> getReader() {
// Parameterized type "T" doesn't seem to carry through here
return new MyReader<T>();
}
}
公共类Foo{/*为简洁起见省略了代码*/}
公共类MyFoo扩展Foo{/*为简洁起见省略了代码*/}
公共抽象类AbstractLoader{/*为简洁起见省略了代码*/}
公共抽象类AbstractReader{/*为简洁起见省略了代码*/}
公共类MyReader扩展AbstractReader{/*为简洁起见省略了代码*/}
公共类加载器扩展了AbstractLoader{
/*为简洁起见省略了代码*/
公共MyReader getReader(){
//参数化类型“T”在这里似乎不适用
返回新的MyReader();
}
}
示例代码:
static void main(String... s) {
Loader<MyFoo> loader = new Loader<>(); // new Loader<MyFoo>() for Java < 1.7
MyReader<MyFoo> = loader.getReader();
ParameterizedType pt = (ParameterizedType)loader.getClass().getGenericSuperclass();
System.out.println("LoaderType = " + pt.getActualTypeArguments()[0]);
// Prints: LoaderType = MyFoo
pt = (ParameterizedType)reader.getClass().getGenericSuperclass();
System.out.println("ReaderType = " + pt.getActualTypeArguments()[0]);
// Prints: ReaderType = T
}
static void main(字符串…s){
Loader=new Loader();//Java<1.7的new Loader()
MyReader=loader.getReader();
ParameteredType pt=(ParameteredType)loader.getClass().getGenericSuperclass();
System.out.println(“LoaderType=“+pt.getActualTypeArguments()[0]);
//打印:LoaderType=MyFoo
pt=(ParameterizedType)reader.getClass().getGenericSuperclass();
System.out.println(“ReaderType=“+pt.getActualTypeArguments()[0]);
//打印:ReaderType=T
}
直觉告诉我这“应该”在某种程度上是可能的,但我似乎无法找到正确的答案。OTOH,这可能是另一个由于类型擦除而“无法执行”的示例。您找不到对象的类型参数-它在运行时被擦除
如果可以,则
加载程序加载程序0
、加载程序加载程序1
和加载程序加载程序2
将给出不同的结果。这种差异必须在运行时以某种方式表示:要么直接在对象中,要么通过引用不同的类。第一种变体要求每个实例都有额外的内存,因此被认为是不合适的。第二个要求在运行时创建类,因为类加载器本身不能包含参数化类加载器的所有可能变体——它们在编译时是未知的 你完全误解了什么。newloader()之间没有区别代码>,新加载程序()代码>,和新加载器()代码>,等等。要把他们分开是不可能的。现在就把这个想法从你的脑子里弄出来
如果我们创建一个类,那么关于该类的声明中的类型(包括泛型),包括超类、方法类型、字段类型等,都存储在类文件中。可以在运行时检索此信息
因此,当您拥有newfoo(){}
时,它会创建某个类(匿名类)的实例,该类使用特定的类型参数扩展泛型类型。它类似于:
class SomeAnonymousClass extends Foo<Bar> {
}
new SomeAnonymousClass()
class SomeAnonymousClass扩展了Foo{
}
新的SomeAnonymousClass()
事实上,Foo
在编译时被硬编码为此类的超类,这在运行时是可检索的
但是你的代码没有做这种事情。您没有创建加载程序的任何子类
,请发布一个。您现有的示例不完整,并且存在编译错误。特别是,loader
的泛型类型不应该是可修改的-您需要执行newloader(){}
;很抱歉。我尝试了new Loader()
和new Loader您的示例仍然错误-它打印“LoaderType=T ReaderType=T”(在修复reader
声明之后)。请确保你的问题的前提是有意义的,或者删除它。