Force the same type in java generics implementing an interface
having:
public <T extends Foo> int(T a, T b) { }
Lets me pass a different type to a
and b
if both implement an interface Foo
.
I think it would be better said as:
public <T extends Foo, U extends Foo> int(T a, U b) { }
My question is, is there a way to achieve the first signature (that both a and b are the same type and that both implement the interface Foo
)?
source to share
The following is a little ugly, but it works.
public class Main {
static class Foo {}
static class Bar extends Foo {}
static class Baz extends Foo {}
static <T extends Foo, S extends T> void foo(T a, S b) { }
public static void main(String []args) {
foo(new Foo(), new Foo()); // Compiles fine
foo(new Bar(), new Bar()); // Compiles fine
foo(new Bar(), new Baz()); // Compiler error Baz doesn't extend Bar
}
}
This is a little different from what you want, because it allows the second parameter to subclass the first. I think it's ok because S
- it is T
, so it should work wherever it is T
.
source to share
If you have control over the classes you can do this
public static class Foo<T extends Foo<T>> {}
public static class Bar extends Foo<Bar> {}
public static class Baz extends Foo<Baz> {}
public static <T extends Foo<T>> void doSomething(T a, T b) {}
final Bar bar = new Bar();
final Baz baz = new Baz();
doSomething(bar, bar); // Allowed
doSomething(bar, baz); // Compile error
This is similar to how types are defined Enum
. However, it allows the second parameter to be a subclass of the first.
source to share