显式类型参数可以省略吗?

6

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

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

这两组方法是否等效?哪种方式(或风格)更好?


3
如果这些方法返回void,请优先使用后者。如果它们返回参数,则使用前者可能会很有用,因为您可以返回T(例如Objects.requireNonNull)。 - Slaw
3
只要方法类型参数仅被使用一次,我更喜欢第二种方式。 - Smutje
3
只有在需要在多个地方使用 T 时才需要引入它(例如返回类型、多个方法参数或具有多个类型的泛型参数,如 Pair<T,T>)。 - Thilo
2个回答

5
在你的情况下,这两种方法实际上是等效的。它们都将参数类型限制为 MyObject<...> 或其子类型。
由于你的示例方法返回 void,所以使方法通用化并没有真正的好处。对于你的方法来说,唯一重要的事情是参数是一个 MyObject<...>——在此之外,实际类型是无意义的。添加使参数类型更具体的能力对方法的实现没有任何帮助,对调用者也没有任何作用。换句话说,它只是无关紧要的“花哨”内容。
因此,在你的示例中,我会选择非通用选项。它更加干净和直接。
但是,如果你的方法将给定的参数返回给调用者,则使方法通用化可能会很有用;它允许你声明返回类型为 T。这为调用者打开了一些可能性,例如基于传递的特定类型进行方法链接或在另一个方法调用“内部”调用该方法。核心库中的一个示例是 Objects.requireNonNull(T)
@Thilo 在评论中提到了另一个使方法通用化的好例子:
"如果你的方法接受多个参数,则可以引入一个 T 来确保这两个参数具有相同的类型(而不是两个不同的类型,恰好分别满足各自的约束条件)"

2
另一种情况是,如果您的方法需要多个参数,则可以引入一个 T 来确保这两个参数具有相同的类型(而不是两个独立的类型,它们分别满足约束条件)。 - Thilo

2
是的,它们是等效的。这两组方法声明了相同的内容 - 方法参数必须是类型为MyObject<>或兼容子类型(子类)。
只有在需要引用T的其他位置时(例如方法的返回类型),或者如果您有多个相同类型的参数或方法体内部时,才需要以这种方式声明T
我总是更喜欢更短、更简单、更清晰、括号少一点的版本,以避免刺痛眼睛 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接