• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Var args ... explanation needed

 
Ranch Hand
Posts: 381
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ranchers,
Can anybody explains the behaviour of

?
 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It doesn't compile.

However I've changed the code slighty to try and help you along



This is an example of how you can use varargs and how you can overload them

Hope this helps a little.
 
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I think in this type of overloading with varargs.You have to use different name of methods.Because at compile time compiler become confuse .i have written it as
If any Wrong in my explanation then.Please tell me

Thanks,
Prashant Kumar Singh
 
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Nor does this compile
Can anyone tell us the reason WHY?

 
Sanjeev Singh
Ranch Hand
Posts: 381
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Dear Ranchers,

The output here is obvious,there are matching arguments for both of the method calls.
My question is why there is ambiguity in the code

Does the rule of preference of the overloaded method not exists here,when there is no matching parameter?Imagine the case when there is no var args and the argument in the methods are (long x) and (Integer x),it is the (long x) which dominates,why not such a case is here?
[ November 07, 2006: Message edited by: Sanjeev Kumar Singh ]
 
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

class Vararg
{
static void vararg(long ... x){ System.out.println("long...");}static void vararg(Integer ... x){ System.out.println("Integer...");}public static void main(String [] args) { int i = 5; vararg(5,5);}}
 
Rancy Chadha
Ranch Hand
Posts: 135
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

class Vararg
{
static void vararg(long ... x) ---------- (1)
{ System.out.println("long...");
}
static void vararg(Integer ... x) ----------- (2)
{ System.out.println("Integer...");
}
public static void main(String [] args)
{ int i = 5;
vararg(5,5);
}
}
At compile time a vararg is converted to an array.
What happens after we calls vararg(5,5)
at (1) after widening it can be converted to long[] = {5,5}
at (2) after autoboxing it can be converted to Integer[] = {5,5}
in this case compiler does not find MOST SPECIFIC method to use when it is working out method overloading, because both long[] and Integer[] are Array objects so it gives us error stating ambiguity.

The above reason is the reason that I think would be holding true, I may be wrong on this. If anybody finds this answer wrong please do correct me.

Thanks,
Rancy
 
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think this is strange because I thought the rule is to take the 'old style' when there's a doubt. So i'd think the compiler would take long..., because widening existed long time before autoboxing. Apparently I'm missing something here...
 
Ranch Hand
Posts: 1880
Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Article on Varargs :
http://www.javabeat.net/javabeat/scjp2/ht/index.php?examType=SCJP&msgId=19
 
Sanjeev Singh
Ranch Hand
Posts: 381
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The above link gives only a primary knowlege of var-args and a lot of things is missing...
 
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ranchers,

We know that at compile time a vararg is converted to an array.

Thus after compilation the code may look something like this :

public class VarArgs {

// static void vararg(long ... x) {
static void vararg(long[] x) {
System.out.println("long...");
System.out.println(x instanceof Object); // returns true;
}

// static void vararg(Integer ... x) {
static void vararg(Integer[] x) {
System.out.println("Integer...");
System.out.println(x instanceof Object); // returns true;
}

public static void main(String [] args) {
int i = 5;
vararg(5,5);
}

}

Now while calling the method varag, lets say its arguments get converted to an Object of some array type.
Now there are 3 possibilities for this array type � It can be either converted to long[], or Integer[] or Object[].

So lets modify the main method a bit for these arrays. Now the code looks as shown below:

public class VarArgs {

// static void vararg(long ... x) {
static void vararg(long[] x) {
System.out.println("long...");
System.out.println(x instanceof Object); // returns true;
}

// static void vararg(Integer ... x) {
static void vararg(Integer[] x) {
System.out.println("Integer...");
System.out.println(x instanceof Object); // returns true;
}

public static void main(String [] args) {
int i = 5;
Object[] obj = {i,i};
long[] ln = {i,i};
Integer[] in = {i,i};

//vararg((Integer[])obj); // gives runtime exception ClassCastException
// vararg((long[])obj); // compilation error of inconvertible type
vararg(ln);
vararg(in);
}

}

Now for the above code it gives error if converted to Object[]. Thus the possibility of the vararg method�s arguments getting converted to Object[] can be canceled.

But the above code runs fine for both long[] and Integer[] if the arguments of vararg method are converted to any one of that type.

Thus compiler is showing ambiguous method call error during compilation of our original problem. B�cos compiler is confused as to which type of array it should convert the arguments of vararg method.

I guess I sound somewhat logical here.


regards
Saurabh
 
Sanjeev Singh
Ranch Hand
Posts: 381
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another question raises:
is
Why ( 1 ) gives Runtime ClassCastException ?
Why ( 2 ) give compilation error ?
 
Saurabh Vyas
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
1) Runtime Exception comes because we are trying to cast the object of a Parent class to its child class. This is not possible. We can cast an object of child to that of a Parent but can not cast a Parent to a Child.

2) Compilation error comes because both the array types are inconvertible.
 
Saurabh Vyas
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It would be a Runtime Error and not Compile time error.
 
Ranch Hand
Posts: 10198
3
Mac PPC Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I see that this post has slowly deviated to reference casting. So I'm presenting here my way of interpreting things when it comes to reference casting. I'm showing it here in terms of words rather than in sentence.

You can never assign a superclass reference to a subclass refernce without a cast to that corresponding subclass which otherwise would result in a compile time error (without a cast). At the same time, if the superclass reference variable has an object of superclass type itself, then the result of that assignment(assigning superclass reference to a subclass type with casting of subclass) would result in a run time ClassCastException.

Here is the code view,

class Super{}
class Sub extends Super{}

Super s = new Super();
Sub ss = (Sub)s //would result in run time ClassCastException

but saying,

Super s = new Sub();
Sub ss = (Sub)s //would work fine

I hope this helped.
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi ranchers,


thanks to Sanjeev for this interesting question. And also thanks to Ganesh, who found out that it has nothing to do with Boxing, as the same behaviour occured, when the parameter type of the second method was changed from Integer to int.


I was surprised in this behavior in simply not compiling.
By the way, compiler says:
reference to vararg is ambiguous, both method vararg(long...) in Vararg and method vararg(java.lang.Integer...) in Vararg match
vararg(5,5);
^
in Sanjeev's version and

reference to vararg is ambiguous, both method vararg(long...) in Vararg and method vararg(int...) in Vararg match
vararg(5,5);
^
in Ganesh's version of the problem.



I think it cannot compile, because the compiler cannot say, what the most specific method is.
The criteria by which it decides this are rather complicated in the Language Specification, but I think in the end, the compiler cannot dexide.



This strange behaviour occurs only with primitive varargs. If all the varargs are Objects, there is no ambiguity.


And for primitives, the ambiguity occurs only, when one arguments is the smallest (as in the example, an int where the parameter lists were int... and long...).

So in this example, only one line would not compile if commented in, the bold one:



the other five lines calling the method print five times "double...".


