【问题标题】:Java Method with Enforced Array Size Parameters?具有强制数组大小参数的 Java 方法?
【发布时间】:2010-10-30 08:36:58
【问题描述】:

我想为一个接受 3 个参数的 Java 类创建一个初始化方法:

Employee[] method( String[] employeeNames, Integer[] employeeAges, float[] employeeSalaries )
{
    Employee myEmployees[] = new Employee[SIZE]; // I don't know what size is

    for ( int count = 0; count < SIZE; count++)
    {
        myEmployees[count] = new Employee( employeeNames[count], employeeAges[count], employeeSalaries[count] );
    }
    return myEmployees;
}

您可能会注意到这段代码是错误的。未定义 SIZE 变量。我的问题是我想传入 3 个数组,但我想知道我是否可以确保这三个数组都是相同的数组大小。这样for循环就不会失败,因为for循环中的构造函数使用了数组的所有参数。

也许 Java 有一个不同的功能可以强制解决我的问题。我可以接受另一个名为 SIZE 的参数,它将在 for 循环中使用,但如果参数 1 和 2 的大小为 10 并且第三个参数是大小为 9 的数组,这并不能解决我的问题。

如何强制这 3 个参数都是包含完全相同数量元素的数组?使用指定数组大小的额外参数不是很优雅而且有点脏。它也没有解决数组参数包含不同大小的数组的问题。

【问题讨论】:

    标签: java class architecture


    【解决方案1】:

    你不能在编译时强制执行。您基本上必须在执行时检查它,如果不满足约束,则抛出异常:

    Employee[] method(String[] employeeNames,
                      Integer[] employeeAges,
                      float[] employeeSalaries)
    {
        if (employeeNames == null
            || employeeAges == null 
            || employeeSalaries == null)
        {
            throw new NullPointerException();
        }
        int size = employeeNames.length;
        if (employeesAges.length != size || employeeSalaries.length != size)
        {
            throw new IllegalArgumentException
                ("Names/ages/salaries must be the same size");
        }
        ...
    }
    

    【讨论】:

    • 这是我认为使用 NullPointerException 的错误方法的一个很好的例子。我将对每个传递的参数进行单独检查 if (employeeNames == null) { throw new IllegalArgumentException("employeeNames == null");这使得堆栈跟踪对于诊断问题更有帮助。
    • 我认为在这种情况下抛出 NPE 也是可以接受的(虽然没有人会不同意抛出 IAE);但也许作为这场辩论/争议中的一种妥协,最好在 NPE 中加入一条消息。
    • 我使用 NullPointerException 来遵循 Effective Java 2nd edition, item 60 中显示的约定。要真正正确地做到这一点,我会对每个参数使用单独的检查,因此我可以将正确的名称放入 -但我想保持这个例子的代码简短:)
    • NullPointerException 同上。引用 javadoc,NullPointerException 是“当应用程序在需要对象的情况下尝试使用 null 时抛出”。 IllegalArgumentException 是“抛出以指示方法已传递非法或不适当的参数。”在这种情况下,空数组显然是一个非法参数。它没有被访问。
    【解决方案2】:

    由于传入的数组直到运行时才生成,因此无法阻止方法调用完成,具体取决于作为编译时检查传入的数组的特征。

    正如 Jon Skeet 所提到的,指出问题的唯一方法是在运行时抛出 IllegalArgumentException 或类似的东西,以在使用错误参数调用方法时停止处理。

    无论如何,文档应该清楚地说明使用该方法的期望和“合同”——传入三个长度相同的数组。在该方法的 Javadocs 中注明这一点可能是个好主意。

    【讨论】:

      【解决方案3】:

      绕过这个问题的一种方法是创建一个构建器,例如 EmployeeArrayBuilder,

      public class EmployeeArrayBuilder {
         private Integer arraySize = null;
         private String[] employeeNames;
         public EmployeeArrayBuilder addName(String[] employeeNames) {
            if (arraySize == null) {
               arraySize = employeeNames.length;
            } else if (arraySize != employeeNames.length) {
               throw new IllegalArgumentException("employeeNames needs to be " + arraySize + " in length");
            }
            this.employeeNames = employeeNames;
            return this;
         }
         public EmployeeArrayBuilder addSalaries(float[] employeeSalaries) {/* similar to above */}
         public EmployeeArrayBuilder addAges(Integer[] employeeAges) {/* similar  */}
         public Employee[] build() {
             // here, you can do what you needed to do in the constructor in question, and be sure that the members are correctly sized.
             Employee myEmployees[] = new Employee[arraySize ];// dont know what size is            
             for ( int count = 0; count < arraySize ; count++) {
                  myEmployees[count] = new Employee( employeeNames[count], employeeAges[count], employeeSalaries[count] );
             }
             return myEmployees;
         }
      }
      

      【讨论】:

      • 我认为这里不适合使用构建器,因为 API 中没有任何内容表明年龄、姓名和薪水都是必需的。当您可以有可选参数时,Builder 是合适的。与 Jon Skeet 的回答相比,它也相当复杂。
      • @Ken Liu:两者都解决了同样的问题——我发布这个是因为另一个解决方案已经发布了,为什么要重复?这是一个值得考虑的替代方案。实际上,API 中没有任何内容表明这些是必需的参数,但这并不会影响构建器模式。
      猜你喜欢
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      相关资源
      最近更新 更多