Requiring at least one element in java variable argument list

醉酒当歌 提交于 2019-12-01 02:10:38

I suppose one incredibly hacky way to do this is to create a no-args method and mark it as deprecated. Then compile with these two flags: -Xlint:deprecation -Werror. This will cause any use of a deprecated method to be a compile time error.

edit (a long time after the initial answer):

A less hacky solution would be to ditch the MyClass(Integer... numbers) constructor and replace it with MyClass(Integer[] numbers) (and add a private no-args constructor). It stops the compiler from being able to implicitly use the super class constructor, but without any args, and gives you a compile time error message.

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

The cost is your calling syntax will become a bit more verbose:

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

You can of course write a helper functions to help with this eg.

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

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

and then:

Child c0 = Child.newInstance(1, 2, 3);
Child c1 = new Child(array(1, 2, 3));

I think the best approach to have at least 1 argument is to add one like this:

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

Adding an argument of the same type along with varargs will force the constructor to require it (at least one argument). You then just need to handle your first argument separately.

The unique way to validate is verifies the params.

Validate the arguments :

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

As stated in the comments, no, it doesn't seem possible to force a var arg to be of at least size 1.

The only compile time fix that I can think of is to simply require an array (Integer[]) as the argument to the constructor. Subclasses could still take a var arg in their constructor and any other users of the class would simply have to create an array from the desired arguments before calling the constructor.

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

A really hacky way you can do that is to make a private version of that method with no parameters. That would at least prevent anyone outside this class from passing in one parameter at compile-time, but it won't provide a useful error message. But if it is super important at least one value is passed in, that will make it so.

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?!?"); 
}

I think it's not in the ̶f̶u̶n̶c̶t̶i̶o̶n̶ class itself, but when you call the ̶f̶u̶n̶c̶t̶i̶o̶n̶ class. Make sure your array has elements before calling the ̶f̶u̶n̶c̶t̶i̶o̶n̶ class with it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!