Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Why does this " System.out.println(2 + 1.0f) " print 3.0?

 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ranchers!

I am a bit confused with this code snippet while I was studying:

System.out.println(2+1.0f) -> prints 3.0

Is the reason why it printed a float type is because float is larger than an int and so it got promoted to a float?
and same also as the double in the snippet below?

System.out.println(2+1.0d) -> prints 3.0
 
Roel De Nijs
Sheriff
Posts: 10040
127
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I guess you expected "3"? Or maybe "21.0"?
 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yap, that's right. I was expecting an int.
 
Roel De Nijs
Sheriff
Posts: 10040
127
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
When executing calculations Java uses a "standard" datatype. When you are calculating with integers, the result of the calculation will be an int. That's why for example this code snippet won't compile (although you might think it would, it really doesn't ):


If you are doing some calculation with floating-points (decimals), the result will be a double. Again the reason why this won't compile too:


Also don't forget: when you use a floating-point literal value, it's automatically considered to be a double too. That's why you need to add an f (or F) when you need a float. So float f = 10.0; will not compile, but float f = 10.0F; does!

In your println-statement you are adding an int with a double, so the result will be a double (and thus 3.0 is printed)

Hope it helps!
 
Robert James Liguori
Author
Ranch Hand
Posts: 551
5
Java Netbeans IDE Oracle
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fantastic question, associated with "Binary Numeric Promotion"!

You will find the answer here:

The Java Language Specification, Java SE 8 Edition
http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf (5.6.2 Binary Numeric Promotion)

"...If either operand is of type double , the other is converted to double ..."

-- Robert

Note: I also have this reference in the Java 8 Pocket Guide.
 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:When executing calculations Java uses a "standard" datatype. When you are calculating with integers, the result of the calculation will be an int. That's why for example this code snippet won't compile (although you might think it would, it really doesn't ):


If you are doing some calculation with floating-points (decimals), the result will be a double. Again the reason why this won't compile too:


Also don't forget: when you use a floating-point literal value, it's automatically considered to be a double too. That's why you need to add an f (or F) when you need a float. So float f = 10.0; will not compile, but float f = 10.0F; does!

In your println-statement you are adding an int with a double, so the result will be a double (and thus 3.0 is printed)

Hope it helps!


Thanks! That's a very clear explanation, now I know why.
 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Robert Liguori wrote:Fantastic question, associated with "Binary Numeric Promotion"!

You will find the answer here:

The Java Language Specification, Java SE 8 Edition
http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf (5.6.2 Binary Numeric Promotion)

"...If either operand is of type double , the other is converted to double ..."

-- Robert

Note: I also have this reference in the Java 8 Pocket Guide.


Great! thank you for providing additional resource on that topic.
 
Roel De Nijs
Sheriff
Posts: 10040
127
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you think will happen with this code snippet? Compiles without error or compiler error (or something else)?

 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:What do you think will happen with this code snippet? Compiles without error or compiler error (or something else)?



I think that would compile with error, same reason as what you've said before.
It doesn't seem to make any difference making the two operands final.

But after I tried to compile it, there was no error. How did that happen?
 
Roel De Nijs
Sheriff
Posts: 10040
127
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
Ed Cardenas wrote:But after I tried to compile it, there was no error. How did that happen?

Yeah, it was a bit a trick question

The compiler is actually one smart cookie Because you used final for both variables, these are compile time constants. So the compiler knows the values of these variables and asks himself 1 question; does the value of the constant expression fit into the type of the variable? If it does, a narrowing primitive cast is used. If it doesn't, a compiler error is still given.

So for this example: the compiler knows there are 2 constants: 2 and 5, the value of the constant expression (2 + 5) is 7 and 7 fits the data type short, so compiler uses narrowing primitive cast (conversion) and no compiler error is given.

It's all explained in detail in JLS 5.2 Assignment Conversion:
In addition, if the expression is a constant expression (ยง15.28) of type byte, short, char, or int: - A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.


So if you now know all this extra info, what would happen with this code snippets?



Hope it helps!
 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I get it now, thanks!

Roel De Nijs wrote:
So if you now know all this extra info, what would happen with this code snippets?



My guess was right, this will compile because the value of the constant expression is 127 and fits in a byte (-128 to 127) through narrow primitive casting.





Again my guess was right that this code snippet won't compile.
Because of the value of the constant expression is 128, it can't fit into a byte (-128 to 127) so there is compiler error.
Thanks for the great explanation!

I have a question again Roel, when I tried to remove one of the final keyword on the code snippet below, why was there a compiler error?
Isn't the expression promoted to a compile time constant?

 
Roel De Nijs
Sheriff
Posts: 10040
127
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ed Cardenas wrote:Isn't the expression promoted to a compile time constant?


If you remove one of the final keywords, you don't have a compile time constant anymore and then we are back where we started: at the 1st post (and answer) of this thread
 
Roel De Nijs
Sheriff
Posts: 10040
127
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
And just for completeness: you can only have a compile time constant if you are using a literal value (like 200 or 10). So invoking a method and putting the result in a variable marked as final will NOT result in a compile time constant.

As the following code shows:
 
Ed Cardenas
Ranch Hand
Posts: 43
1
Chrome IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Great! Many thanks for the explanation.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic