Search code examples
javagenericsbounded-types

Is it possible to have a Type Parameter that extends 2 other type parameters?


Here is my goal: I want to have an argument that needs to be two separate types at the same time.

The goal here is to extract two different types from a single object using just generics (no casting or instanceof).

My idea is to have a third type parameter that extends the other two.

class DualType<A, B> {
    A a;
    B b;
    <T extends A & B> DualType(T obj) {
         a = obj;
         b = obj;
    }
}

This does not work. Since java does not support multiple inheritance, and there isn't a way the compiler can guarantee that B isn't another class, we get an error.

My question is this: Is there some way to define a type parameter that constrains it to only be used with interfaces? I would assume you would be able to use implements rather than extends but as we all know, only super and extends are valid in type parameter declarations. Is there a workaround for this? Or is it simply not possible?

The thing I am trying to achieve here isn't for some practical purpose, but I rather would just like to know if something like this is possible at all in Java?


Solution

  • Is there some way to define a type parameter that constrains it to only be used with interfaces?

    Compiler can't know whether A and B are interfaces or classes, since these type variables are only placeholders and actual types will be provided at runtime.

    And since type variable T has multiple bounds <T extends A & B> only A can be a class and B should be an interface. But B can be pretty much anything, and therefore your constructor causes a compilation error.

    only "super" and "extends" are valid in type parameter declarations

    That's not correct. We can use super only with wild cards, not with bounded types. T super MyInterface will not compile. With bounded type parameters we can use only extends.

    And it's not possible to let the compiler know that B is an interface by using extends. Even if bound would be an interface B extends MyInterface it doesn't imply that B expected to be an interface.

    There's no way to achieve what you're trying to do.