• 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

Numeric Promotion in Switch - OCP Oracle Certified Professional Java SE 11 Developer

 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi!
I have a question about numeric promotion with final modifier which is covered by book.
book: OCP Oracle Certified Professional Java SE 11 Developer Complete Study Guide: Exam 1Z0-815, Exam 1Z0-816, and Exam 1Z0-817
chapter: 4
subchapter: "Creating Decision-Making Statements" ---> "Numeric Promotion and Casting"

Perhaps the best way to start is to quote the book:

Numeric Promotion and Casting
Last but not least, switch statements support numeric promotion that does not require an explicit cast. For example, see if you can understand why only two of these case statements compile:



I was interested in this stuff with 'final' and decided to experiment. Below are some of my examples:












I am so lost in it...
I can't find any logical explanation why #3 compiles and #4 doesn't. Is long some kind of exception? I would be able to understand it, but what happens in #10 then? As you can see in #10, there is no problem anymore and the compiler can handle this long.
#8 and #9 is also strange to me, because looking at #1, #2 and #3 I understood that using 'final' when declaring a variable and assigning it a value immediately will make this variable automatically converted to the smallest possible container in a given type. If I declare a variable of type int but assign the value 127 or -128 to it, the compiler will say "that int is redundant here" and will automatically set the type of the variable to byte because 127 or -128 will fit in the type byte. ---> that's how I got it
If that were the case, why in #9 the compiler doesn't set the type of variable 'a' to float, which is the smallest possible floating point container?

Could someone explain this somehow to me, please? How should I think about this? Because my way of thinking turned out to be extremely incorrect.
 
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The short answer is "Because that's the rules!!" The Java Language Specification says which conversions are allowed, and which are prohibited.

So in a way, you are done.  They had to pick some things to be legal and some to be illegal, and there are tradeoffs all around based on those decisions.

On the off chance you are SO curious you wish to see what the JLS says, you got me interested enough to look, and so here it is:

JLS for Java 16 SE, Section 5.1.12 wrote: Forbidden Conversions
Any conversion that is not explicitly allowed is forbidden.




JLS for Java 16 SE, Section 5.2 wrote:In addition, if the expression is a constant expression (§15.29) of type byte, short,
char, or int:
• A narrowing primitive conversion may be used if the variable is of type byte,
short, or char, and the value of the constant expression is representable in the
type of the variable.
• A narrowing primitive conversion followed by a boxing conversion may be used
if the variable is of type Byte, Short, or Character, and the value of the constant
expression is representable in the type byte, short, or char respectively.
The compile-time narrowing of constant expressions means that code such as:
byte theAnswer = 42;
is allowed. Without the narrowing, the fact that the integer literal 42 has type int would
mean that a cast to byte would be required:
byte theAnswer = (byte)42; // cast is permitted but not required

 
Jesse Silverman
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Albert:

Welcome to the Ranch!!

My reply to you might sound like I think it is funny, so this is supplemental to the answer I gave, which was correct but unsatisfying.

Think about what we are doing with any of these types.  The Integer Concept just means no fractional part, a million to the million to the million to the million power is still an Integer to a mathematician or to Python (Python may take six times the current age of the universe to calculate that, but it won't give you an error unless your computer runs out of memory).

To represent an Integer (or an int) in a finite number of bits, compromises need to be made.  Many decisions need to be made, allow unsigned types or not, how many bits does each one represent.
Java made most of those decisions back in 1993.

The great thing about the JLS if you have worked in languages like C and C++, is that it specifies almost all behavior.

So, if you are a human, living in the Universe, there will be all kinds of arbitrary decisions about how to handle integer and floating point constants, variables and overflow and underflow, division by zero and a million others.

If you are a C programmer, your life sucks, because you will have twenty different platforms that handle these decisions just *slightly* differently, and you will see code that worked great on 10 platforms fail bizarrely on the 11th.

But, if you are in Java world, thanks to your friend the JLS, you will get the same (sometimes you might think it is stupid, why do they do this??!) behavior EVERYWHERE, and that is a million times better.  Way, way, WAY less chasing down strange behaviors as your code moves thru time, space or compile options.

This also extends to what will and will not compile.  It is very easy to cook up C code that will compile on 16 compilers and fail compile (or at least give scary warnings) on 6 others.  Or vice versa.  Or to stop compiling when you build DEBUG or optimized.  It builds character!

So for things where you just can't resist seeing WHY something compiles or not, you can always go to look up the JLS:
https://docs.oracle.com/javase/specs/jls/se16/html/

It is more readable than those for many other languages by a good bit, but certainly not easy reading.

Please don't try to learn Java from it, that would not be an accessible option, but if you have insatiable itches to know more about something about what is or is not legal in Java, that is the source.  It is freely available, and is required to be followed by all Java implementations.

Even if you almost never look at it, you should be glad it is there.  You might not like every one of them, but there are many, many rules about how Java MUST behave, and that makes every Java programmer's life way, WAY easier than the ones that let every implementation make its own decision about a million different things.  If you read the JLS and Javadocs, they make clear that an implementation can do whatever it wants as long as it doesn't break the rules, but most people are using Open JDK now, less like in the old days when you could play trivia games about how different popular implementations behaved (even then, they followed the JLS)...

p.s. Your imagining that this overrides the type of the variable is not accurate, the declared type of the variable is indeed the actual type.  You are always allowed to assign a primitive numeric to a larger one where it would fit.  You are never allowed to assign the larger values to a smaller one without casting, because it can so easily lose data (altho you can cheat with += ), but then the JLS gives a bunch of exceptions to these rules that were decided long ago to be okay because the compiler could be sure everything would be fine.  Then Java does what the JLS says.
 
Jesse Silverman
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
p.s. regarding:

In addition, if the expression is a constant expression (§15.29) of type byte, short,
char, or int:



when the compiler sees a definition like:
final int myVar = 42; // myVar is a constant expression, as is myVar * 2, myVar - 9, etc.

int myOtherVar = 100; // this is NOT a constant expression, because it might change, so this isn't, nor is myVar + myOtherVar, myOtherVar etc.

Just because we look at code on a screen and see "this never changes" doesn't mean the compiler will.  Its contract is to treat local variables marked as final as "constant expressions", not to analyze code to see whether or not they change...
 
Albert Kozera
Greenhorn
Posts: 8
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let me start by saying that I thank you very much for your time. I really appreciate that.
I think your 3 answers have dispelled my doubts.
It seems that this is just a hard JLS definition of "what is allowed and what is not". These kinds of things are the worst to remember.

Thanks again for all yours answers. I'm going back to learning
 
Jesse Silverman
Bartender
Posts: 1737
63
Eclipse IDE Postgres Database C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Albert Kozera wrote:Let me start by saying that I thank you very much for your time. I really appreciate that.
I think your 3 answers have dispelled my doubts.


You are welcome, I too wish to know the Secret Reasons behind everything, but there is so much material to learn!

Albert Kozera wrote:
It seems that this is just a hard JLS definition of "what is allowed and what is not". These kinds of things are the worst to remember.


No way, the kinds of things that vary everywhere from compiler to compiler and setting to setting are the worst to remember!  But you don't really have much of that at all when studying Java.

Albert Kozera wrote:
Thanks again for all yours answers. I'm going back to learning


Me too, see you there!
 
Replace the word "snake" with "danger noodle" in all tiny ads.
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic