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

时间:2012-10-05 18:06:47

标签: java arguments minimum variadic-functions

在此代码构造中:

public MyClass(Integer... numbers) {
    do_something_with(numbers[]);
}

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

显然,我可以这样做:

public MyClass(Integer number, Integer... more_numbers) {
    do_something_with(number, more_numbers[]);
}

但这不会很优雅。

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

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

7 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:8)

我认为一种令人难以置信的hacky方法是创建一个no-args方法并将其标记为已弃用。然后使用这两个标志进行编译:{{1​​}}。这将导致使用不推荐使用的方法成为编译时错误。

编辑(初次回答后很长一段时间):

一个不太常见的解决方案是放弃-Xlint:deprecation -Werror构造函数并将其替换为MyClass(Integer... numbers)(并添加一个私有的无参数构造函数)。它阻止编译器隐式使用超类构造函数,但没有任何args,并为您提供编译时错误消息。

MyClass(Integer[] numbers)

费用是你的调用语法会变得更冗长:

./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

你当然可以写一个辅助函数来帮助解决这个问题,例如。

new Child(new Integer[] {1, 2, 3});

然后:

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

@SafeVarargs
public static <T> T[] array(T... items) {
    return items;
}

答案 2 :(得分:7)

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

验证参数:

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

答案 3 :(得分:2)

正如评论中所述,不,似乎不可能强制var arg至少为1。

我能想到的唯一编译时修复只需要一个数组(Integer[])作为构造函数的参数。子类仍然可以在它们的构造函数中使用var arg,并且该类的任何其他用户只需在调用构造函数之前从所需的参数创建一个数组。

答案 4 :(得分:1)

public MyClass(boolean ignore, Integer... numbers) {
    do_something_with(numbers[]);
}

答案 5 :(得分:0)

你可以做的一个非常黑客的方法就是在没有参数的情况下制作该方法的私有版本。这至少会阻止此类之外的任何人在编译时传入一个参数,但它不会提供有用的错误消息。但是,如果它是至关重要的,至少传递一个值,那就会成功。

private MyClass() {
    // This exception will be thrown only if you manage to do a "new MyClass()"
    // within your own class since it is private.
    throw new RuntimeException("Why did you do this?!?"); 
}

答案 6 :(得分:0)

我认为这不是在̶f̶u̶n̶c̶t̶i̶o̶n̶类本身,而是当你打电话给̶f̶u̶n̶c̶t̶i̶o̶n̶课程时。用它来调用̶f̶u̶n̶c̶t̶i̶o̶n̶课之前,确保你的数组有元素。