我知道我不能这样做:
public abstract class DTODomainTransformer<T, S> {
public abstract S transform(T);
public abstract T transform(S);
}
因为我收到编译器投诉:
Method transform(T) has the same erasure transform(Object) as another method in type Transformer<T,S>
我理解这是因为T
和S
都可以扩展同一个类。所以这样做我可以告诉他“不,他们不一样,所以放轻松”
public interface Transformer<T extends AbstractDTO , S extends AbstractDomain> {
public abstract S transform(T object);
public abstract T transform(S object);
}
然后,我的问题是,有没有办法告诉编译器T
和S
从不同的类扩展而不告诉具体哪些?我的意思是,在最后一种情况下,我已经指定了哪些类必须是T
和S
(分别扩展)。但是,如果我想要它更通用而不指定它们怎么办?我想告诉编译器,“嘿,编译器,T
和S
不一样!它们是不同的类。我不确切地知道它们是哪个类,但我是确定它们不同“。
答案 0 :(得分:3)
这不是一个明显的方法。 (虽然你可以建立一个,如下所示。)
此重载规则是由于声明重载的超类型(在本例中为接口)如何(通过擦除)转换为字节码的限制。
如果通用参数声明为T
,则在其签名中使用T
的方法将生成字节码作为T
的上限,例如
class Generic<T> {
void work(T t) {}
}
将被删除
class Generic {
void work(Object t) {}
}
和
class Generic<T extends Number> {
void work(T t) {}
}
将被删除
class Generic {
void work(Number t) {}
}
这是有界示例的工作方式,因为重载的擦除方式不同。
public interface Transformer {
public abstract AbstractDomain transform(AbstractDTO object);
public abstract AbstractDTO transform(AbstractDomain object);
}
但是没有特定的界限,应该为重载的方法生成什么擦除字节码?
因此,您的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>()
但我不一定建议这样做。虽然很有趣,但对我来说似乎很精致。这取决于实际类层次结构的复杂程度。
What Louis suggested in the comments要简单得多:给方法命名不同。