Vinit89
Vinit89

Reputation: 583

What should be the return type of generic type implementation in java

Refering to the following code snippet, I have a interface Splitter which takes generic type parameters T and V. There is one implementation which is CompanySplitterImpl. There could be many such implementations.

public interface Splitter<T, V> {
    V[] split(T arg);
}

public class CompanySplitterImpl
implements Splitter<Company, Department> {

    @Override
    public Department[] split(Company comp) {

        return comp.getDepartment();
    }
}

I am trying to write a factory method which returns different implementation based on a key parameter value passed in to the factory method.

// Factory method to return different Implementation of Splitter
// (Is Splitter return type correct?)
public static Splitter getSplitter(String key) {

    return new CompanySplitterImpl(); // Is this correct?
}

My question is what is the correct manner of returning instance of different implementation of Splitter<K, V>?

// Client to call factory method...
// Not sure what will be type argument for Splitter type
Splitter<?> split = getSplitter("dummyKey");

At the client side, What will be the type argument for Splitter type?

Upvotes: 1

Views: 247

Answers (1)

Paul Boddington
Paul Boddington

Reputation: 37645

Splitter is a raw type. You should not use raw types. Since the key (a String) carries no type information, it is not possible to infer the type parameters from the argument passed to getSplitter. Therefore, the only way to avoid raw types is to make the return type Splitter<?, ?>.

This is ugly and forces the caller of the method to cast:

Splitter<Company, Department> split = (Splitter<Company, Department>) getSplitter("dummyKey");

A better way of doing this is to use a key that carries type information, and the usual way to do this is to use Class<T> objects.

public static <T, V> Splitter<T, V> getSplitter(Class<T> key1, Class<V> key2) {

    if (key1 == Company.class && key2 == Department.class)
        return (Splitter<T, V>) new CompanySplitterImpl();

    // more cases
}

Then the caller could do:

Splitter<Company, Department> split = getSplitter(Company.class, Department.class);

Upvotes: 5

Related Questions