When Do You Use Varargs in Java

When do you use varargs in Java?

Varargs are useful for any method that needs to deal with an indeterminate number of objects. One good example is String.format. The format string can accept any number of parameters, so you need a mechanism to pass in any number of objects.

String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);

When to prefer a varargs list to an array?

In your case varargs is just fine. You don't really need to make an array of the paths that you will be importing because there's nothing you want to do with these paths other than to pass them along to your importFrom method.

The varargs functionality saves you from having to explicitly create an array solely for the purpose of passing a collection of values to a one-off method, which you do appear to have here.

BTW, you can still pass in an array if you want to

public class VarargsDemo {
public static void f(String... args) {
for (String s: args) {
System.out.println(s);
}
}
public static void main(String[] args) {
String[] english = new String[]{"one", "two", "three"};
f(english);
f("uno", "dos", "tres");
}
}

Because the behavior is the same, the difference comes down to a (probably minor) question of what you want the method signature to "say". When you declare a method to take an explicit array parameter, it's almost as if you want to stress that you want to operate on an array object, something that has been defined outside the method and has its own existence and importance outside the method, and one in which, perhaps, operations like indexing matter. When declaring the method with varargs, its as if you are saying "just give me a bunch of items".

Then again, this doesn't have to be true; the JVM doesn't know the difference, all it sees is an array at run time. Many programmers won't bother splitting hairs over the intent of the method signature. Varargs is all about making the calls convenient.

That said, the main limitation of varargs is that such a parameter must be the last one of the method. In your case this is not a problem, but in general it is something to consider.

Java 8 varargs on main function signature

It's been legal since varargs were added to the language, I believe. The syntax for calling them explicitly differs, sure, but command-line arguments are passed in not by other Java code but "magically."

JLS 12.1.4 specifies this:

The method main must be declared public, static, and void. It must specify a formal parameter (§8.4.1) whose declared type is array of String. Therefore, either of the following declarations is acceptable:

public static void main(String[] args)

public static void main(String... args)

Consumer with varargs

Variable arity parameter (varargs) is a syntactic element, a special token indicating that a method (or a constructor) expects 0 or more arguments of that type. And these arguments will be wrapped by an array (so that technically they will constitute a single argument) when the method gets executed.

Its usage is limited: a method can have only one parameter of variable arity and it must be defined in the last position.

Variable arity parameter isn't a type by itself. If you'll try to use eclipses ... anywhere apart from the last position of a method (constructor) declaration, you'll get a compile error (take a look at JLS for more information).

In order to use a variable number of arguments in a function, you can define a functional interface with a method of variable arity. And this method is the only place where elipses ... needs to be used.

@FunctionalInterface
public interface MyConsumer<T> {
void accept(T... items);
}
MyConsumer<String> myConsumer = items -> Stream.of(items).forEach(System.out::println);

myConsumer.accept("A", "B", "C");

Will give an output:

A
B
C

varargs as input parameter to a function in java 8

You cannot use the varargs syntax in this case as it's not a method parameter.

Depending on what you're using the Function type for, you may not even need it at all and you can just work with your methods as they are without having to reference them through functional interfaces.

As an alternative you can define your own functional interface like this:

@FunctionalInterface
public interface MyFunctionalInterface<T, R> {
R apply(T... args);
}

then your declaration becomes:

MyFunctionalInterface<String, String> doWork = a -> doSomethingWithArray(a);

and calling doWork can now be:

String one = doWork.apply("one");
String two = doWork.apply("one","two");
String three = doWork.apply("one","two","three");
...
...

note - the functional interface name is just a placeholder and can be improved to be consistent with the Java naming convention for functional interfaces e.g. VarArgFunction or something of that ilk.

Why can't we just use arrays instead of varargs?

The only difference between

foo(String... strings)

and

foo(String[] strings)

is for the calling code. Consider this call:

foo("a", "b");

That's valid with the first declaration of foo, and the compiler will emit code to create an array containing references to "a" and "b" at execution time. It's not valid with the second declaration of foo though, because that doesn't use varargs.

In either case, it's fine for the caller to explicitly create the array:

for(new String[] { "a", "b" }); // Valid for either declaration

Also does main(String[] args) in java use varargs , if not how are we able to pass runtime parameters to it

When it's written as main(String[] args) it doesn't; if you write main(String... args) then it does. It's irrelevant to how the JVM treats it though, because the JVM initialization creates an array with the command line arguments. It would only make a difference if you were writing your own code to invoke main explicitly.

Why varargs should be the last in a method signature?

It follows the C convention. The C convention in turn is based on CPU architectures which pass arguments on the stack. The first non-vararg arguments end up at a fixed offset in the stackframe. If you could put the vararg arguments first, the stack offset of the following arguments would depend on how many vararg parameters you would have passed. This would greatly complicate the amount of code needed to access them.

In your example, with String a first, it's conceptually at offset 0 independent how the number of vararg arguments that follow. But with String a last, it could be at offset 0, 4, 8, 12 etc - you'd have to calculate args.size * 4 everytime you needed String a.

How realy work Varargs in java?


So my question does varargs cast primitive types to object?

It casts to the type of the array. If you have

a(int... ints)

They will be int

and if you have

b(double... doubles)

they will be doubles even if you write b (1, 2.0f, 10L)

If you have an

c(Object... obj)

it will autobox primitives. This is not a feature of var-args but how types are autoboxed as needed anyway.



Related Topics



Leave a reply



Submit