Is there any way in java, to create a method, which is expecting two different varargs? I know, with the same object kind it isn\'t possible because the compiler does\'nt kn
I just read another question about this "pattern", but it is already removed, so I would like to propose a different approach to this problem, as I didn't see here this solution.
Instead to force the developer to wrapping the inputs parameter on List or Array, it will be useful to use a "curry" approach, or better the builder pattern.
Consider the following code:
/**
* Just a trivial implementation
*/
public class JavaWithCurry {
private List<Integer> numbers = new ArrayList<Integer>();
private List<String> strings = new ArrayList<String>();
public JavaWithCurry doSomething(int n) {
numbers.add(n);
return this;
}
public JavaWithCurry doSomething(String s) {
strings.add(s);
return this;
}
public void result() {
int sum = -1;
for (int n : numbers) {
sum += n;
}
StringBuilder out = new StringBuilder();
for (String s : strings) {
out.append(s).append(" ");
}
System.out.println(out.toString() + sum);
}
public static void main(String[] args) {
JavaWithCurry jwc = new JavaWithCurry();
jwc.doSomething(1)
.doSomething(2)
.doSomething(3)
.doSomething(4)
.doSomething(5)
.doSomething("a")
.doSomething("b")
.doSomething("c")
.result();
}
}
As you can see you in this way, you could add new elements of which type you need when you need.
All the implementation is wrapped.
If you are not going to be passing a large number of Strings most of the time for the first argument you could provide a bunch of overloads that take different numbers of Strings and wrap them in an array before calling a method that takes the array as the first argument.
public void doSomething(int... i){
doSomething(new String[0], i);
}
public void doSomething(String s, int... i){
doSomething(new String[]{ s }, i);
}
public void doSomething(String s1, String s2, int... i){
doSomething(new String[]{ s1, s2 }, i);
}
public void doSomething(String s1, String s2, String s3, int... i){
doSomething(new String[]{ s1, s2, s3 }, i);
}
public void doSomething(String[] s, int... i) {
// ...
// ...
}
Only one vararg
is allowed. This is because multiple vararg
arguments are ambiguous. For example, what if you passed in two varargs of the same class?
public void doSomething(String...args1, String...args2);
Where does args1 end and args2 begin? Or how about something more confusing here.
class SuperClass{}
class ChildClass extends SuperClass{}
public void doSomething(SuperClass...args1, ChildClass...args2);
ChildClass extends SuperClass, and so is can legally exist in args1, or args2. This confusion is why only one varargs
is allowed.
varargs
must also appear at the end of a method declaration.
Just declare the specific type instead as 2 arrays.
It is not possible because the Java Language Specification says so (see 8.4.1. Formal Parameters):
The last formal parameter of a method or constructor is special: it may be a variable arity parameter, indicated by an ellipsis following the type.
Note that the ellipsis (...) is a token unto itself (§3.11). It is possible to put whitespace between it and the type, but this is discouraged as a matter of style.
If the last formal parameter is a variable arity parameter, the method is a variable arity method. Otherwise, it is a fixed arity method.
As to why only one and only the last parameter, that would be a guess, but probably because allowing that could lead to undecidable or ambiguous problems (eg consider what happens with method(String... strings, Object... objects)
), and only allowing non-intersecting types would lead to complications (eg considering refactorings where previously non-intersecting types suddenly are), lack of clarity when it does or does not work, and complexity for the compiler to decide when it is applicable or not.
follwing on Lemuel Adane (cant comment on the post, due to lack of rep :))
if you use
public void f(Object... args){}
then you may loop using How to determine an object's class (in Java)?
like for instance
{
int i = 0;
while(i< args.length && args[i] instanceof String){
System.out.println((String) args[i]);
i++ ;
}
int sum = 0;
while(i< args.length){
sum += (int) args[i];
i++ ;
}
System.out.println(sum);
}
or anything you intend to do.
Only one vararg, sorry. But using asList() makes it almost as convenient:
public void myMethod(List<Integer> args1, List<Integer> args2) {
...
}
-----------
import static java.util.Arrays.asList;
myMethod(asList(1,2,3), asList(4,5,6));