Java泛型类型擦除方法签名问题
给定以下假设的类型层次结构:Java泛型类型擦除方法签名问题,java,class,generics,type-erasure,Java,Class,Generics,Type Erasure,给定以下假设的类型层次结构: BaseElement + StringElement + .... + .... + BooleanElement + .... + .... + ... 我有一个如下形式的类接口: IBaseElementService createElementService(Class<? extends BaseElement> element); IBooleanElementServ
BaseElement
+ StringElement
+ ....
+ ....
+ BooleanElement
+ ....
+ ....
+ ...
我有一个如下形式的类接口:
IBaseElementService createElementService(Class<? extends BaseElement> element);
IBooleanElementService createElementService(Class<? extends BooleanElement> element);
IBaseElementService createElementService(类重命名了方法。(但为什么有两个方法?也许第一个应该是唯一的公共方法;它可以检查类类型并转发到第二个BooleanElement方法)
根据当前的语言规范,您的两个方法应该可以编译。请参阅。我在Java 7中听说这两个方法不能再共存了。不确定其原理。您可以向IBaseElementService
添加泛型
在creaseElementService内部,您需要执行一些检查以返回正确的elementservice
IBaseElementService<T> createElementService(Class<T extends BaseElement> elementClass) {
if (elementClass.equals(BooleanElement.class))
return new IBooleanElementService();
return new IBaseElementService();
}
public class IBooleanElementService implements IBaseElementService<BooleanElement> { ... }
public class IBaseElementService implements IBaseElementService<BaseElement> { ... }
IBaseElementService createElementService(类elementClass){
if(elementClass.equals(BooleanElement.class))
返回新的ibooleElementService();
返回新的IBaseElementService();
}
公共类IBooleanElementService实现IBaseElementService{…}
公共类IBaseElementService实现IBaseElementService{…}
在VM级别,方法签名也包括返回类型。因此,您的两个方法都有签名
createElementService(类):ibooleElementService
和createElementService(类):IBaseElementService
。只要编译器知道调用哪个方法,它就可以在字节码中调用正确的方法。我想这就是Eclipse 3.4所做的
在Java语言级别上,方法只根据名称和参数类型进行区分(ClassA类似的问题和答案:eclipse 3.4编译这个cade真的很奇怪!@salman.mirghasemi,引用的问题是不相似的。@Patrick理解为什么这个代码不起作用,并问eclipse 3.4如何编译它以及如何修改代码。问你提到的问题的人没有回答根本不理解擦除。可能与此错误报告有关。如果Eclipse 3.4编译它,这意味着存在错误,并且在Eclipse 3.6中已修复。编译器在各种重载方法中进行选择时应忽略返回类型。返回类型不是签名的一部分,因为调用方可能忽略返回值,例如调用方法int foo(inti)作为foo(5)。所以你的评论很有趣,但似乎不准确……虽然我没有更好的解释…@AlexR:eclipse3.4不是根据返回类型选择的,而是根据参数的类型参数选择的——返回类型仅用于VM区分。但是正如你所说(我说过),这在这里是错误的。我考虑过这种可能性,但更倾向于重命名方法,而不是使用反射机制。无论如何,谢谢!没错,我应该提到,如果两个接口之间存在显著差异,重命名是最好的方法。如果两个接口(几乎)相同,则此解决方案效果最好。
IBaseElementService<T> createElementService(Class<T extends BaseElement> elementClass) {
if (elementClass.equals(BooleanElement.class))
return new IBooleanElementService();
return new IBaseElementService();
}
public class IBooleanElementService implements IBaseElementService<BooleanElement> { ... }
public class IBaseElementService implements IBaseElementService<BaseElement> { ... }