Petr Sezemský
Petr Sezemský

Reputation: 23

Generic constructor of generic class

I have generic class ConsumerTest<T, U> and I plan that T is mutable type and U is ekvivalent immutable type like <StringBuilder, String>, <MutableInt, Integer>, <MutableDouble, Double>, ... How can I write generic constructor which creates the mutable type from immutable? Here is my attempt:

import org.apache.commons.lang3.mutable.MutableDouble;
import org.apache.commons.lang3.mutable.MutableInt;

class ConsumerTest<T, U> {

private T value;

public <T, U> ConsumerTest(U u) {
        this.value = new T(u);  // compile error
}

public static void main(String[] args) {
        ConsumerTest ctS = new ConsumerTest<StringBuilder, String>("Hello");
        ConsumerTest ctI = new ConsumerTest<MutableInt, Integer>(666);
        ConsumerTest ctD = new ConsumerTest<MutableDouble, Double>(11.11);
}

}

Upvotes: 1

Views: 67

Answers (2)

rgettman
rgettman

Reputation: 178253

As another answer states, new T(u) is invalid syntax. One cannot use a type parameter as a new class to instantiate, because there is no guarantee that that particular class's constructor takes exactly one argument of that exact type.

In addition, you've created a generic constructor that defines its own T and U, which shadow the class's declarations of T and U. That's why you get a compiler error message such as "Cannot convert T to T". Remove the declarations of T and U from the constructor, but not from the class.

You still need to be able to construct an object of type T from one of type U, so provide a converter function. Note here that Java's built in Functions reverse the sense of U and T that you have.

class ConsumerTest<T, U> {

    private T value;

    public ConsumerTest(U u, Function<U, T> converter) {
        this.value = converter.apply(u);
    }

    public static void main(String[] args) {
        ConsumerTest ctS = new ConsumerTest<StringBuilder, String>("Hello", StringBuilder::new);
        ConsumerTest ctI = new ConsumerTest<MutableInt, Integer>(666, MutableInt::new);
        ConsumerTest ctD = new ConsumerTest<MutableDouble, Double>(11.11, MutableDouble::new);
    }
}

There may be additional reasons you need to encapsulate this functionality in a class that you haven't shown, but you may not need a class such as ConsumerTest. Just create the functions.

Function<String, StringBuilder> ctS = StringBuilder::new;

Or you may not need to bother with the functions at all. Create the mutable objects directly.

StringBuilder sb = new StringBuilder("Hello");

Upvotes: 0

Jeff Scott Brown
Jeff Scott Brown

Reputation: 27200

new T(u) is invalid because T isn't a type. In order to create an instance of a class, you need to know the type, and you don't in that context.

Upvotes: 2

Related Questions