Java Generics with Static Factory方法

时间:2016-08-09 09:58:47

标签: java generics

我尝试创建一个Variable类,可以使用泛型来表示IntegerDouble值。

以下是我尝试过的代码。由于擦除,我使用enum来存储Variable的预期类型,然后尝试使用它来将值初始化为正确的类型。

public class Variable<T> {

    private enum Type {INTEGER, DOUBLE};
    private Type type;

    private T value;

    public static Variable<Integer> createAsInteger() {
        return new Variable<Integer>(Type.INTEGER);
    }

    public static Variable<Double> createAsDouble() {
        return new Variable<Double>(Type.DOUBLE);
    }

    private Variable(Type type) {
        this.type = type;

        if(type == Type.INTEGER) {
            value = new Integer(0);
        } else {
            value = new Double(0.0);
        }
    }

    public static void main(String[] args) {
        Variable.createAsInteger();
        Variable.createAsDouble();
    }

}

然而,当我编译它时,我收到以下消息......

error: incompatible types: Integer cannot be converted to T
                    value = new Integer(0);

同样适用于Double

任何人都可以解释为什么会发生这种情况,如果有一种解决方法,而不必编写两个单独的类,一个用于Integer,另一个用于Double

修改

感谢您的所有答案......基于他们,我现在意识到有更好的方法可以做到这一点。但是,我试图理解为什么这种方法不起作用,以便我将来不会犯同样的错误。

当我按照建议将我的班级定义为public class Variable<T extends Number>时,我仍然会遇到同样的错误。

4 个答案:

答案 0 :(得分:2)

您的架构似乎玷污了泛型的概念。

最简单的方法是在类型参数中设置上限:

class Variable<T extends Number> {...}

然后,您可以根据所需的类创建Variable<X>的通用工厂方法:

static <X extends Number>Variable<X> create() {
    return new Variable<X>();
}

然后您可以将其调用为:

Variable.<Integer>create(); // returns an instance of `Variable<Integer>`

这不仅限于IntegerDouble,而是任何Number

如果必须,您可以通过执行以下操作来限制这些选择:

  • create方法中添加参数:create(Class<X> clazz)
  • 检查方法正文中clazz参数的值:

    if (!clazz.equals(Integer.class) && !clazz.equals(Double.class)) {
        // TODO complain
    }
    

否则,您可以确保使用private构造函数并提供static createAs...非通用方法,例如createAsInteger等,这些方法将返回new Variable<Integer>等。< / p>

答案 1 :(得分:1)

这里的问题是T可以是任何东西。如果T例如String,那么您的代码将等于:

String value = new Integer(0);

您可以像这样布置工厂方法:

public static Variable<Integer> createAsInteger() {
    return new Variable<>(new Integer(0), Type.INTEGER);
}

你有一个像:

这样的构造函数
private Variable(T value, Type type) {
    this.value = value;
    this.type = type;
}

答案 2 :(得分:0)

您收到错误是因为您在泛型类中表示了一个方法。你不能在T泛型类中定义一些。

顺便说一句,你误解了设计模式。

您必须为Variable设计一个泛型类,构造函数也必须将T作为参数类型。

在另一个类中,您使用createInteger和createDouble方法实现工厂。

答案 3 :(得分:0)

您可以使您的类继承自Numbers并使用类型检查来调用Integer或Double的适当方法。

public class Variable<T extends Number> {
     public static Variable<T extends Number> Variable<T> create(Variable<T> var){
               if (var instanceOf Integer){
                // Take appropriate action
               }
               else if (var instanceOf Double){
               // Take appropriate action
               }

     }
}

通过这种方式,没有特别需要为类型维护单独的枚举。