Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can explicit type parameters redundant?

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?

like image 811
Jin Kwon Avatar asked Jun 26 '19 07:06

Jin Kwon


2 Answers

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

like image 163
Slaw Avatar answered Nov 10 '22 18:11

Slaw


Yes they are equivalent. Both sets of methods declare the same thing - that the method parameter must be of type MyObject<> or a compatible subtype (subclass).

The only reason to declare T in this way is if you need to refer to T elsewhere, such as the return type of the method, or if you have multiple parameters of the same type, or inside the method body.

I would always prefer the shorter, simpler, clearer version with less angle brackets to hurt the eyeballs :)

like image 29
halfnuts Avatar answered Nov 10 '22 18:11

halfnuts