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将强制构造函数需要它(至少一个参数).然后你只需要分别处理你的第一个参数.
验证的独特方法是验证参数.
验证参数:
if (numbers == null || numbers.length == 0 ) {
throw new IllegalArgumentException("Your angry message comes here");
}
Run Code Online (Sandbox Code Playgroud)
我想一个令人难以置信的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)