Parameter a class with type A or B

Viewed 724

I am trying to parameter a class with a type that is whether A or B and nothing else.

Something like

final class ChildClass<A | B> extends MotherClass {

This way I can create a ChildClass<A> or a ChildClass<B> but nothing else.

Is it possible in Java?


Edit:

I must specify that I am using Java 8 and that I have no control of classes A and B (which are classes of the Android framework I am working with).

4 Answers

Unfortunately is not. Search for term union types in java or java either type.

The most known case of union types in Java is catching multiple exceptions, which is built-in into language, however it would be awful to abuse exceptions for your own types.

Here is also interesting workaround.

With the addition of this JEP, there is a rather interesting way to do it now.

You can create an interface that is sealed:

sealed interface F permits A, B {

    default String name() {
        return "F";
    }
}

add the generic type that is going to be bounded by this interface:

static class WithGenerics<T extends F> {

    private final T t;

    public WithGenerics(T t) {
        this.t = t;
    }

    public void findName() {
        System.out.println(t.name());
    }

}

And finally create the two classes A and B:

static final class A implements F {
    .....
}

static final class B implements F {
   .....
}

And you have effectively said that only A and B can be passed to :

 WithGenerics<A> a = new WithGenerics<>(new A());
 a.findName();

 WithGenerics<B> b = new WithGenerics<>(new B());
 b.findName(); 

because there can be no type C that can potentially implement F.

You might be able to check the class type of T like this:

public Class Foo<T> extends MotherClass {
    private final Class<T> classType;

    public Foo(Class<T> classType) {
        this.classType = classType;
    }

    public Class<T> getClassType() {
        return this.classType;
    }

    public void method() {
        if (classType.equals(A.class)) {
        //Do something
        } else if (classType.equals(B.class)) {
        //Do something
        }
    }
}

Heres an example of creating an object of Foo..

Foo<A> foo = new Foo<>(A.class);

Hope this helps you if it doesn't leave a comment and I'll try to edit and provide a more helpful answer.

This way I can create a ChildClass<A> or a ChildClass<B> but nothing else. Is it possible in Java?

I am assuming that A and B are real types and not just generic parameters. Otherwise, A and B could be anything so you may as well just have A.

So why not just predefine the class to return an instance of whichever ones are allowed?

class MyClass<A> extends MotherClass {
    private MyClass() {
    }
    
    public static MyClass<Integer> instanceOfInteger() {
        return new MyClass<Integer>();  
    }
    public static MyClass<String> instanceOfString() {
         return new MyClass<String>();
    }
    // rest of class here
}


MyClass<Integer> mc1 = MyClass.instanceOfInteger();
MyClass<String> mcs = MyClass.instanceOfString();
Related