If you change for example the vararg(byte... to (int... then the lines that call the method with the short or int won't compile as well.




I guess, to really understand why it is so, you got to work through this conditions in the language specification (see link above). But I think there would be a high risk of falling asleep and then you have the pattern of the keyboard on your forehead.


I said, you won't find this strange behaviour when you have only Wrapper (or any object) classes:





Compiles and prints out the expected. The class should get a different name.




Yours,
Bu.

---
to all (most) of the US cowboys: Have a funny election day!

sorry, I accidently deleted one sentence, I put it in again, these are the two edits.


[ November 07, 2006: Message edited by: Burkhard Hassel ]
[ November 07, 2006: Message edited by: Burkhard Hassel ]
 
Ranch Hand
Posts: 34
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Saurabh Vyas:

Thus compiler is showing ambiguous method call error during compilation of our original problem. B�cos compiler is confused as to which type of array it should convert the arguments of vararg method.


class Vararg {
static void vararg(long ... x)
{ System.out.println("long..."); }
static void vararg(Integer ... x)
{ System.out.println("Integer..."); }
public static void main(String [] args) {
int i = 5;
vararg(5,5);
}
}


?

--------------------

Thanks
Sanjeev KS
Posts: 60 | Registered: Nov 2006 | IP: Logged
Jae Stryker
greenhorn
Member # 137135

posted November 07, 2006 01:46 AM Profile for Jae Stryker Send New Private Message Edit/Delete Post Reply With Quote It doesn't compile.

However I've changed the code slighty to try and help you along

code:


class Vararg {
static void vararg(String ... x)
{ System.out.println("String..."); }
static void vararg(Integer ... x)
{ System.out.println("Integer..."); }
public static void main(String [] args) {

int i = 5;
vararg(i,i);

String testOne = "TestOne";
String testTwo = "TestTwo";
String testThree = "TestThree";
//vararg(testOne,testTwo,testThree); Now there is no Error
}
}

I agree with Saurabh as this program dosen't produce any error , if we do not attempt to call these ambiguous overloaded methods
 
Atul Shukla
Ranch Hand
Posts: 34
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thank you so much Burkhard!! that was a very nice explanation..

i am really not able to get into that horrable language Specification!!

 
Sanjeev Singh
Ranch Hand
Posts: 381
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ranchers,

reference to vararg is ambiguous, both method vararg(long...) in Vararg and method vararg(java.lang.Integer...) in Vararg match
vararg(5,5);
^



To understand this problem I have tried to find out what compiler does when it finds the var-args?
Considering our example


Lets us first recall the rules associated with Boxing,Var-Args and Widening.
  • Primitive widening uses the "smallest" method argument possible.
  • Used individually, boxing and var-args are compatible with overloading.
  • You CANNOT widen from one wrapper type to another. (IS-A fails.)
  • You CANNOT widen and then box. (An int can't become a Long.)
  • You can box and then widen. (An int can become an Object, via Integer.)
  • You can combine var-args with either widening or boxing.


  • Considering that there is only one method-method 1.This is what I gets when I compile the code and then again decompiled it...

    In the above code the comiler has followed the rules stated i.e.
    Primitive widening uses the "smallest" method argument possible.
    You can combine var-args with either widening or boxing.

    the integer type is first widened into long and then converted into long array.

    Now consider the second schenario when method 1 is missing and only method 2 exists.This is what i get after compilation and decompilation.

    int has been wrapped into Integer... no problem
    Now since both the overloaded method are valid and is sticked to the rules stated above,when used individually.Also there is no precedence rules in such cases... the API writter might have missed it .... or they may not because both the feature Boxing and varargs are Java5 features.

    So is the ambiguity....This is how I tried to understand the problem.

    Again a question get raised while doing cognitive operation on this proble.

    Why the compiler has inserted transient in the all the static method,though transient are meant for the instance variables?
    [ November 08, 2006: Message edited by: Sanjeev Kumar Singh ]
     
    Greenhorn
    Posts: 26
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi All,

    The ambiguity is because of the rule that Sanjeev has highlighted.
    "You can combine var-args with either widening or boxing."

    Which is same as,
    "You cannot combine var-args with both widening and boxing"

    Coming to transient being used for methods,

    It is mainly because of obfuscation in java(try to make the decompiled code not readable and/or recompilable).

    You can also see java keywords like for,if etc., used for method names in decompiled code.

    I found the below link usefull to understand obfuscation,
    http://today.java.net/pub/a/today/2004/10/22/obfuscation.html

    - Ramu
     
    Burkhard Hassel
    Ranch Hand
    Posts: 1274
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi Ramu,

    I though that this was the explanation in the first place. But it is not.
    Please test the code posted by Ganesh first near the beginning of this thread.
    I'll repaste it here skipping the unused line:



    Does not compile due to ambiguity, and there is no Boxing in here.


    Yours,
    Bu.
     
    The problems of the world fade way as you eat a piece of pie. This tiny ad has never known problems:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic