java java变量参数列表中至少需要一个元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12751746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Requiring at least one element in java variable argument list
提问by Markus A.
In this code construct:
在此代码构造中:
public MyClass(Integer... numbers) {
do_something_with(numbers[]);
}
is it possible to require that numbers
contains at least one entry in such a way, that this is checked at compile-time? (At run-time, of course, I can just check numbers.length.)
是否可以要求numbers
至少包含一个条目,以便在编译时进行检查?(当然,在运行时,我可以只检查 numbers.length。)
Clearly I could do this:
显然我可以这样做:
public MyClass(Integer number, Integer... more_numbers) {
do_something_with(number, more_numbers[]);
}
but this isn't going to be very elegant.
但这不会很优雅。
The reason I would like to do this is to make sure that a sub-class does not simply forget to call this constructor at all, which will default to a call to super()
with no numbers in the list. In this case, I would rather like to get the familiar error message: Implicit super constructor is undefined. Must explicitly invoke another constructor
.
我想这样做的原因是为了确保子类不会简单地忘记调用这个构造函数,这将默认调用super()
列表中没有数字的调用。在这种情况下,我宁愿得到熟悉的错误消息:Implicit super constructor is undefined. Must explicitly invoke another constructor
.
Could there be another way to achieve the same, like some @-annotation that marks this constructor as non-implicit?
是否有另一种方法可以实现相同的目标,例如某些 @-annotation 将此构造函数标记为非隐式?
采纳答案by Dunes
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.
我想这样做的一种令人难以置信的hacky方法是创建一个无参数方法并将其标记为已弃用。然后用这两个标志编译:-Xlint:deprecation -Werror
. 这将导致任何不推荐使用的方法的使用成为编译时错误。
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.
一个不那么hacky的解决方案是放弃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
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));
回答by Ivan V
I think the best approach to have at least 1 argument is to add one like this:
我认为至少有 1 个参数的最佳方法是添加一个这样的:
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.
添加相同类型的参数和可变参数将强制构造函数要求它(至少一个参数)。然后你只需要单独处理你的第一个参数。
回答by thiago.lenz
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");
}
回答by Tim Bender
As stated in the comments, no, it doesn't seem possible to force a var arg to be of at least size 1.
正如评论中所述,不,似乎不可能强制 var arg 的大小至少为 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.
我能想到的唯一编译时修复是简单地要求一个数组 ( Integer[]
) 作为构造函数的参数。子类仍然可以在其构造函数中使用 var arg,并且该类的任何其他用户只需在调用构造函数之前从所需的参数创建一个数组。
回答by irreputable
public MyClass(boolean ignore, Integer... numbers) {
do_something_with(numbers[]);
}
回答by Jordan
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.
我认为它不在 ?f?u?n?c?t?i?o?n 中?类本身,但是当你调用 ?f?u?n?c?t?i?o?n? 班级。在调用 ?f?u?n?c?t?i?o?n? 之前,请确保您的数组有元素。用它上课。
回答by kurtzbot
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.
你可以做到的一个非常hacky的方法是制作一个没有参数的方法的私有版本。这至少会阻止此类之外的任何人在编译时传入一个参数,但它不会提供有用的错误消息。但是,如果它非常重要,至少传入一个值,那就行了。
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?!?");
}