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

时间:2015-03-19 20:04:00

标签: java generics

我知道我不能这样做:

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>

我理解这是因为TS都可以扩展同一个类。所以这样做我可以告诉他“不,他们不一样,所以放轻松”

public interface Transformer<T extends AbstractDTO , S extends AbstractDomain> {

    public abstract S transform(T object);

    public abstract T transform(S object);

}

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

1 个答案:

答案 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);
}

但是没有特定的界限,应该为重载的方法生成什么擦除字节码?

因此,您的TS在< 上的不同是不重要的。重要的是已知的声明边界,它被转换为超类型类的擦除字节码。


可能的解决方案可以使用标记接口。

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要简单得多:给方法命名不同。