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

Can explicit type parameters redundant?

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

class MyObject<IdType> {

    @Setter
    @Getter
    private IdType id;
}

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

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

< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
    object.copyIdTo(this);
}

我刚刚意识到我可以做到这一点。

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

void copyIdFrom(MyObject<? extends IdType> object) {
    object.copyIdTo(this);
}

这两组方法是等价的吗?更喜欢哪种方式(或风格)?

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

由于您的示例方法 return void 使方法通用化并没有真正的好处。对于您的方法唯一重要的是参数是 MyObject<...>——除此之外,实际类型是无意义的。添加使参数类型更具体的功能不会为方法的实现添加任何内容,也不会为调用者做任何事情。换句话说,它是无关紧要的 "fluff".

因此,对于您的示例,我会说更喜欢 non-generic 选项。它更干净、更直接。


但是,如果您的方法 return 将给定的参数返回给调用者,那么使该方法通用可能会很有用;它将允许您将 return 类型声明为 T。这为调用者打开了可能性,例如方法链接或调用方法 "inside" 另一个方法调用,所有这些都基于作为参数传递的特定类型。核心库中的一个例子是 Objects.requireNonNull(T).

@Thilo 在评论中提到了另一个使方法通用的好例子:

Another case would be if your method takes multiple arguments. Then you can introduce a T to make sure those two arguments have the same type (instead of two distinct types that happen to [fulfill] the constraints individually).

是的,它们是等价的。两组方法都声明相同的东西——方法参数必须是 MyObject<> 类型或兼容的子类型(子类)。

以这种方式声明T的唯一原因是如果您需要在其他地方引用T,例如方法的return类型,或者如果您有多个相同类型的参数,或在方法体内。

我总是更喜欢更短、更简单、更清晰的版本,尖括号更少,以免伤眼:)