Can explicit type parameters redundant?

Jin Kwon :

I have a class with a type parameter.

class MyObject<IdType> {

    @Setter
    @Getter
    private IdType id;
}

And I thought I can add some method for conveniency so I did.

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

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

And I just realized that I can do this.

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

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

Are those two sets of methods are equivalent? Which way (or style) is prefer?

Slaw :

In your case, the two approaches are effectively equivalent. They both restrict the argument's type to MyObject<...> or a subtype.

Since your example methods return void there's no real benefit from making the method generic. The only important thing for your method is that the argument is a MyObject<...>—beyond that the real type is meaningless. Adding the ability to make the argument's type more specific adds nothing for the method's implementation and does nothing for the caller. In other words, it's irrelevant "fluff".

So for your examples, I would say prefer the non-generic option. It's cleaner and more straightforward.


However, if your methods returned the given argument back to the caller then making the method generic could prove useful; it would allow you to declare the return type as T. This opens up possibilities to the caller such as method chaining or invoking the method "inside" another method call, all based on the specific type passed as an argument. An example of this in the core library would be Objects.requireNonNull(T).

Another good case for making the method generic is mentioned by @Thilo in the comments:

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).

This could also be applied to a single argument if it were, for instance, a Collection<? extends T>.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=120951&siteId=1