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

type casting - return value

 
Murat Kutluer
Greenhorn
Posts: 21
IntelliJ IDE Java PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Do you have any idea why test2 compiles but test3 does not?

Murat



 
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
Murat Kutluer wrote:Do you have any idea why test2 compiles but test3 does not?

Yes! Try marking variable i in test3 as final and see what happens...
 
Murat Kutluer
Greenhorn
Posts: 21
IntelliJ IDE Java PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Roel, I got it. The trick is compile-time constant.

 
Murat Kutluer
Greenhorn
Posts: 21
IntelliJ IDE Java PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,

What about this one? Both int and long are larger primite than short, but int works, long doesn't.

Murat

 
fred rosenberger
lowercase baba
Bartender
Posts: 12266
36
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What exactly does the compiler error say?  Believe it or not, they usually give you a pretty good idea what the problem is.
 
Murat Kutluer
Greenhorn
Posts: 21
IntelliJ IDE Java PHP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It says "incompatible types: possible lossy conversion from long to short".

I wonder why we don't see an error message like "incompatible types: possible lossy conversion from int to short" for "short s = (int) 1;".
 
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
Murat Kutluer wrote:The trick is compile-time constant.

Exactly! In this topic you'll find an explanation about what's a compile-time constant.
 
Henry Wong
author
Marshal
Pie
Posts: 22119
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

To give more detail regarding the first question... the return statement is defined by section 14.17 of the JLS... https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17

In that section, it is mentioned that how it is assignable is defined by section 5.2 of the JLS...  https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.2

And that is how we reach the compile time constant conclusion.


Regarding the second question... variable assignment conversions is simply defined by section 5.2 of the JLS. No need to give further detail here...

Henry
 
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
Murat Kutluer wrote:What about this one? Both int and long are larger primite than short, but int works, long doesn't.

That's very simple: because you can't assign a long to a short (or int or byte) without using an explicit cast.

Let's have a look at what happens behind the scenes. Remember that the compiler is often a very friendly guy, but sometimes can be very picky Assume this statementWhen the compiler sees that statement he has to decide if he must complain (compiler error) or not. So he probably thinks something like: "Hey dude, you know every integer literal is by default of type int and you are trying to assign an int to a short without an explicit cast. That's not looking very good for you. But wait a minute, I don't offer any suffix (or other alternative) to create a short literal (like with L or l for a long) and 15 is within the range of short, so I am not gonna complain about this statement. Otherwise you always have to write short s1 = (short)15; and that's a lot of typing and clutters your code. I am such a friendly guy! ".

Now consider this statementAnd again the compiler has to make up his mind about what to do with this statement: "I know you know that an integer literal is by default of type int. And I know as well that you know I am happy to let it pass so you can save some key strokes, but 150_000 is not within range of short! Do I need to assign 0, 15, 150, 1500, 15000, or ... to s2? I really have no clue, so because I can't make this decision myself, I must create a compiler error for this statement. Sorry about that!"

Finally consider the following statementAnd here is what the compiler thinks about this statement: "What are trying to pull off here, dude? You explicitly tell me to handle this literal as a long literal by adding the L suffix (or the long cast as in your example. And then you want me to be ok about assigning a long to a short? That definitely won't happen! You explicitly want me to treat that literal as a long and a long can't be assigned to a short without explicit cast. Don't forget that allowing short s1 = 15; was a friendly gesture of me to save you some typing (and also because you can't create a short or byte literal). But now you have explicitly turned the literal into a long literal, so you have to face the consequences. Here is a big, fat, juicy compiler error!"

For the same reason, the following statement will also fail to compileAnd just for the record, the Java Language Specification is the only thing that matters for the compiler and this behavior is clearly mentioned in §5.2. Assignment Contexts
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.


Finally I like to draw your attention to the following code snippetAlthough both statement will have the same result (a primitive long variable with a value of 15), there is a slight (but important) difference between both statements. On the first line the int literal is implicitely widened to long and that value is assigned to lo1. On the second line a long literal is simply assigned to lo2. And that seems a minor difference, but is very important when you have a literal value which is outside the range of int as you can see in this code snippetNow line1 and line2 will fail to compile! Your very good friend, the compiler, considers 15_000_000_000 as an int literal but 15_000_000_000 is outside the range of int (resulting in a compiler error). On line3 the compiler considers 15_000_000_000L as a long literal and 15_000_000_000 is within the range of long, so this statement compiles successfully. That's the short version of the explanation. If you want the more elaborate one, just read this topic

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
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:Regarding the second question... variable assignment conversions is simply defined by section 5.2 of the JLS. No need to give further detail here...

Based on my previous post I beg to differ
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic