简体   繁体   中英

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);
}

}

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.

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 Function s 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");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM