Java - 如何处理构造函数中的类型擦除?

Jer*_*emy 18 java type-erasure

假设我的课程中有两个构造函数:

public User (List<Source1> source){
...
}

public User (List<Source2> source) {
...
}
Run Code Online (Sandbox Code Playgroud)

假设这两个构造函数都提供了有关用户的相同信息,并且是为不同用例构建用户的同等有效方法.

在Java中,由于类型擦除而无法执行此操作 - Java不会接受两个具有作为参数List <?的构造函数.>.

那么,解决这个问题的方法是什么?什么是不是矫枉过正但仍然尊重基本OO的解决方案?由于Java没有强大的泛型支持,因此必须构建一个工厂方法或其他接口似乎是错误的.

以下是我能想到的可能性:

1)接受a List<?>作为构造函数的参数,并在构造函数中解析您需要哪种逻辑,或者如果它不是任何可接受的类型则抛出异常.

2)创建一个接受List的类,构造相应的User对象,并返回它.

3)创建包装器,List<Source1>然后List<Source2>可以将其传递给User构造函数.

4)使用两个类对这个人进行子类化,其中除了构造函数之外,所有的功能都是继承的.一个的构造函数接受Source1,另一个接受Source2.

5)用一个构建器包装这个人,其中两个不同的构建器方法用于实例化两个不同的数据源.

我的问题是这些:

1)是否需要使用Java或有意的设计决策来做这个缺陷?什么是直觉?

2)在保持良好代码而不引入不必要的复杂性方面哪种解决方案最强?为什么?

这个问题是类似的:在Java中围绕类型擦除设计构造函数但没有详细说明,它只是提出了各种解决方法.

Boh*_*ian 8

通常的方法是使用工厂方法:

public static User createFromSource1(List<Source1> source) {
    User user = new User();
    // build your User object knowing you have Source1 data
    return user;
}

public static User createFromSource2(List<Source2> source) {
    User user = new User();
    // build your User object knowing you have Source2 data
    return user;
}
Run Code Online (Sandbox Code Playgroud)

如果你需要使用建筑Source1Source2(即你没有一个默认的构造函数),您只需隐藏你的构造函数,强制客户端使用你的工厂方法:

private User () {
    // Hide the constructor
}
Run Code Online (Sandbox Code Playgroud)

出现这个问题是因为你不能以不同的方式命名构造函数,如果这些是正常的方法,那就是你如何克服它.因为构造函数名称被固定为类名,所以这种代码模式只能区分,然后给出相同类型的擦除.