我知道我不能这样做:
public abstract class DTODomainTransformer<T, S> {
public abstract S transform(T);
public abstract T transform(S);
}
Run Code Online (Sandbox Code Playgroud)
因为我得到编译器投诉:
Method transform(T) has the same erasure transform(Object) as another method in type Transformer<T,S>
Run Code Online (Sandbox Code Playgroud)
据我所知,是因为这两个T和S可扩展同一类.所以这样做我可以告诉他"不,他们不一样,所以放轻松"
public interface Transformer<T extends AbstractDTO , S extends AbstractDomain> {
public abstract S transform(T object);
public abstract T transform(S object);
}
Run Code Online (Sandbox Code Playgroud)
然后,我的问题是,有没有办法告诉编译器T并S从不同的类扩展而不告诉具体哪些?我的意思是,在最后一种情况下,我已经指定了哪些类T和S(分别扩展).但是,如果我想要它更通用而不指定它们怎么办?我想告诉编译器,"嘿,编译器,T并且S不一样!它们是不同的类.我不确切地知道它们是哪个类,但我确信它们是不同的".
没有明显的方法。(尽管您可以构建一个,如下所示。)
此重载规则是由于声明重载的超类型(在本例中为接口)如何转换(通过擦除)为字节码的限制。
如果声明了泛型参数T,则在其签名中使用的方法T将生成字节码作为 的上限T,例如
class Generic<T> {
void work(T t) {}
}
Run Code Online (Sandbox Code Playgroud)
将被擦除
class Generic {
void work(Object t) {}
}
Run Code Online (Sandbox Code Playgroud)
和
class Generic<T extends Number> {
void work(T t) {}
}
Run Code Online (Sandbox Code Playgroud)
将被擦除
class Generic {
void work(Number t) {}
}
Run Code Online (Sandbox Code Playgroud)
这就是有界示例的工作原理,因为重载的擦除方式不同。
public interface Transformer {
public abstract AbstractDomain transform(AbstractDTO object);
public abstract AbstractDTO transform(AbstractDomain object);
}
Run Code Online (Sandbox Code Playgroud)
但是如果没有特定的界限,应该为重载方法生成什么样的擦除字节码?
所以你的亚型T和亚型的不同S并不重要。重要的是已知的声明边界,这些边界将被转换为超类型类的已擦除字节码。
一个可能的解决方案是使用标记接口。
interface TransformT {}
interface TransformS {}
interface Transformable extends TransformT, TransformS {}
interface Transformer<T extends TransformT, S extends TransformS>
T transform(S s);
S transform(T t);
}
abstract class AbstractDTO implements Transformable {}
abstract class AbstractDomain implements Transformable {}
new SomeTransformerImpl<AbstractDTO, AbstractDomain>()
Run Code Online (Sandbox Code Playgroud)
但我不一定建议这样做。虽然很有趣,但对我来说似乎很复杂。这取决于实际类层次结构的复杂程度。
路易斯在评论中的建议要简单得多:为方法指定不同的名称。