代码之家  ›  专栏  ›  技术社区  ›  wannaBeDev

如何从重载的varargs构造函数中调用对象的基构造函数?

  •  2
  • wannaBeDev  · 技术社区  · 1 年前

    我有一个简单的类,它有一个所有可用字段的构造函数,我想添加一个带有varargs的重载构造函数,以允许创建对象,即使有些字段是未知的。

    class FooClass {
        int id;
        String first;
        String second;
        String third;
    
        FooClass(final int id, final String first, final String second, final String third) {
            this.id = id;
            this.first = first;
            this.second = second;
            this.third = third;
        }
    
        FooClass(final int id, final String... myStrings){
            if(myStrings.length == 1) {
                this.id     = id;
                this.first  = myStrings[0];
            } else if (myStrings.length == 2) {
                this.id     = id;
                this.first  = myStrings[0];
                this.second = myStrings[1];
            } else {
                this.id     = id;
                this.first  = myStrings[0];
                this.second = myStrings[1];
                this.third  = myStrings[2];
            }
        }
    }
    

    我想重构第二个构造函数以避免重复 this.id, this.first ... 如下所示,但我得到了一个编译错误

    FooClass(final int id, final String... myStrings){
            if(myStrings.length == 1) {
                this(id, myStrings[0], null, null);
            } else if (myStrings.length == 2) {
                this(id, myStrings[0], myStrings[1], null);
            } else {
                this(id, myStrings[0], myStrings[1], myStrings[2]);
            }
        }
    

    错误为:

    对“this()”的调用必须是构造函数体中的第一条语句

    从varargs构造函数调用基构造函数的正确方法是什么 null 价值观还是一种更好的方式来实现我上面描述的内容?

    4 回复  |  直到 1 年前
        1
  •  5
  •   Nexevis    1 年前

    在Java中,对的调用 this super 必须是构造函数的第一行。

    class FooClass {
        int id;
        String first;
        String second;
        String third;
    
        FooClass(final int id, final String first) {
            this(id, first, null);
        }
        
        FooClass(final int id, final String first, final String second) {
            this(id, first, second, null);
        }
        
        FooClass(final int id, final String first, final String second, final String third) {
            this.id = id;
            this.first = first;
            this.second = second;
            this.third = third;
        }
        
    }
    

    获得与varargs类似功能的一种方法是简单地编写多个构造函数,这些构造函数向上传递默认值。

    不过,如果参数的数量很高,这可能会变得很麻烦,但该示例仅使用3 String 价值观

    以下是对它们的称呼:

    //Example calls
    public static void main(String [] args) {
        FooClass foo1 = new FooClass(1, "foo1");
        FooClass foo2 = new FooClass(2, "foo1", "foo2");
        FooClass foo3 = new FooClass(3, "foo1", "foo2", "foo3");
    }
    
        2
  •  3
  •   rzwitserloot    1 年前

    你不能。正如错误所说, this 可用,但是 只有 如果它是第一行(因此本质上你只能写一个这样的调用,总计)。

    理论上你可以做到,但它是否干净——这有待商榷:

    this(id, myStrings[0],
      myStrings.length > 1 ? myString[1] : null,
      myStrings.length > 2 ? myString[2] : null);
    

    没有通用的解决方案——你可以找到一种方法将整个事情简化为一个 this() 调用,只使用静态方法和基本表达式,或者,你不能这样做。在这种特定的情况下,有一种方法可以使用基本表达式实现这一点,但该选项并不总是可用的。

        3
  •  3
  •   Bohemian    1 年前

    遵守错误消息,将代码压缩为一行:

    FooClass(final int id, final String... myStrings) {
        this(id, myStrings[0], myStrings.length == 1 ? null : myStrings[1], myStrings.length == 2 ? null : myStrings[2]);
    }
    

    通常的方法是工厂方法,适用于任意复杂的代码:

    public static FooClass create(int id, String... myStrings) {
        if (myStrings.length == 1) {
            return FooClass(id, myStrings[0], null, null);
        } else if (myStrings.length == 2) {
            return FooClass(id, myStrings[0], myStrings[1], null);
        } else {
            return FooClass(id, myStrings[0], myStrings[1], myStrings[2]);
        }
    }
    
        4
  •  2
  •   Chaosfire    1 年前

    你可以写 static 方法,负责从数组中提取值。

    private static String getValue(int index, String... strings) {
      if (strings == null || index >= strings.length) {
        return null;
      }
      return strings[index];
    }
    

    然后将此方法和所有args构造函数一起使用,如下所示:

    public class FooClass {
    
      //fields
    
      public FooClass(final int id, final String first, final String second, final String third) {
        //assign values
      }
    
      FooClass(final int id, final String... myStrings){
        this(id, getValue(0, myStrings), getValue(1, myStrings), getValue(2, myStrings));
      }
    
      private static String getValue(int index, String... strings) {
        ...
      }
    }
    

    这是有争议的,如果这是否更干净,我想说这取决于当前项目中采用的风格。