实例化一个通用类型

3

我正在尝试将一个已有的类转换为使用泛型,并在转换构造函数时受阻。

原始类是一个POJO,包含文本控制台游戏中从一个房间移动到另一个房间的逻辑。实际上,它是一个包含一些字符串触发器的类(例如,用户输入“向右走”),一个描述和指向新位置的指针。

当前非泛型版本的类如下所示:

public class Navigation implements Serializable {
    private static final long serialVersionUID = 1L;
    private String trigger;
    private String description;
    private Location target;

    public Navigation() {
        this("", "", new Location());
    }

    public Navigation(String trigger, String description, Location target) {
        this.trigger = trigger;
        this.description = description;
        this.target = target;
    }

    // plus getters, setters, etc.
}

Location类是另一个描述位置的POJO,与此无关。)

我想扩展Navigation类以处理不是Location的目标。 我认为最好的方法是将Navigation类转换为使用通用类型,因此我尝试了这样做:

public class Navigation<T> implements Serializable {
    private static final long serialVersionUID = 2L;
    private String trigger;
    private String description;
    private T target;

    public Navigation() {
        this("", "", new T());
    }

    public Navigation(String trigger, String description, T target) {
        this.trigger = trigger;
        this.description = description;
        this.target = target;
    }

    // plus getters, setters, etc.
}

然而,在这行代码 this("", "", new T()); 中,编译不通过,因为无法实例化T。是否有可能在这种情况下实例化泛型类型对象?


1
请看右边的所有相关问题。 - Sotirios Delimanolis
我明白了。他们传递了一个类,答案是调用clazz.newInstance()。这是默认构造函数。但我没有一个类。 - Roddy of the Frozen Peas
1
然后直接传递target实例。这是您唯一的选择。 - Sotirios Delimanolis
@RoddyoftheFrozenPeas:由于类型擦除,你不能这样做。 - SLaks
3个回答

4
你基本上有两个选择:
1.需要一个实例:

您可以创建一个新的实例,该实例将运行您的IT应用程序。这是一种常见的方法,因为它允许您拥有完全控制权并且不会受到其他应用程序的干扰。

2.使用共享服务器:

您可以使用共享服务器来运行您的IT应用程序。这意味着您与其他人共享服务器资源,因此您可能会受到其他应用程序的影响。但是,这也意味着您不必支付独立服务器的费用。

public Navigation(T t) {
    this("", "", t);
}

2. 需要一个类的实例:

public Navigation(Class<T> c) {
    this("", "", c.newInstance());
}

你可以使用工厂模式,但最终你将面临同样的问题,只是将其推到代码的其他位置。


2
由于类型擦除,您无法执行new T()。默认构造函数只能是

public Navigation() {
    this("", "", null);
}

您可以创建其他构造函数来为触发器和描述提供默认值。您需要一个具体的 T 对象。

你能详细解释一下你的答案吗?new T()擦除了什么?new Object()呢? - Roddy of the Frozen Peas
@RoddyoftheFrozenPeas 这并不会擦除任何东西。它在语法上是不正确的。 - Sotirios Delimanolis

2
不需要,而且你想要这样做似乎不是一个好主意。你真的需要这样的默认构造函数吗?

由于对象最初是通过解析XML和YAML数据创建的,因此我需要一个默认构造函数。target也不允许为空,这就是为什么我在这里尝试实例化它的默认版本的原因。 - Roddy of the Frozen Peas
1
@RoddyoftheFrozenPeas 如果 T 没有无参构造函数怎么办? - Sotirios Delimanolis
@SotiriosDelimanolis 我期望的行为与在其上调用 clazz.newInstance() 时发生的相同,即:抛出一个InstantiationException异常。 - Roddy of the Frozen Peas
1
@RoddyoftheFrozenPeas 这将发生在运行时。通用的 T 是一个编译时的概念。 - Sotirios Delimanolis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接