在java中,如何使两个构造函数具有相同数量的参数,但变量不同

在java中,如何使两个构造函数具有相同数量的参数,但变量不同,java,constructor,Java,Constructor,在我的例子中,这个类将有两个构造函数,都以3个字符串作为参数,但是其中一个构造函数中要初始化的字符串变量可能不同。 是否可以执行以下操作: class A { String x = null; String y = null; String z = null; String a = null; A(String x, String y, String z) { .... } A(String a, String y, String z)

在我的例子中,这个类将有两个构造函数,都以3个字符串作为参数,但是其中一个构造函数中要初始化的字符串变量可能不同。 是否可以执行以下操作:

class A {
   String x = null;
   String y = null;
   String z = null;
   String a = null;

   A(String x, String y, String z) {
      ....
   }

   A(String a, String y, String z) {
      ....
   }
}
是否可以执行以下操作

没有

因为编译器没有内置的水晶球以便在编译时选择合适的构造函数

请注意两点:

  • 构造函数签名中的参数名在编译后丢失-它们是纯人工的。因此,它们不能用于在两个CTOR之间进行调度

  • 参数名与字段名无关。编译器并不关心这两者通常是相同的

    • 简言之:没有

      长答覆: 它们有什么不同?如果它们非常不同,您可能需要考虑创建基类并扩展它。

      另一个选项是创建StringType枚举并将其与构造函数一起传递


      通常,如果您有两个类似的构造函数,则需要检查您的设计。

      您不能这样做。不能有两个具有完全相同签名的构造函数,也不能有两个具有完全相同签名的方法。参数名称并不重要

      一种解决方案是使用所谓的静态工厂方法:

      // in class A
      // Parameter names could be "tar", "feathers" and "rope" for what it matters
      public static A withXYZ(String x, String y, String z)
      {
          final A ret = new A();
          ret.x = x; ret.y = y; ret.z = z;
          return ret;
      }
      
      代码:

      final A myA = A.withXYZ(whatever, you, want);
      
      另一个解决方案是使用一个


      有关现成的解决方案,请参见下面的@Andy答案。

      否,但快速解决方案是使用静态助手:

      class A {
      
        String x, y, z, a;
      
        /** Constructor. Protected. See static helpers for object creation */
        protected A(String x, String y, String z, String a) {
          this.x = x;
          this.y = y;
          this.z = z;
          this.a = a;
        }
      
        /** Construct a new A with an x, y, and z */
        public static A fromXYZ(String x, String y, String z) {
          return new A(x, y, z, null);
        }
      
        /** Construct a new A with an a, y, and z */
        public static A fromAYZ(String a, String y, String z) {
          return new A(a, null, y, z);
        }
      }
      

      绝对不是。如果我写:

      A a = new A("foo", "bar", " ");
      
      那么我会调用哪个构造函数呢

      您可以选择使用静态方法,即:

      public static A withXYZ(String x, String y, String z) 
      {
          final A a = new A();
          a.x = x;
          a.y = y;
          a.z = z;
          return a;
      }
      
      A myA = A.withXYZ("foo", "bar", " ");
      
      否则,您可以在构造后使用普通setter注入值,即:

      A a = new A();
      a.setX("foo");
      a.setY("bar");
      a.setZ(" ");
      

      +1的正确答案,尽管值得一提的是解决问题的其他方法,例如建筑商。这并不完全正确。参数名在编译后不会丢失,除非进行模糊处理,否则它们将以原始形式保留在字节码中。至少如果是用标准的javac编译的话。@Andy:除非你用调试设置编译代码,否则它们就会丢失。然后,它们不能以与字段名相同的方式访问。它们仅用于(可选)调试。反射API很好地说明了这一点:有
      方法#getParameterTypes()
      但没有
      方法#getParameterNames()
      或类似方法。出于同样的原因,如果没有翻天覆地的更新,Java将永远不会有类似命名参数的东西。你确定吗?我已经反编译了很多java应用程序。除非对应用程序进行模糊处理,否则可以获取原始参数和变量名。标准Java反射库不允许您在运行时访问参数名。但是,您可以在运行时使用某些实用程序检查类的字节码。(不是普通的或超级有用的,但可能)。@安迪:我肯定。方法和构造函数名称只能作为调试符号使用。在一个没有调试设置的简单类上尝试
      javap
      newa(“1”、“2”、“3”)
      -->我正在调用哪个构造函数?使用合理名称的静态创建方法应该可以。你可能会问自己,“在什么情况下,让构造函数填写其中一些成员变量是有意义的,在什么情况下应该只填写其他变量,这样就不会指定某些变量集?“空成员变量并不是一个好主意,这非常表明您的代码可以更干净。@damo您的名声是“leet”;)这个问题怎么办?可能会让构造器成为我的习惯——在大多数内部事务中受到保护,除非我知道我不需要对它进行子类化。好吧,我不讨论味道;)但是,这样的构造函数是包可访问的。关于可访问的包,您是对的!您不需要将字段初始化为null,因为这是默认值。纯粹是习惯!我总是尽可能地使变量成为最终变量。我限制了自己,因为我通常也会将方法参数设置为最终参数。它使我能够清楚地发现将要修改的变量。