具有相同通用参数的重载方法?

jsc*_*man 9 java generics

我知道我不能这样做:

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)

据我所知,是因为这两个TS可扩展同一类.所以这样做我可以告诉他"不,他们不一样,所以放轻松"

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)

然后,我的问题是,有没有办法告诉编译器TS从不同的类扩展而不告诉具体哪些?我的意思是,在最后一种情况下,我已经指定了哪些类TS(分别扩展).但是,如果我想要它更通用而不指定它们怎么办?我想告诉编译器,"嘿,编译器,T并且S不一样!它们是不同的类.我不确切地知道它们是哪个类,但我确信它们是不同的".

Rad*_*def 3

没有明显的方法。(尽管您可以构建一个,如下所示。)

此重载规则是由于声明重载的超类型(在本例中为接口)如何转换(通过擦除)为字节码的限制。

如果声明了泛型参数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)

但我不一定建议这样做。虽然很有趣,但对我来说似乎很复杂。这取决于实际类层次结构的复杂程度。

路易斯在评论中的建议要简单得多:为方法指定不同的名称。