泛型 - 使用它从另一个调用参数化构造函数

时间:2015-03-04 14:32:00

标签: java generics

我有一个类的2个构造函数。参数化构造函数和非参数化构造函数。问题是我无法使用此(...)从另一个调用参数化参数。但是当我从其他地方尝试相同的调用时(例如主方法)

这是代码

package com.test.generics;

    public class Key<T> {

        private T t;

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

        public T getKey(){
            return t;
        }
    }

然后

package com.test.generics;

    public class KeyValueObject<T> {
        private String value;
        private Key<T> key;

        public KeyValueObject(Key<T> k){
            key = k;
            value = "-1";
        }

        public KeyValueObject(String keyString){
            this(new Key<String>(keyString)); //Here is the problem, this says the Constructor KeyValueObject<T>(Key<String> k) is undefined
        }
        public static void main(String[] args) {
            Key<String> keyStr = new Key<String>("x");
            KeyValueObject<String> keyValObj = new KeyValueObject<String>(keyStr); //I try the same thing from main method and it works.
        }
    }

为什么编译器会说“Constructor KeyValueObject(Key k)未定义”。我确实有一个构造函数KeyValueObject(Key k)。

同样在主要方法中,我几乎都在做同样的事情。如果重载的构造函数有效,我可以使用new KeyValueObject("x")

4 个答案:

答案 0 :(得分:3)

KeyValueObject<T>属性的声明类型:

private Key<T> key;

与构造函数调用中的type参数不同:

public KeyValueObject(String keyString){
    this(new Key<String>(keyString));
}

构造函数的泛型类型参数必须与属性的类型匹配:

public KeyValueObject(T t){
    this(new Key<T>(t));
}

答案 1 :(得分:1)

编译器错误是合理的,因为代码不是类型安全的。 为了解原因,假设你写道:

KeyValueObject<Integer> kv = new KeyValueObject("not an Integer");

上述操作会尝试使用KeyValueObject<Integer>(Key<Integer>)参数调用Key<String>,这显然无效。

答案 2 :(得分:1)

正如我在评论中所写,你可以这样做:

public class Program {
    public static void main(String[] args) {
        KeyValueObject<String> $0 = new KeyValueObject<>(new Key<>("x")); //old school
        KeyValueObject<String> $1 = new KeyValueObject<>("x"); //boxing constructor
        KeyValueObject<String> $2 = KeyValueObject.make("x"); //factory method
    }
}

class Key<T> {
    T key;

    public Key(T key){
        this.key = key;
    }

    public T getKey(){
        return key;
    }
}

class KeyValueObject<T> {
    //Solution 2: Create a factory method to handle the case `T` == `String`
    static KeyValueObject<String> make(String value) {
        return new KeyValueObject<>(value);
    }

    String value;
    Key<T> key;

    KeyValueObject(Key<T> key){
        this.key = key;
        this.value = "-1";
    }

    //Solution 1: Change `String` to `T`
    KeyValueObject(T key){
        this(new Key<>(key));
    }
}

答案 3 :(得分:1)

类型Key<String>不一定与Key<T>匹配,因此错误有效。 (可能会想到不安全的类型转换)

考虑实施这样的工厂方法:

public static KeyValueObject<String> createKeyValueObject(final String keyString) {
    return new KeyValueObject<String>(new Key<String>(keyString));
}

或为了更好地利用通用可能性:

public KeyValueObject(T k) {
    this(new Key<T>(k));
}