显式类型参数可以冗余吗?

Jin*_*won 6 java generics bounded-wildcard

我有一个带有类型参数的类。

class MyObject<IdType> {

    @Setter
    @Getter
    private IdType id;
}
Run Code Online (Sandbox Code Playgroud)

我想我可以添加一些方便的方法,所以我做到了。

<T extends MyObject<? super IdType>> void copyIdTo(T object) {
    object.setId(getId());
}

< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
    object.copyIdTo(this);
}
Run Code Online (Sandbox Code Playgroud)

我只是意识到我可以做到这一点。

void copyIdTo(MyObject<? super IdType> object) {
    object.setId(getId());
}

void copyIdFrom(MyObject<? extends IdType> object) {
    object.copyIdTo(this);
}
Run Code Online (Sandbox Code Playgroud)

这两套方法是否等效?首选哪种方式(或样式)?

Sla*_*law 5

在您的情况下,这两种方法实际上是等效的。它们都将参数的类型限制为MyObject<...>或子类型。

由于您的示例方法返回了,void因此使该方法通用没有真正的好处。对于您的方法,唯一重要的事情是参数是一个- MyObject<...>除了实数类型没有意义之外。添加使参数的类型更具体的功能不会对方法的实现产生任何影响,对调用者也不会产生任何影响。换句话说,它是无关紧要的“绒毛”。

因此,对于您的示例,我想说一下非通用选项。更干净,更直接。


但是,如果您的方法将给定的参数返回给调用者,则使该方法通用可以证明是有用的。它将允许您将返回类型声明为T。这为调用者打开了可能性,例如方法链接或在另一个方法调用“内部”调用方法,所有这些都基于作为参数传递的特定类型。核心库中的示例是Objects.requireNonNull(T)

@Thilo在注释中提到了使方法通用的另一个好案例:

另一种情况是您的方法采用多个参数。然后,您可以引入a T以确保这两个参数具有相同的类型(而不是碰巧分别[满足]约束的两个不同类型)。

如果它是单个参数,例如,也可以将其应用Collection<? extends T>

  • 另一种情况是您的方法采用多个参数。然后,您可以引入“ T”以确保这两个参数具有相同的类型(而不是碰巧分别满足约束的两个不同的类型)。 (2认同)