在匿名类中捕获类型参数

问题描述 投票:0回答:1

我想动态创建一个类,它实现给定的接口并绑定该接口的类型参数。这是我的界面定义:

public interface Container<T> {}

我最初的想法是为此使用匿名类,如下所示:

public <T> Class<?> getContainerImplementationForType(Class<T> type) {
    return new Container<T> { ... }.getClass();
}

但是,如果我检查返回的类对象,此实现的类型参数

T
不会绑定到作为
type
传递的任何内容,但它仍然只是一个类型变量
T

我有一个模糊的想法为什么这不起作用,但我想知道如何实现我的目标。使用 ASM、ByteBuddy 或类似方法手动创建类型是唯一的方法吗?我认为动态代理也不起作用,因为在获取代理类时我找不到为

Container
指定类型参数边界的方法。

java generics type-parameter
1个回答
0
投票

正如javadoc所述,getGenericInterfaces()仅从源代码返回static类型值:

如果超级接口是参数化类型,则为其返回的 Type 对象必须准确反映源代码中使用的实际类型参数。

...而在源代码中它是 dynamic

T

换句话说:在 Java 中,泛型类型信息不会作为对象实例的一部分存储在 RAM 中,反射真正所做的主要只是提供来自字节码的静态信息(例如来自

*.class
文件)。因此,为了能够获取传递给超类/实现的接口的类型参数的值,必须将此信息硬编码到您将调用的getGenericInterfaces()/
getGenericSuperclass()
子类/实现器的字节码中。 OTOH,在你的源代码中只有 one 实现者,他是 generic,所以你将只有 1 个类文件,没有任何静态类型信息(因为它是通用的)。如前所述,当创建 
Container
实例时,它不会保留对用作
T
参数的类的任何引用(您只能在引用
type
参数的匿名类中创建自定义字段/方法)
)。

如果您必须使用反射来获取类型值,那么唯一的解决方案正是您所指出的:每次调用

getContainerImplementationForType(type)

 时动态创建一个字节码(动态 ByteBuddy/ASM 类)来存储给定的类型值。 
如前所述,反射的替代方法可能是向您的匿名类(以及
getContainerImplementationForType(type)
 接口,如果它在您的控制之下)添加像 
Container
 这样的方法,它将返回 
getContainerType()
type
 参数。

© www.soinside.com 2019 - 2024. All rights reserved.