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

java变量参数列表中至少需要一个元素,java,arguments,minimum,variadic-functions,Java,Arguments,Minimum,Variadic Functions,在此代码构造中: public MyClass(Integer... numbers) { do_something_with(numbers[]); } 是否可以要求numbers至少包含一个条目,并在编译时进行检查?(当然,在运行时,我可以只检查数字。长度。) 很明显,我可以做到: public MyClass(Integer number, Integer... more_numbers) { do_something_with(number, more_numbers[

在此代码构造中:

public MyClass(Integer... numbers) {
    do_something_with(numbers[]);
}
是否可以要求
numbers
至少包含一个条目,并在编译时进行检查?(当然,在运行时,我可以只检查数字。长度。)

很明显,我可以做到:

public MyClass(Integer number, Integer... more_numbers) {
    do_something_with(number, more_numbers[]);
}
但这不会很优雅

我这样做的原因是为了确保子类根本不会忘记调用这个构造函数,这将默认为调用
super()
,列表中没有数字。在本例中,我希望得到熟悉的错误消息:
隐式超级构造函数未定义。必须显式调用另一个构造函数


是否有其他方法可以实现同样的效果,比如某种@注释将此构造函数标记为非隐式?

唯一的验证方法是验证参数

验证参数:

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

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


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

一种非常有技巧的方法是创建该方法的私有版本,而不使用任何参数。这至少可以防止此类之外的任何人在编译时传入一个参数,但不会提供有用的错误消息。但如果它是超重要的,至少传递了一个值,这将使它变得如此重要

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

我想它不在̶f̶u̶n̶c̶t̶I̶o̶n̶类中,但当你叫̶f̶u̶n̶c̶t̶I̶o̶n̶类时。在调用–,f–,u–,n–,c–,t–,i–,o–,n–,类之前,请确保数组中有元素。

我认为一种非常简单的方法是创建一个无参数方法并将其标记为已弃用。然后使用这两个标志编译:
-Xlint:deprecation-Werror
。这将导致任何不推荐使用的方法都是编译时错误

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

一个不太老套的解决方案是抛弃
MyClass(Integer…numbers)
构造函数,用
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;
}

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

public MyClass (int num, int... nums) {
    //Handle num and nums separately
    int total = num;
    for(i=0;i<nums.length;i++) {
        total += nums[i];
    }
    //...
}
公共MyClass(int num,int…nums){ //分别处理num和nums int-total=num;
对于(i=0;iNo您不能这样做..var arg只不过是
数组
的不同表示形式。因此,正如您不能使数组至少包含一个元素一样..这同样适用于var args..RuntimeException,因为并非所有编程错误都可以在编译时找到。这是一种语言限制。您不能这样做..那么@-注释(最后一句)?有这样的事情吗?这正是我想要避免的运行时检查;)@Markus,在编译时也不能避免以下调用:
MyClass m=new MyClass(null,null,null,null)
除非将
Integer…numbers
更改为
int…numbers
。所以我认为抛出IllegalArgumentException已经足够优雅了。实际上,我可以使用null,而我的实际代码也不使用Integer,这只是一个简化的示例。我只需要提请注意,有一个构造函数需要被调用。在代码中忘记它太容易了,因此可能会导致一些故障模式,使用RuntimeException很难跟踪。我已经想到了这一点,但不幸的是它不起作用…它仍然会使用空列表调用另一个构造函数,因为这一个是不可见的。唯一的方法是ng这会防止(再次出现运行时异常)是一个不带参数调用自己的类。真的吗?这很有趣。如果创建了更具体的函数,默认情况下应该忽略
函数。我觉得奇怪的是,Java会试图根据它是公共的还是私有的来区分。我觉得不应该发生这种情况,但我没有让Java…这可能发生在运行时有意义,但问题是是否可以在编译时检查数组号是否包含至少一个元素这是一个非常有创意的想法!我喜欢它!不幸的是,它有两个问题:如果不显式调用super(),Eclipse没有地方向您显示弃用警告,所以不幸的是,它没有让我立即看到我希望看到的红色方块和曲线。更糟糕的是,我确实在代码的其他地方使用了一些弃用的方法,我不能让错误发生在我身上。(在我因为使用不推荐的方法而受到批评之前:这些是Date上的方法,因为GWT不支持Calendar。)我会将此设置为答案。它非常粗糙,不幸对我来说不可用,但它是我问题的最真实答案,即在编译时捕获对super的调用是否没有参数。此外,跳出框框思考应该得到奖励!;)Dead API的弃用是有理由的,因为有些情况下会产生错误的输出。考虑<代码>日期>代码>作为一个简单的包装器,用于长代码和<代码>日历/>代码,以增加除毫秒以外的单位的时间。一旦你在日历中有了你想要的日期,你就可以要求它创建一个日期。那次是Sent。我肯定会建议重新分解你的代码。这是一个很棒的答案。开箱即用
Child c0 = Child.newInstance(1, 2, 3);
Child c1 = new Child(array(1, 2, 3));
public MyClass (int num, int... nums) {
    //Handle num and nums separately
    int total = num;
    for(i=0;i<nums.length;i++) {
        total += nums[i];
    }
    //...
}