• 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
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Varargs and arrays - Mughal's mock exam, question 60

 
Ranch Hand
Posts: 241
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
from Mughal's mock exam, question 60:



I have a problem with line 6. As far as the generic print method is concerned, the element <E> is a String array, right? So the varargs E...src would be an array of String arrays?

How do the Strings "9" and "6" get interpreted as being an array of Strings? They are passed to the print method individually...
 
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chandella Montero wrote:How do the Strings "9" and "6" get interpreted as being an array of Strings?



the second argument "6" interpreted by the compiler as new String[]{"6"} . so it matches the parameter E ... src again it is interpreted as Object[] src.

For better understanding I do suggest you to use decompiler on .class file
 
Ranch Hand
Posts: 144
Oracle Fedora Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Edit: comment removed after having access to compiler
 
Greenhorn
Posts: 17
Slackware Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Seetharaman Venkatasamy wrote:
the second argument "6" interpreted by the compiler as new String[]{"6"} . so it matches the parameter E ... src again it is interpreted as Object[] src.
For better understanding I do suggest you to use decompiler on .class file



I still didn't understand
can you give me more details?
I've decompiled and opened the .class file but I didn't understand much
and I've made this test inside print method:



both return true
so I've found the correct types (I think)
but I still can't understand why src is an Object[] and not a String[]
thanks
 
Ranch Hand
Posts: 49
Java ME PHP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Generics are a facility of allowing "a type or method to operate on objects of various types while providing compile-time type safety".so
common use of this feature is when using a Java Collection that can hold objects of any type, to specify the specific type of object you will be storing in it.so it depends on the objects types.and you can not directly that both of them are String..

when it is come to "String" they always create a new object in the memory so each time you pass a "String" value there is new object.so I'll explain line by line.


"E e" means you can pass any types of single value.
"E... src" means you can pass any types of multiple value
that belongs to same type.means array reference.
so it could be a 0-any number of length array.so you can pass value only if you need.



"E elt" like "E e". "sre" is an array refrence.(I think you know it.if you don't please check about it
about foreach)


this is a String type array object
you pass 1 value to first"E e" and 1 value to the second"E... src"


you pass "sa" array to the first and no value to the second.yes you can do because array length can be 0-any number

you pass 1 value as "sa" to first parameter and to the scened parameter pass "sa" array then it prints "sa" values

you pass 1 value as "sa" to first parameter and to the scened parameter pass "sa" 2 time
means that "sre" array now seems like this src[0]=sa ,src[1]=sa now "" is an object array

as I told you every single String create new Object "9" "6" both create individual objects.and referenced
to "src" array src[0]="9" ,src[1]="6" but these are objects not just a Strings.when we print String objects
it prints the real String value because there is a method call toString() in String class.but still String is an object type

try this code



 
deca leni
Ranch Hand
Posts: 49
Java ME PHP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

deca leni wrote:Generics are a facility of allowing "a type or method to operate on objects of various types while providing compile-time type safety".



if more explanation let me know..
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jeane Lindford wrote:



what happened when you run System.out.println(src instanceof String[]); ?

actually all the generic information is erased by the compiler at compile time. so all the types T are replaced by the super type of object i.e, java.lang.Object. this type eraser introduced for the backward compatibility.
 
T Vergilio
Ranch Hand
Posts: 241
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Deca, I tried compiling and running your code, and indeed, it seems like what is passed to the method is an Object, followed by an Object array.

I still don't get why

public static <E> void print(E e, E...src)

compiles without warnings. Doesn't the compiler check that E is used to refer to the same type at compile time?

And how come if I change the class declaration to:

public static <E, Y> void print(E e, Y...src)

and the for loop declaration to I get a warning:

Can anyone explain? This is driving me insane!
 
deca leni
Ranch Hand
Posts: 49
Java ME PHP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
yep you right...look at here


though you pass 2 parameter values, it prints only values of "E...src".
"E elt" variable reference. it gets the current value of the "src" array value.
this is how loop work.
in first round "E elt" gets the src[0] then and print
in next time "E elt" gets the src[1] then and print
in next time "E elt" gets the src[2] then and print
so on until it reach the end of the array.

remember, the disasters happen at runtime not the compile time.most of compilers generate warnings to tell you when you are using a unsafe(non-generic) collection.non generic is quit happy to hold anything that is not primitive.so programmer have to be careful.
generic code(type safe) can be integrated with legacy(non-generic) code after java5 .the code I gave you is not generic safe.but think generic as strictly a compile time protection. the compiler uses generic type (the <type> in the angle brackets) to make sure that your doesn't put the wrong thing in to a collection.and that you don't assign what you get from a collection to the wrong reference type.But none of this protection exists at run time.that's why the disasters happen at runtime.

BUT this is different from Arrays.
they give both compile/run time protection.

