Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Using == operator on wrapper classes

 
Prathima gaitonde
Ranch Hand
Posts: 130
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

I have this code below:



The out put of the program is true.
Now, as per my knowledge == checks for value of 2 operators. i being an object its address should be compared with 10 and return false,
1>How is it true then?
2>Is it i.intValue() before comparison?
3>As per my understanding element.intValue() is called only when wrapper is assigned to primitive. Is it not true?
4>Is element.intValue() is called in every operation? Like increment, decrement... etc?
5>If this is true, then why is it compile time error to compare object of different classes ( especially in wrapper classes) with == operator?
example: Why is it not s.intValue()==i.intValue()?
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, intValue() isn't called. In the first example they are actually referencing the same object. The run-time keeps a cache of Integer objects within a certain range and will re-use those when it can. This is safe because Integer objects are immutable.

You should still always use equals() with wrappers, though.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Matthew Brown wrote:No, intValue() isn't called. In the first example they are actually referencing the same object.

That's not true at all! In the 1st example an Integer (variable i) and an int (variable j) are compared. When == is used to compare a primitive to a wrapper, the wrapper will be unwrapped and the comparison will be primitive to primitive. That's why true is printed!

Here is a very simple code snippet comparing a primitive with a wrapper:

After decompiling the .class file you'll get this code:

So the intValue method is definitely used!

Matthew Brown wrote:The run-time keeps a cache of Integer objects within a certain range and will re-use those when it can. This is safe because Integer objects are immutable.

These both statements are correct! And for the OCAJP7 exam you'll (unfortunately) need to know that range. For Integer it's -128 to 127 (inclusive). Important note: this cache is only used when the autoboxing feature is used! If you use the new operator when you create the wrapper instance, this cache is not used. If you want to know the reason why, you should definitely read this post, it's very well explained by Jesper de Jong. And another important note: although you can compare a short and an int using ==, you can not compare a Short with an Integer using == (you'll get a compiler error if you try to do so ).


Now that you (hopefully) have learnt a lot about primitives, wrappers and the == operator, it's time to have some fun!

For each line you have to determine if the line compiles successfully. And if it does, what will be the output of this line (of course only for the System.out.println statements). Good luck!


Hope it helps!
Kind regards,
Roel
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:
Matthew Brown wrote:No, intValue() isn't called. In the first example they are actually referencing the same object.

That's not true at all! In the 1st example an Integer (variable i) and an int (variable j) are compared. When == is used to compare a primitive to a wrapper, the wrapper will be unwrapped and the comparison will be primitive to primitive. That's why true is printed!

Ah. I was going too fast - carelessly thought it was comparing two wrappers rather than a wrapper and a primitive (that's also a very common question). Sorry!
 
Prathima gaitonde
Ranch Hand
Posts: 130
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Roel Ok, Now my understanding... as usual, correct me if I am wrong.

Point A:
1> Integer i=10; will be created in cache. whose address say add1.As Integer cache range from value -128 to 127.
2> Integer j=10; will get add1 from the cache.
3> Integer k=129; is never created in cache it will be create in heap whose address say add2.
4> Integer y=new Integer(10); same as k say its address add3.

Therefore, above only i==j is true rest are false.

Point B:
When wrapper is compared with primitive, No matter whether they are of same type or not the wrapper class call method intValue() before comparison
so..
int x=10;

x==y;//true
x==i;//true

Now the analysis of the program below.



Couple of things I dint get,

1> Like Integer, is there cache mechanism for char,byte,short,long,float,double?
2> Is cache mechanism same as String pooling?
3> Why cant we compare object of different class with ==? Why cant it be Short.intValue==Integer.intValue()?
4> On line no. 19, is it Short.doubleValue() called?
5>Finally I dont get the behaviour of Number!!! Why is it compile time error while comparing with primitives? Why is it true only with Integer comparison?
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This will probably result in quite a long post. Sit tight and fasten your seatbelt. Here we go!

Prathima gaitonde wrote:Point A:
1> Integer i=10; will be created in cache. whose address say add1.As Integer cache range from value -128 to 127.
2> Integer j=10; will get add1 from the cache.
3> Integer k=129; is never created in cache it will be create in heap whose address say add2.
4> Integer y=new Integer(10); same as k say its address add3.

Therefore, above only i==j is true rest are false.

Spot-on!

Prathima gaitonde wrote:Point B:
When wrapper is compared with primitive, No matter whether they are of same type or not the wrapper class call method intValue() before comparison
so..
int x=10;

x==y;//true
x==i;//true

Not completely true! When a wrapper is compared with a primitive using ==, the wrapper is unwrapped. That's true! But which method is invoked/called depends on the type of the wrapper. If your wrapper is of type Integer, then indeed the intValue method will be called. But if it's a Short, then it's the shortValue method. For a Long wrapper, it's the longValue method. And a Double wrapper is unwrapped using the doubleValue method.

I hope everything is clear until this point. Time to take a deep breath before we start analysis of the program.


Let's start with this tricky statement This does not compile! As you (should) know, every integer literal (and operation with integers) result in an int. So 10 in line8 is an int. So the Java compiler knows an int should be autoboxed into an Integer, so it uses this code Integer.valueOf(10) resulting in this statement Double myDouble2 = Integer.valueOf(10);. So your assigning an Integer to a Double which are 2 different types, so you'll get a compiler error. That was sneaky, isn't it? Some other qneaky code examples which will not compile are:
Byte myByte1 = 150; // should be <= 127
Long myLong1 = 10; // should be 10L
Float myFloat1 = 10; // should be 10F
Float myFloat2 = 10.0; // should be 10.0F



Correct! All these statements print true. Reason: point B. Wrappers are unwrapped/unboxed and 2 primitives are compared.


This statement is again a little tricky, but indeed does not compile. You may think the Java compiler will simply unbox this value as well (like with the other statements). But although Number is the (abstract) parent class of concrete classes Integer, Long, Float,... boxing/unboxing does not work with Number. The Java compiler needs to know exactly what type of number it's dealing with to perform the boxing/unboxing. So it works with the concrete types like Integer, Long, Float,... not with the abstract Number.


Again correct! Reason: point A. On line14 2 cached Integers are compared (which prints true). On line15 1 cached Integer and another newly created Integer are compared (which prints false).


Both these statements will indeed not compile. The reason is the same: incompatible types! Although Short and Integer (and Double) share the same parent class (Number) these types are completely different from each other. Integer IS-NOT-A Short and Integer IS-NOT-A Double. Instances of different types can never be the same, so the compiler doesn't allow you to compare them using the == operator. Maybe this sounds a little bit weird, because both contain the same value (10), but their type is completely different (Short vs Integer vs Double). It's similar to Cat and Dog, both are Animals and can have the same name (e.g. "Max"), but can never be the same! That's exactly the same as with Short and Integer (and any other wrapper type).
Another nice to know: if you would compare a Short and an Integer both having the same value (e.g. 10), false will be returned. So myInteger1.equals(myShort1) will always return false. Reason: the equals method of a wrapper class will only return true if and only if the argument is not null, has the same type and contains the same value as this object.


Let's have a look at this tricky statement. It prints indeed true. But why? First of all, this code compiles successfully. No compiler error like with line16 and line18. So no incompatible types here, because these types are not different from each other. Integer IS-A Number. Now let's look at line6: Number myNumber1 = 10;. We already know this 10 is an int and thus the compiler will wrap/autobox it into an Integer using Integer.valueOf(10) resulting in this statement: Number myNumber1 = Integer.valueOf(10);. And because 10 is in the range of cached values (-128 to 127, inclusive), the same cached instance as myInteger1 (and myInteger2) will be returned. So myInteger1 and myNumber1 refer to the same instance, hence the == operator returns true.

Hang on! We are almost there


This statement prints indeed true. Reason: point B. Wrapper is unwrapped/unboxed and 2 primitives are compared.


This statement does indeed not compile for the same reason as line16 and line18 (Double and Short are incompatible types).


Now the last tricky statement. This statement prints indeed false. The explanation is very similar to line17. It compiles successfully, because Short IS-A Number. And we know (from explanation line17) that myNumber1 refers to the same cached Integer instance as myInteger1. So myNumber1 can never refer to the same (cached) Short instance as myShort1, hence false is printed.

Prathima gaitonde wrote:1> Like Integer, is there cache mechanism for char,byte,short,long,float,double?

Yes! Only for:
  • Boolean
  • Byte
  • Character from \u0000 to \u007f (7f is 127 in decimal)
  • Short and Integer from -128 to 127 (inclusive)


  • Prathima gaitonde wrote:2> Is cache mechanism same as String pooling?

    Yes! These internal caches help to avoid creating redundant objects for frequently used values.

    Prathima gaitonde wrote:3> Why cant we compare object of different class with ==? Why cant it be Short.intValue==Integer.intValue()?

    Because unboxing (unwrapping) only happens when you compare a primitive with a wrapper using the == operator. Let's say your proposed behavior is implemented in the Java compiler, then you will never be able to compare if 2 Integer reference variables refer to the same Integer instance (even if you exactly wanted this behavior). Because myInteger1 == myInteger2 will be changed into myInteger1.intValue() == myInteger2.intValue(). With the current implementation, you can still do both.

    Prathima gaitonde wrote:4> On line no. 19, is it Short.doubleValue() called?

    No. This is the decompiled version of line19. Disclaimer: you don't need to know this (the decompiled) code for the OCAJP7 exam.
    System.out.println((double)myShort1.shortValue() == 10D);

    Prathima gaitonde wrote:5>Finally I dont get the behaviour of Number!!! Why is it compile time error while comparing with primitives? Why is it true only with Integer comparison?

    I already explained this behavior when I covered all the different statements. But in short: myNumber1 was referring to the same Integer instance as myInteger1 (and myInteger2). If you would change line6 to Number myNumber1 = 10;, you'll get some other values in the output (because now it's a Double which doesn't use a caching mechanism). Something for you to try out


    Phew! If you made it until here and you understand everything, you deserved a little break with a cup of coffee and a (big) slice of pie That's all folks!

    Hope this helps!
    Kind regards,
    Roel

    PS. That's probably the longest answer I posted since I joined CodeRanch 10 years ago. And will probably be hard to beat
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi @Roel, As you said, at this point I am unable to digest everything, in your post. I will get there in few hours(hopefully!!!), after writing different code, that came into my mind as doubt while going through your post, Here I would like to say that, have never met a person like you before(at least not online), who has so much patience, so good hold on the subject (Even few of them those who have, but definitely dont have big extending hand of help, some were impatient) and sooo much clear and detailed explanation about each of my query!!!. Please keep up the good work, people like me need this kind of support.....

    I will write again, on this post as soon as I get hold of each point explained by you.

    Real big thanks,
    With great, great respect
    Prathima
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    My understanding on this topic.

    1> Double d=10;

    Here 10 is an int primitive, d is an object hence, primitive should be promoted to object, so...

    d=Integer.valueOf(10);//compiler try to promote.

    d being Double and sibling of Integer says to the compiler, Hello I am not Integer, I am a double. Hence compile time error.

    2> Number is an abstract class, and is a super class of wrappers, so...

    Number n=10 or 10.0 or 10.0f or 10L all are fine as Integer, Long, Double, Float, Short, Byte, Character all are subclass/Children of Number.

    Catch mechanism is same with the number, If its assigned a value which is in catch then address of that object will be return.

    Hence, from original example:

    Number myNumber1 = 10;
    Integer myInteger1 = 10;
    Integer myInteger2 = 10;




    3> When a primitive is compared with wrapper, its respective method is called, ex: for Integer with any primitive, Integer.intValue() and then 2 primitives are compared,

    But Number, is there a equal primitive value called num? Oh!!!, no compiler shouts, so

    Number n==int i ;//Number.numValue() no such method exists hence compile time error.


    4>Double d==Integer i

    No Cat is indeed different from Dog (Might be they are sharing the name, I don't care), I am not a fool to compare them says the compiler!!!

    5>Nice to know tip....

    Integer i=new Integer(10);
    Short s=new Short(10);

    i.equals(s)//false

    Thanks again as, same thing when I posted as a doubt in some other forum, one of the sample, impatient answer I got was, you need to read more on equals and ==. One line thats it.
    Then, after that I came to this forum and wanted to know equals() in wrapper classes
    http://www.coderanch.com/t/643266/ocajp/certification/equals-method-overridden-String-Wrapper this post and this person Sergej Smoljanov helped me a lot. I am really thankful to both, i.e this site and that person.

    Chat appart answer for point 5 is equals method in all the wrapper class(and String) first checks for the same instance then, the value.

    6>Integer i=new Integer(10);
    Integer j=10;
    Why is it not, i==j, be i.intValue()==j.intValue()?

    If this is what compiler does than, How can I compare the address of i and j for equality?

    7>Still not 100% clear point is,

    Short s=10;

    s==10.0// No compilation issue as s calls shortValue() i.e, s.shortValue()==10.0

    Here right hand operand is primitive, remains primitive, and its double. No question of it getting changed.
    Left hand operand is an object, which now has to be converted as primitive, and it will allways call its respective wrapper method as explained it point 3. so s.shortValue() is called,
    Doubt :
    1>((double) s.shortValue()) Is this a casting? How does this work, though I do understand that, short s=10, double d=10.0, s==d are equal but don't know much about, compiled code, i.e how does it work internally!!!. First int is assigned to short, second short is compared with double

    8> Finally I did try this:

    Double d=10.0;
    Number n=10.0;

    d==n// No compilation issue as d is n. prints false as, Double are never cached, hence d and n are separate objects.

    Where as

    short s=10;//A primitive value short

    Number n=s;// Object 10 catched into short. Its address say add1

    Short myShort=10;//gets add1

    myShort==n//true

    Please, please correct if any of the statement(s) is/are wrong, as it would mislead others as well.

    With kind and heartfelt regards,
    Prathima
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:1> Double d=10;

    Here 10 is an int primitive, d is an object hence, primitive should be promoted to object, so...

    d=Integer.valueOf(10);//compiler try to promote.

    d being Double and sibling of Integer says to the compiler, Hello I am not Integer, I am a double. Hence compile time error.

    Correct!

    Prathima gaitonde wrote:2> Number is an abstract class, and is a super class of wrappers, so...

    Number n=10 or 10.0 or 10.0f or 10L all are fine as Integer, Long, Double, Float, Short, Byte, Character all are subclass/Children of Number.

    Catch mechanism is same with the number, If its assigned a value which is in catch then address of that object will be return.

    Hence, from original example:

    Number myNumber1 = 10;
    Integer myInteger1 = 10;
    Integer myInteger2 = 10;


    Almost correct! One small remark: you probably mean "cache mechanism" (instead of "catch mechanism") and "cached object" (instead of "cathed object"). One (very) big mistake: although char is an integral type, Character IS-NOT-A Number; so it's not a subclass of Number at all. But it's still a primitive wrapper class, so you can still use autoboxing (and unboxing) as the following code snippet illustrates:



    Prathima gaitonde wrote:3> When a primitive is compared with wrapper, its respective method is called, ex: for Integer with any primitive, Integer.intValue() and then 2 primitives are compared,

    But Number, is there a equal primitive value called num? Oh!!!, no compiler shouts, so

    Number n==int i ;//Number.numValue() no such method exists hence compile time error.

    True! To unwrap a Number, the compiler must know its concrete type (Integer, Long, Byte, Float,...); otherwise you'll get a compiler error.


    Prathima gaitonde wrote:4>Double d==Integer i

    No Cat is indeed different from Dog (Might be they are sharing the name, I don't care), I am not a fool to compare them says the compiler!!!

    True! The compiler doesn't allow to compare 2 reference variables of different (concrete) wrapper classes using the == operator. Although you are allowed to compare different primitives with each other using the == operator.

    Prathima gaitonde wrote:5>Nice to know tip....

    Integer i=new Integer(10);
    Short s=new Short(10);

    i.equals(s)//false

    Spot-on!

    Prathima gaitonde wrote:Chat appart answer for point 5 is equals method in all the wrapper class(and String) first checks for the same instance then, the value.

    Probably just a wording issue, you probably mean the exact same thing but you have just phrased it incorrectly. The equals method (of the wrapper classes) checks if the parameter (argument) has the same type. So when you call i.equals(s), the equals method of Integer checks if variable s is also an Integer. If it isn't it returns false; otherwise the primitive values are compared.

    Prathima gaitonde wrote:6>Integer i=new Integer(10);
    Integer j=10;
    Why is it not, i==j, be i.intValue()==j.intValue()?

    If this is what compiler does than, How can I compare the address of i and j for equality?

    Indeed! If compiler would always use intValue when the == operator is used, it would be a huge limitation of the Java language. Because you can't compare addresses (objects) anymore to check for equality.

    Prathima gaitonde wrote:7>Still not 100% clear point is,

    Short s=10;

    s==10.0// No compilation issue as s calls shortValue() i.e, s.shortValue()==10.0

    Here right hand operand is primitive, remains primitive, and its double. No question of it getting changed.
    Left hand operand is an object, which now has to be converted as primitive, and it will allways call its respective wrapper method as explained it point 3. so s.shortValue() is called,
    Doubt :
    1>((double) s.shortValue()) Is this a casting? How does this work, though I do understand that, short s=10, double d=10.0, s==d are equal but don't know much about, compiled code, i.e how does it work internally!!!. First int is assigned to short, second short is compared with double

    No need to doubt, that's indeed a cast! It's no magic at all. It's just telling the compiler: i know this variable is a short, but I want to use it as a double. To understand the == operator on wrapper classes, you don't need to know more about casting. But you need to know casting (and its intricacies) for the OCAJP7 exam, so when you are studying about casting and you have some doubts, just start a new thread.

    Prathima gaitonde wrote:Double d=10.0;
    Number n=10.0;

    d==n// No compilation issue as d is n. prints false as, Double are never cached, hence d and n are separate objects.

    True! But 2 remarks:
  • You can't say d is n in this example. You mean: Double IS-A (or is a subclass of) Number
  • d and n are separate objects is an incorrect statement as well. d and n are reference variables, so it would be better to say: d and n refer to separate objects

  • Both remarks result in this valuable tip: It's very important you (learn to) use the correct jargon. Otherwise you can't communicate correctly with other java developers.

    Prathima gaitonde wrote:Where as

    short s=10;//A primitive value short

    Number n=s;// Object 10 catched into short. Its address say add1

    Short myShort=10;//gets add1

    myShort==n//true

    True as well!

    Hope it helps!
    Kind regards,
    Roel
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks, I will take your each point, and definately work on my wordings.



    "The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive)."

    I think this is the reason for, behavior of the above code

    Regards,
    Prathima
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:"The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive)."

    I think this is the reason for, behavior of the above code

    Spot-on!

    That line will only compile if you add the cast, like in this statement:


    With this cast to char, you simply tell the compiler: "hey dude, I know 67500 is too big to fit in a char, but I know what I'm doing, I'm a smart cookie, just treat it as a char and stop complaining". And the compiler will treat it as a char and (auto)box it into a Character without complaining. Everybody happy

    Kind regards,
    Roel
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Roel,



    The Out put of the above code is ?,?,? in my computer.
    Is it depends on the compiler? I mean to say Does out put of this program, differ from computer to computer?
    The reason I am asking this is, If such questions were asked in the exam, is the out put unpredictable?

    Regards,
    Prathima
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:The Out put of the above code is ?,?,? in my computer.
    Is it depends on the compiler? I mean to say Does out put of this program, differ from computer to computer?
    The reason I am asking this is, If such questions were asked in the exam, is the out put unpredictable?

    The output on my computer would probably be also ?,?,?

    It has nothing to do with the compiler. The compiler just compiles your program. The output is created at runtime (not compile time).

    The reason is fairly easy. Each integer between 0 and 65535 (inclusive) represents a character. But that could be a character from the Chinese alphabet. But my computer (and probably your's too) doesn't know how to represent this character, because it only knows characters from the Latin alphabet, so it shows a question mark instead. For the exam you don't need to know which integer corresponds with a character. That should be a huge relief!
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks.
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:
    Prathima gaitonde wrote:1> Double d=10;

    Here 10 is an int primitive, d is an object hence, primitive should be promoted to object, so...

    d=Integer.valueOf(10);//compiler try to promote.

    d being Double and sibling of Integer says to the compiler, Hello I am not Integer, I am a double. Hence compile time error.

    Correct!


    After so many days, I got this doubt, why Short s=150; is not a compiler error?

    s=Integer.valueOf(150);// Short=Integer!!! As valueOf() method returns Integer object.

    How can an Integer object fit into Short?
    Sorry if I am missing something which is already there in the previous discussion.

    With respect,
    Prathima

     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:After so many days, I got this doubt, why Short s=150; is not a compiler error?

    s=Integer.valueOf(150);// Short=Integer!!! As valueOf() method returns Integer object.

    How can an Integer object fit into Short?
    Sorry if I am missing something which is already there in the previous discussion.

    Very good remark! It's not yet explained in this thread.

    As you know the compiler is a very smart cookie. It knows 150 fits in a short, so it's treated as a short (instead of an int). So other code is used to box/wrap the value into an object. The decompiled code looks like:


    A little pop quiz: what happens if you use a value outside the range of a short? Like:


    Hope it helps!
    Kind regards,
    Roel
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Roel,

    Thanks for the reply,

    Roel De Nijs wrote:
    As you know the compiler is a very smart cookie.

    This compiler is too......... smart cookie, to understand.

    A little pop quiz: what happens if you use a value outside the range of a short? Like:



    Out of your quiz questions so far, this was bit easy for me . The answer is, compile time error, as short ranges from -32768 to 32767.

    With great respect,
    Prathima
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:A little pop quiz: what happens if you use a value outside the range of a short? Like:



    Out of your quiz questions so far, this was bit easy for me . The answer is, compile time error, as short ranges from -32768 to 32767.
    Spot-on!

    Now you can earn some bonus points:
    1/ how can you make this code compile? (You can't (of course) change the type of variable ss and the value must be boxed, so you can't use constructors/methods of Short)
    2/ what's the output of System.out.println(ss);?

    Kind regards,
    Roel
     
    Prathima gaitonde
    Ranch Hand
    Posts: 130
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Roel,
    Roel De Nijs wrote:
    Now you can earn some bonus points:
    1/ how can you make this code compile? (You can't (of course) change the type of variable ss and the value must be boxed, so you can't use constructors/methods of Short)
    2/ what's the output of System.out.println(ss);?


    To answer this, it was bit tricky, I new the answer is casting, but I tried this Short s=(Short)35000; which dint work, then I did this Short s=(short)35000; When this technique worked I new printing s would print negative value, but dint know exact value. The out put I got was this: -30536. Even now I cant figure out why is casting(short) works fine, and not (Short). If you can explain me this, that would be great.

    With great respect,
    Prathima
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Prathima gaitonde wrote:Even now I cant figure out why is casting(short) works fine, and not (Short). If you can explain me this, that would be great.

    I'll try to explain one step at a time with a few code examples as well.

    Let's start with a value which is in the range of short:

    When the compiler sees this code, it thinks: "hey, I'm a friendly guy (or girl), maybe I'm even your BFF Normally I would treat 150 as int. But I know you don't like typing too much and this value is in range of a short, so I'll add a cast to short for you, handle this value as a short and wrap this value into a Short". This code compiles successfully, thanks to the friendliness of the compiler

    Now let's have a look at the following code:

    Now the compiler thinks: "you know I'm a friendly guy/girl, but as 35000 is outside the range of short, I have to treat this value as an int. So this code won't compile. Sorry! Hope you are still my BFF ". And this code doesn't compile.

    Finally you can explicitly add the cast yourself as shown in this statement:

    Because you added the explicit cast to short yourself, you tell the compiler: "hey compiler, my BFF, I know 35000 is an int, but you have to treat this as a short instead. You are my good friend, so please trust me, I know what I'm doing here!". The compiler answers: "Phew, we are still BFFs. Of course I'll trust you! And to prove this, I treat this 35000 as a short and wrap it in a Short. No further questions asked". And this code compiles successfully as well.

    What a fun and instructive story!

    Now why doesn't the code compile when you cast to Short (with capital case s) as shown in this little code snippet:

    If you combine a few things you learnt the past few days/weeks abou wrapper classes and autoboxing, you'll have the answer. The important facts:
  • only primitives are boxed/wrapped
  • each integer literal is treated as an int
  • although a short fits into an int, Short IS-NOT-A Integer

  • If you combine these facts, you'll get something like: before you can cast to Short (an object type, not a primitive), the primitive 35000 needs to be boxed/wrapped first. It's an integer literal, so it's treated as an int and wrapped into an Integer. And then you try to cast this Integer to Short. That's of course impossible as Short IS-NOT-A Integer.

    This code compiles without errors:


    Hope it helps!
    Kind regards,
    Roel

    Note: for OCAJP7 and OCPJP7 exams you don't need to know how to calculate the negative value which was printed
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi,

    I went through this discussion and not able to get this one, Please help.

    Roel De Nijs wrote:

    Now the last tricky statement. This statement prints indeed false. The explanation is very similar to line17. It compiles successfully, because Short IS-A Number. And we know (from explanation line17) that myNumber1 refers to the same cached Integer instance as myInteger1. So myNumber1 can never refer to the same (cached) Short instance as myShort1, hence false is printed.



    Why is it. is it because Short myShort1 = 10; is decompiled as Short myShort1 = Short.valueOf(10) ? then also should it not refer to the same literal in the cache?

    Regards
    Sharmili
     
    Sergej Smoljanov
    Ranch Hand
    Posts: 467
    10
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:Why is it. is it because Short myShort1 = 10; is decompiled as Short myShort1 = Short.valueOf(10) ? then also should it not refer to the same literal in the cache?

    I think the explanation is pretty clear.

    The only thing I can add. You are comparing reference variables using the == operator, so it only returns true if both reference variables point/refer to the same object.

    myNumber1 refers to a cached Integer object with value 10.
    myShort1 refers to a cached Short object with value 10.

    Although a short fits into an int, Short IS-NOT-A Integer. So both reference variables definitely refer to different objects (they have incompatible types, it's like a Dog and a Cat, they never can be the same), and that's why false is printed.

    Hope it helps!
    Kind regards,
    Roel
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Am really sorry that i forgot the fact Number myNumber1 = Integer.valueOf(10);
    It just skipped out of my mind!

    Please review my understanding and let me know if am wrong

    1.XXX b=1; is decompiled as XXX b=XXX.valueOf(1);
    where XXX is any wrapper class
    2.In any primitives comparison we are just comparing only the magnitudes.
    3.
    Another nice to know: if you would compare a Short and an Integer both having the same value (e.g. 10), false will be returned. So myInteger1.equals(myShort1) will always return false. Reason: the equals method of a wrapper class will only return true if and only if the argument is not null, has the same type and contains the same value as this object.


    According to the abovelogic, should not we get a compile time error if we are trying something like this:


    Because compiler knows b1 is not of type Integer?
     
    Sergej Smoljanov
    Ranch Hand
    Posts: 467
    10
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    equals from Integer


    http://www.coderanch.com/t/643266/ocajp/certification/equals-method-overridden-String-Wrapper


    System.out.println(i1==b1); - compiler error
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sergej Smoljanov wrote:equals from Integer



    I did check the equals method of Integer, but my doubt is, compiler knows the reference type of b1, and Byte does not have a relationship with Integer, So should it not be telling us, this will never return true?
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:According to the abovelogic, should not we get a compile time error if we are trying something like this:


    Because compiler knows b1 is not of type Integer?

    No, not at all!

    The method signature of the equals method of Integer (inherited from Object) looks like:
    And Byte IS-A Object. So no compiler error. It would be a whole other story if you tried invoking the compareTo method of Integer with a Byte object.

    Hope it helps!
    Kind regards,
    Roel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:I did check the equals method of Integer, but my doubt is, compiler knows the reference type of b1, and Byte does not have a relationship with Integer, So should it not be telling us, this will never return true?

    The compiler is very smart, but lazy! It's only concerned about what's known at compile time, doesn't care about what's happening at runtime.

    The compiler checks if the call to the equals method is allowed. And that's it! Nothing more! And because equals has a parameter of type Object, the call with a Byte object is allowed.
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Can you please tell what is happening here..


    I was expecting this to print false but it prints true
     
    Paul Anilprem
    Enthuware Software Support
    Ranch Hand
    Posts: 3819
    10
    • Likes 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:Can you please tell what is happening here..


    I was expecting this to print false but it prints true


    You will keep getting such puzzlers until you read and understand this section thoroughly: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.21.1
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:Can you please tell what is happening here..


    I was expecting this to print false but it prints true

    This topic is one of the best topics in this forum. It covers (almost) everything you need to know about wrapper classes, primitives and the == operator (illustrated with tons of code snippets). So if you read it very carefully and understand everything, you won't get any puzzlers like this anymore

    In this post is explained why you get true (instead of false). You are comparing a primitive and a wrapper using the == operator, so the wrapper will be unwrapped/unboxed and thus you compare 2 ints, both having exactly the same value (8).

    Hope it helps!
    Kind regards,
    Roel
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel wrote: In this post is explained why you get true (instead of false). You are comparing a primitive and a wrapper using the == operator, so the wrapper will be unwrapped/unboxed and thus you compare 2 ints, both having exactly the same value (8).


    I completely agree to this, but i was misguided by the fact that when we use a new keyword, the integer cache is not used. So


    creates a new object in heap and


    is seen as Integer j=Integer.intValue(8); and uses the cache. So the references are different and hence i thought i==j should print false.

    To be frank, am reading this complete thread for the third time and am able to convince myself for true as well as for false!
     
    Sharmili Rameshbabu
    Greenhorn
    Posts: 27
    2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    And I found this link useful to have the overview of the conversion rules, Thanks to Paul.

    Especially the tables Table 5.1. Casting conversions to primitive types and Table 5.2. Casting conversions to reference types brings all the concepts together.
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:So the references are different and hence i thought i==j should print false.

    If you change the type of i to Integer, you'll definitely see false (and then your assumption is spot-on! )
     
    Puspender Tanwar
    Ranch Hand
    Posts: 397
    2
    Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sharmili Rameshbabu wrote:
    I completely agree to this, but i was misguided by the fact that when we use a new keyword, the integer cache is not used. So


    creates a new object in heap and


    is seen as Integer j=Integer.intValue(8); and uses the cache. So the references are different and hence i thought i==j should print false.

    To be frank, am reading this complete thread for the third time and am able to convince myself for true as well as for false!

    hello sharmili, what I learnt from this wonderful thread is:

    here i is not referring to any cache Integer object containing value 8, instead unboxing of Integer(8) is happening .. is short, Integer(8) is unwrapped to using Integer.intValue() and then it is stored in int i .

    here we can say that j is referring to a cache Integer object having value 8.
    but when you compare i==j, than Integer j will be unwrapped/unbox to the int
    and hence true is returned
     
    Puspender Tanwar
    Ranch Hand
    Posts: 397
    2
    Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    thank you so much Roel, for such a wonderful explanations
    but i have a confusion at //20 of your code


    even though 10 is also in range of Short and Short IS-A Number, then why at //line3, Number is not using Short.valueOf(10);

    if
    will the compiler use ??
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Puspender Tanwar wrote:even though 10 is also in range of Short and Short IS-A Number, then why at //line3, Number is not using Short.valueOf(10);

    Because every integral literal in Java is by default an int. Just like any decimal point literal is by default a double.

    Puspender Tanwar wrote:if
    will the compiler use ??

    Yes! You can easily verify it by printing the class name of mynumber

    Hope it helps!
    Kind regards,
    Roel
     
    nick woodward
    Ranch Hand
    Posts: 370
    11
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    wow.

    is all of this in the oca 7 scope?

    pretty sure mala's and the k&b book didn't go into anywhere near this detail. i didn't even know there was an equivalent to the string pool.

    good to know, will read this several times!
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    nick woodward wrote:is all of this in the oca 7 scope?

    pretty sure mala's and the k&b book didn't go into anywhere near this detail. i didn't even know there was an equivalent to the string pool.

    No, this thread in its entirety is probably out of scope for the OCA exams. But starting with an OCA-related question, it became a thread covering everything you need to know about using the == operator on wrapper classes. So this probably will be useful to both OCA and OCP exams (and that's why it's available in both forums).

    Kind regards,
    Roel
     
    Puspender Tanwar
    Ranch Hand
    Posts: 397
    2
    Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    nick woodward wrote:wow.

    is all of this in the oca 7 scope?

    pretty sure mala's and the k&b book didn't go into anywhere near this detail. i didn't even know there was an equivalent to the string pool.

    you encounter some questions which uses == and equals(). Though it is not a topic of OCA.. but one should have a good knowledge of using ==, otherwise you will face problems in problems in solving such codes , and if you are known with the working of ==, you can easily answer such questions in just few seconds
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic