Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何为不同类型的变量数编写Java构造函数?_Java_Constructor - Fatal编程技术网

如何为不同类型的变量数编写Java构造函数?

如何为不同类型的变量数编写Java构造函数?,java,constructor,Java,Constructor,我必须为类戳编写一个构造函数。构造函数应该最多接受五个类型为String、int和double的参数。因此,构造函数将如下所示: public Stamp(String code, int year, String country, double value, int numberOfCopies){...} 问题是,在创建类戳记的对象时,可能不会提供所有参数,即对象可以声明为 Stamp stamp = new Stamp("some_code", 1991, "Burkina Faso",

我必须为类戳编写一个构造函数。构造函数应该最多接受五个类型为String、int和double的参数。因此,构造函数将如下所示:

public Stamp(String code, int year, String country, double value, int numberOfCopies){...}
问题是,在创建类戳记的对象时,可能不会提供所有参数,即对象可以声明为

Stamp stamp = new Stamp("some_code", 1991, "Burkina Faso", 50, 1000);
以及

Stamp stamp = new Stamp("some_code", 1991, "Burkina Faso");
构造函数必须在这两种情况下都工作,即使参数列表被截断(在后一种情况下,一些默认值被分配给value和numberOfCopies)。当然,我可以只编写六个构造函数(对于可能的参数数量,从0到5,假设参数始终遵循上述顺序,不会混淆),但应该有一种更聪明的方法。我知道我可以像这样声明构造函数

public Stamp(Object[] params){...}

然后将params的元素强制转换为相应的类。这可能会起作用,但我必须始终使用“if”条件检查为构造函数提供了多少个参数,以便决定是否在未提供相应参数的情况下为变量指定默认值,或者在给定参数的情况下使用提供的值。这一切看起来都很丑陋。因此,问题很简单:如果提供的参数列表长度不同,参数类型也不同,那么构建构造函数(或其他方法)的方法是什么?

不要搞砸
对象[]
而要进行构造函数重用

提供所有可能的构造函数,并在内部使用它们

只是前男友

public Stamp(String code, int year)
{
    this(code, "", year,0,0); //calling your main constructor with missed values.
}

到目前为止,没有其他解决方法。

如果传递的项目本身无关紧要,则可以使用varargs:

public Stamp(Object... obj) {

}
然而,给出您的示例,听起来您想要添加构造函数重载。因为所有的数据似乎都有意义,并且代表一个特定的东西,我只想这样:

public Stamp(String code, int year) {
    this(code, year, "Burkina Faso");
}

public Stamp(String code, int year, String location) {
    //...
}

这可能适用于生成器模式

public class Stamp {

  public static class Builder {
    // default values
    private String code = "default code"
    private int year = 1900;
    // etc.

    public Builder withCode(String code) {
      this.code = code;
      return this;
    }
    public Builder withYear(int year) {
      this.year = year;
      return this;
    }
    // etc.

    public Stamp build() {
      return new Stamp(code, year, country, value, numberOfCopies);
    }
  }

  public Stamp(String code, int year, String country, double value,
      int numberOfCopies){...}
}
然后,施工过程变得更加复杂

Stamp s = new Stamp.Builder()
                .withCode("some_code")
                .withYear(1991)
              .build();
这样,参数就不再依赖于顺序了——你可以等价地说

Stamp s = new Stamp.Builder()
                .withYear(1991)
                .withCode("some_code")
              .build();

使用方法重载,java支持这一点。
这意味着您可以使用不同的参数在同一个类中编写相同的方法,只需使用复制粘贴并生成多个方法。

事实上,正如其他人所述,一个可能的解决方案是使用
this()
调用重用构造函数

如果顺序是可变的,而您无法分辨哪个是给定的,哪个不是,那么
对象[]
就不够了。您需要一个
映射
,并且需要为它们编写显式转换。也许还有更好的方法可以通过反射来实现,但我还没有完全弄清楚

因此,“简单”的方法应该是

public Stamp(String code, int year, String country, double value, int numberOfCopies){...}
你会的

public enum StampProperties
{
    CODE("code"),
    YEAR("year"),
    COUNTRY("country"),
    VALUE("value"),
    NUMBER_OF_COPIES("numberOfCopies");

    private String identifier;

    private StampProperties(String identifier)
    {
        this.identifier = identifier;
    }

    public boolean c(String id)
    {
        return identifier.equals(id);
    }
}

public Stamp(Map<String, Object> params)
{
    for(String string : params.keySet())
    {
        mapProperty(params, string);
    }
}

private void mapProperty(Map<String, Object> params, String identifier)
{
    Object object = params.get(identifier);
    if(StampProperties.CODE.c(identifier))
    {
         this.code = (String) object;
    }
    else if(StampProperties.YEAR.c(identifier))
    {
         this.year = ((Integer) object).intValue();
    }
    else if...
}
公共枚举StampProperties
{
代码(“代码”),
年份(“年度”),
国家(“国家”),
价值(“价值”),
份数(“份数”);
私有字符串标识符;
专用StampProperties(字符串标识符)
{
this.identifier=标识符;
}
公共布尔c(字符串id)
{
返回标识符.equals(id);
}
}
公众邮票(地图参数)
{
for(字符串:params.keySet())
{
mapProperty(参数、字符串);
}
}
私有void映射属性(映射参数、字符串标识符)
{
Object Object=params.get(标识符);
if(StampProperties.CODE.c(标识符))
{
this.code=(字符串)对象;
}
else if(StampProperties.YEAR.c(标识符))
{
this.year=((整数)对象).intValue();
}
否则如果。。。
}

但我真的认为其他解决方案要好一点,因为它们使用更少的代码,本质上是类型安全的(不太可能出错),老实说,我会选择Ian Roberts所说的
构建器模式
,我真的很喜欢这个答案。

可能重复阅读[1][1]这篇文章。我认为这有一个解决办法。[1] :Groovy语言对于这类事情有很好的语法,您可以定义一个方法,该方法采用
映射
,然后使用“命名参数”调用它,例如
makeStamp(年份:1991,代码:“some_code”)
@IanRoberts Groovy是类型化语言吗?最困难的部分是根据变量的类型或类映射变量,并修改正确的变量。我一直在思考这个问题,但我还没想好。我以后可能会在家里修改它。在public Builder with code()中,返回类型是什么?它如何返回而不出错?