Java: find out if a function was called using varargs or array

Is there a way to find out if the Java function (or constructor) that accepts varargs is really called with varargs or with an array?

Say I have the following:

public class MyCompositeObjects { MyObject[] objects; MyCompositeObjects(MyObjects... objects) { this.objects = Arrays.copyOf(objects,objects.length); // or just: this.objects = objects; ? } // ... } 

The constructor can be called with a single argument, MyObject[] , which can change later, and if I do not copy the array in the constructor, these changes will also apply to the member variable objects , right? However, if the constructor is called with multiple MyObject s, there is no other array reference * to change it later outside the class, so I could assign it directly. Can I indicate inside the constructor (or, as a rule, any function that takes varargs) how it was called?

* nb: Is there a specific name for this? Is this just an anonymous array?

+7
source share
2 answers

No, you can’t. It should be completely transparent - this code:

 new MyCompositeObjects(a, b); 

exactly equivalent

 new MyCompositeObjects(new MyObjects[] { a, b }); 

If you can trust your subscribers to do the right thing, you can always create two static methods and make the constructor private:

 public static MyCompositeObjects createWithCopy(MyObjects[] values) { return new MyCompositeObjects(Arrays.copyOf(values, values.length)); } public static MyCompositeObjects createWithoutCopy(MyObjects... values) { return new MyCompositeObjects(values); } private MyCompositeObjects(MyObjects[] values) { this.objects = values; } 

Please note that the copy version does not use varargs, which should help users use the correct version.

+9
source

The only way to find out is to parse the code. This is because varargs is a basic component of compilation time and does not change the way the program runs.

If in doubt, I would always copy the array. If you do not know that this will be a performance issue.

BTW: You can do the following.

 MyCompositeObjects(MyObjects o1, MyObjects... objects) { MyCompositeObjects(MyObjects[] objects) { 

However, this can do the opposite of what you want.

Another option is to use a static factory.

 private MyCompositeObjects(MyObjects[] objects) { this.objects = objects; } MyCompositeObjects create(MyObjects... objects) { return new MyCompositeObjects(objects.close()); } MyCompositeObjects createNotCopied(MyObjects... objects) { return new MyCompositeObjects(objects, false); } 

Use a more cumbersome method name for a less secure version. This means that if the method is chosen without a dissenting opinion, a safer version will be more likely.

+4
source

All Articles