Java: 重载调用彼此的构造函数

4
考虑一个从CSV行中实例化的类,它存储一些字段。为这个类创建两个构造函数是有意义的-一个从原始的CSV行创建,另一个使用显式的变量赋值。
例如,
public MyClass(String csvLine)
{
    String[] fields = StringUtils.split(csvLine, ',');
    this(fields[3], fields[15], Integer.parseInt([fields[8]));
}

public MyClass(String name, String address, Integer age)
{
    this.name=name;
    this.address=address;
    this.age=age;
}

在Java中,这会失败,因为:

构造函数调用必须是构造函数中的第一条语句 WhereOnEarth.java

正确的实现方式是什么?

3个回答

7
这是我的看法:
public class MyClass {

    public static MyClass fromCsvLine(String csvLine) {
        String[] fields = StringUtils.split(csvLine, ',');
        return new MyClass(fields[3], fields[15], Integer.parseInt([fields[8]));
    }

    //...

}

使用方法:

MyClass my = MyClass.fromCsvLine("...");

可能 MyClass 不应该“知道” CSV 文件,所以将其放入另一个类中(连同 toCSVLine)可能更有意义。但是静态创建方法肯定是正确的选择 - 构造函数有点混乱。 - Tom Hawtin - tackline

5
创建一个方法。
private init(String name, String address, Integer age) {}

在两个构造函数中都调用它。


2
唯一的问题是这使得无法使用final变量。没有好的解决办法,只能使用静态初始化器 - 当然,你可以用构造函数解决它而不会出现代码重复,但显然那会很丑陋... - Voo
我更喜欢这种方法(开个玩笑!?),因为它方便测试。 - Tony Ennis

5
我不会将代表解析内容的类和内容解析类混合在一起。我会创建一个MayClassFactory或类似的东西:
public class MyClassFactory {

    public MyClass fromCsvLine(String csvLine) {
        String[] fields = StringUtils.split(csvLine, ',');
        return new MyClass(fields[3], fields[15], Integer.parseInt([fields[8]));
    }

    //...
}

+1 这也可以是 MyClass 的静态工厂方法,例如 MyClass.parse(String csv)(如果您不介意有一点混合!) - DNA
@DNA:是的,请看我的回答。虽然如果解析有点复杂(或者有多个来源,比如XML),我们强烈建议进行解耦。 - Tomasz Nurkiewicz
我只在工具类(如StringUtils等)中使用静态方法。当编写工厂时,我会设计继承,因此尽可能不使用静态方法。但是,如果您愿意,可以将其设置为静态内部类。 - Tim Büthe
为什么这是一个实例方法? - Tom Hawtin - tackline
@TomHawtin-tackline:我支持非静态方法。MyClassFactory 可能是有状态的,例如保存 CSV 解析配置/验证规则。 - Tomasz Nurkiewicz
@TomHawtin-tackline 就像我说的,为了支持继承。有人可以扩展它或编写一个仅用于测试目的创建Mock对象的MyClassMockFactory。静态方法无法被覆盖。 - Tim Büthe

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