在java变量参数列表中至少需要一个元素

Mar*_* A. 24 java arguments minimum variadic-functions

在此代码构造中:

public MyClass(Integer... numbers) {
    do_something_with(numbers[]);
}
Run Code Online (Sandbox Code Playgroud)

是否可以要求numbers以这种方式包含至少一个条目,以便在编译时检查?(在运行时,当然,我可以检查numbers.length.)

显然,我可以做到这一点:

public MyClass(Integer number, Integer... more_numbers) {
    do_something_with(number, more_numbers[]);
}
Run Code Online (Sandbox Code Playgroud)

但这不会很优雅.

我想这样做的原因是为了确保子类不会完全忘记调用这个构造函数,这将默认为super()在列表中没有数字的调用.在这种情况下,我宁愿得到熟悉的错误信息:Implicit super constructor is undefined. Must explicitly invoke another constructor.

是否有另一种方法可以实现相同的效果,例如@ -annotation将此构造函数标记为非隐式?

Iva*_*n V 14

我认为至少有一个参数的最佳方法是添加一个这样的:

public MyClass (int num, int... nums) {
    //Handle num and nums separately
    int total = num;
    for(i=0;i<nums.length;i++) {
        total += nums[i];
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)

添加相同类型的参数以及varargs将强制构造函数需要它(至少一个参数).然后你只需要分别处理你的第一个参数.


thi*_*enz 8

验证的独特方法是验证参数.

验证参数:

if (numbers == null || numbers.length == 0 ) {
            throw new IllegalArgumentException("Your angry message comes here");
        }
Run Code Online (Sandbox Code Playgroud)

  • 这正是我想避免的运行时检查;) (2认同)

Dun*_*nes 8

我想一个令人难以置信的hacky方法是创建一个no-args方法并将其标记为已弃用.然后使用这两个标志进行编译:-Xlint:deprecation -Werror.这将导致任何使用不推荐使用的方法成为编译时错误.

编辑(初始答案后很长一段时间):

一个不太讨厌的解决方案是抛弃MyClass(Integer... numbers)构造函数并替换它MyClass(Integer[] numbers)(并添加一个私有的无参数构造函数).它阻止编译器隐式使用超类构造函数,但没有任何args,并为您提供编译时错误消息.

./some_package/Child.java:7: error: constructor Parent in class Parent cannot be applied to given types;
    public Child(Integer[] args) {
                                 ^
  required: Integer[]
  found: no arguments
  reason: actual and formal argument lists differ in length
Run Code Online (Sandbox Code Playgroud)

成本是你的调用语法将变得更加冗长:

new Child(new Integer[] {1, 2, 3});
Run Code Online (Sandbox Code Playgroud)

你当然可以写一个辅助函数来帮助解决这个问题.

public static Child newInstance(Integer... numbers) {
    return new Child(numbers);
}

@SafeVarargs
public static <T> T[] array(T... items) {
    return items;
}
Run Code Online (Sandbox Code Playgroud)

然后:

Child c0 = Child.newInstance(1, 2, 3);
Child c1 = new Child(array(1, 2, 3));
Run Code Online (Sandbox Code Playgroud)