try this code..

 
deca leni
Ranch Hand
Posts: 49
Java ME PHP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
try to learn about Generic and Collection class of Java DOC then you'll be able to get more information about this..
 
Jeane Lindford
Greenhorn
Posts: 17
Slackware Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've made



and both returned true
so the first one was transformed in a String and the second one in a Serializable array, not an Object as I was thinking (but since an instantiated Serializable is an Object, it passes the IS-A test [and an Object[] can receive any kind of not primitive array])
oh man, this is driving me crazy too lol
I think I need to understand better the rules of generics types transformation... where I can find this info?
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Windows XP Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jeane Lindford wrote:
I think I need to understand better the rules of generics types transformation... where I can find this info?



always *google* is there to help you. however *Core Jva volume-1 by Horstmann* book is fantastic on generics .

Note: for your information, String implements serializable
 
Ranch Hand
Posts: 179
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is a tricky topic, atleast imho, and I would also have reasoned like the original poster at first - thinking E would be String[] and src a String[][].

Here's what I think is going on instead, and I may very well be wrong....

For some reason, for a method call of the type:



... the compiler is deciding that the generic type E should be java.io.Serializable.

This works fine for a String array, since this implements Serializable. What happens next is that for the vararg call, the two arguments "9" and "6" are stuffed into a Serializable[], basically since they are both Strings they are a match for a "Serializable...v" vararg method signature, which is why we end up with a Serializble[] called 'src'.

I believe this is what happens, and if I were to guess I think that the reason is this: Serializable is the first superclass (yes I know it's an interface, but we're talking about an IS-A test in essence, class or interface), to which both a String[] and a String can be converted. Obviously I would say this is a very simplified explanation, but in essence I think that's the reasoning that the compiler goes through when it attempts to lock down what the type E should be for this method invocation, with these specific arguments.

One thing I can say for sure though for generic methods, with dual parameters referring to the generic type: the first argument to the method NOT necessarily the type that sets the rules for what the type E should be for any said method invocation. It may very well be the second argument, so don't be fooled looking only at what was the first argument sent, the generic type may well be locked down decisively by what was passed in as a second argument - in my experience it all depends on what you send in and what those arguments can be converted to in order to match the method signature.

// Andreas
 
Ranch Hand
Posts: 206
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

See my comments and analysis below for more info...hope it help.



 
T Vergilio
Ranch Hand
Posts: 241
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey Tommy, Creating Generic Methods is on page 627 in my book by the way Yeah, I re-read that part. But it doesn't mention anything about var-args or arrays being passed to var-args methods. Looking at the comments in your code, am I right to say that any array of any type passed to a var-args method is ALWAYS read as a Serializable?

I've been experimenting....

and look what I got:


Look at lines 7, 8 and especially 9

Running the program, I get for the last three print calls:

--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true
|
--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true
|[I@19821f|

--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true
|9|
6|



So... an array of primitives (ints) is of type Object[]?!
 
Tommy Delson
Ranch Hand
Posts: 206
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chandella Montero wrote:Hey Tommy, Creating Generic Methods is on page 627 in my book by the way Yeah, I re-read that part. But it doesn't mention anything about var-args or arrays being passed to var-args methods. Looking at the comments in your code, am I right to say that any array of any type passed to a var-args method is ALWAYS read as a Serializable?



That's correct, you won't find anything about "var-args or arrays being passed to var-args methods". What I meant is in combination of all, if you need to understand more about var-args and arrays reread these topics in K & B or others, after all you'll understand why and clear your doubt.

Also, this type of scenarios also included "Overloading Made Hard—Method Matching", you can check this topic on page 248 K & B book for more insight.




I've been experimenting....

and look what I got:

Look at lines 7, 8 and especially 9

Running the program, I get for the last three print calls:

--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true




Let's dissect, analyze, and find out why.

Your caller: print(in); //(7) prints all right

The calling method actually is "print(int e);" so, let's see if it makes sense on your instance check.

e value is type of String:false - Yes it's true, "e" value is an int not a String.
e value is type of String arry:false - Yes it's true, "e" value is an int array not String array. If your check is "e instance of int[]" then it's true, but not "e instance of Integer[]" .

sre value is type of object array:true - It's true an int is type of Object because the print() method does an auto boxing on the value you're passing in the method.

Autoboxing: int =>boxing to Integer => boxing to Number => boxing to Object

That's why it return true even thought you're passing an array in[] type int in the print() method.


I'll leave the rest to you to analyze and find out why, hope it help.





|
--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true
|[I@19821f|

--------------------
e value is type of String:false
e value is type of String arry:false
sre value is type of object array:true
|9|
6|

So... an array of primitives (ints) is of type Object[]?!
 
We cannot change unless we survive, but we will not survive unless we change. Evolving tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic