• 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 all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Tim Cooke
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • paul wheaton
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Ron McLeod
  • Piet Souris
  • Ganesh Patekar
Bartenders:
  • Tim Holloway
  • Carey Brown
  • salvin francis

Deep trouble with data types - Extracted from chapter 2 ex. 10 OCA study guide

 
Ranch Hand
Posts: 37
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi again. I'm in a very deep trouble with data types because I've demostrated myself through the compiler that both statements are the same but one compiles and the other doesn't. Please, can someone tell me why do you think that this has this behavior?:



The book says that because the right hand is promoted to int, we need to cast the entire (a + b) because from int to byte ther is a lossy convertion. BUT if I try the bellow code it actually works:



AND if we look which value each of both types returns, we obtain that both are int (I used this way obtaining the wrapper classes because it was the only way that i found to look the types, but anyway I know that the original is which corresponds to int):
System.out.println( ((Object) ((byte) a + b) ).getClass().getName()); // java.lang.Integer
System.out.println( ((Object) ((byte) 40 + 50) ).getClass().getName()); // java.lang.Integer  

The only thing that I can notice is that in one statement we use variables and in the other literals, but anyway both are int. But this looks like this:


So, in summary, the question is: why in case of sum it does not compile and for sum2 it does.
 
Master Rancher
Posts: 172
7
IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Pablo,

When writing the following:

Only the variable a gets cast to byte, b will be an int. And byte + int will be int. What needs to be done is to cast the entire right-hand side of the assignment operator to byte.

Be mindful, what do you think: Is this okay?

With regards to the second part:
When writing this:

The compiler can't know for sure that at compile time the value of z will still fit into a byte and therefore won't allow it. This is called "implicit narrowing". By declaring z as final, the compiler will be reassured.


 
Pablo Napoli
Ranch Hand
Posts: 37
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Brecht. First of all thanks for your fast answer. For your reply I can notice that still i have big problems with understanding how compiler works.

When you say: I think it means the compiler doesn't know the value inside the variable. If so, I guess this behavior is because if it's not able to know what is inside a variable, maybe we can set a value out of range, but what would be the difference if we marked the variable as final? I mean, I could still write an out of range value like 10000.

Cheers!, Pablo.
 
Sheriff
Posts: 6163
163
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Consider the class below:
 
Pablo Napoli
Ranch Hand
Posts: 37
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Knute, thanks for your answer!. I got it but maybe now my doubt is related with how the compiler works, because I still don't fully understand why the compiler can't know the new value of the variable "c" (in case it has changed). I mean, with variable "b" it was able to read it knowing the value was too large. So in case value from "c" changes, it can check it again and if it doesn't fill into byte sum3, just in that case claims. I'm not sure if I'm being enough clear. Anyway with those explanations is enough to detect the right answers in my next oca exam, but I like going a bit deeper

Cheers!
 
Marshal
Posts: 65365
248
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brecht Geeraerts wrote:Hi Pablo,

When writing the following:

Only the variable a gets cast to byte, b will be an int.

Not quite. Both variables in line 1 are bytes, It is only when you try arithmetic on them that there is promotion to an int. Both variables are promoted to ints. The reason you need () is that the cast operator has a higher precedence than +.

. . . Is this okay? . . .

No, it isn't OK to use bytes for arithmetic. A beginner shouldn't use bytes at all. They are there so you can create byte[]s and those arrays are sent across networks. Otherwise, stick to proper integer types: int and long.

It is possible to declare a byte and initialise it to a compile‑time constant possibly 40 + 50 which will fit into a byte.
 
Brecht Geeraerts
Master Rancher
Posts: 172
7
IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That is what I meant but I wasn't expressing myself as clearly. Thanks for the additional clarification.  
My apologies if it has caused any confusion.
 
Campbell Ritchie
Marshal
Posts: 65365
248
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brecht Geeraerts wrote:. . . My apologies if it has caused any confusion.

Apology accepted (). Remember that cert exam books include confusing code which nobody would use in real life. Part of the skill for passing a cert exam is knowing which variables are which type, and which code will and won't compile. We would have answered differently if this same question had come up on a cert exam forum rather than here on BJ.
The line of code you marked with, “is this okay?” won't compile. Let's remind ourselves of it:-Remember you go left‑to‑ight, so the first operation you encounter is the left (byte) cast, which you will find the Java® Language Specification (=JLS) calls an identity conversion. Then you encounter the + operator, which causes promotion (JLS link) of both its operands to ints, even though both are cast to bytes. (The right cast is also an identity conversion.) The addition operation has

the promoted type of its operands

as its result, so the last operation, which has the lowest precedence, is assignment which cannot proceed because the right type (int) cannot fit into the left type (byte).

As I said, bytes are good for putting into arrays to send across networks, but otherwise their only uses are in cert exams, or when you are only trying to find out what happens if....
 
Knute Snortum
Sheriff
Posts: 6163
163
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pablo Napoli wrote:... maybe now my doubt is related with how the compiler works, because I still don't fully understand why the compiler can't know the new value of the variable "c" (in case it has changed). I mean, with variable "b" it was able to read it knowing the value was too large. So in case value from "c" changes, it can check it again and if it doesn't fill into byte sum3, just in that case claims. I'm not sure if I'm being enough clear. Anyway with those explanations is enough to detect the right answers in my next oca exam, but I like going a bit deeper


The short answer is the compiler does the least amount of work to compile a valid Java program.  It does this mainly for speed.  In order for the compiler to be able to tell if the value of c changed, it would have to be akin to an interpreter.

So it may be unsatisfying, but the compiler doesn't track variables like c because that's the way it was designed.
 
Pablo Napoli
Ranch Hand
Posts: 37
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi again Ritchie. I was looking your last post very carefully and let me say (maybe I'm really wrong) that i don't agree with something. Because if we take this example:



Here we have that 40 and 50 are integral literals so they are int type by default. So if i follow the order of precedence, first i have that 40 (int) is cast to byte and then i add 40 (byte) and 50 (int) and applying one of the rules for numeric promotion for arithmeric operations, i obtain that the result becomes to int. By last, the compiler allows that i assing this 90 int value to a byte variable called sum.

So with the examaple below i understand that (byte) a +  b gives an int value because (byte) a is cast to byte (which is redundant) and b is already byte so after the add operation the result becomes to int. But now (i don't know why) this int can't be assigned to the byte variable sum.

 
Campbell Ritchie
Marshal
Posts: 65365
248
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:. . . the compiler does the least amount of work to compile a valid Java program.  It does this mainly for speed. . . . .

Compilers are at risk of going into exponential complexity if they are asked to do too much, so who who knows how long it will take to compile a large program.

Pablo Napoli wrote:

You are correct in how you say that expression is evaluated, remembering you go left‑to‑ight (or even left‑to‑right if I want to spell it correctly ‍).
  • 1: The assignment operator is reached, but this requires its right operand be completely evaluated.
  • 2: The 40 is cast to a byte.
  • 3: The + is reached, which causes the left operand to be promoted, which reverses the cast.
  • 4: The addition produces the result 90.
  • 5: The assignment completes.
  • Now, to understand the rest of the problem: there is one concession allowing an implicit cast. That is where a “narrow” type is assigned with a compile‑time constant expression of a suitable value. So, what you have shown above 40 + 50 is a compile‑time constant. In the second block,...a and b are not compile‑time constants. As Knute said, the compiler doesn't usually follow execution to verify that variables retain their original values. If any of those ints has been reassigned to, there is no way of knowing that the value will fit into a byte, so the compile cannot permit the assignment. The only way you can get that code to compile is by casting the whole expression:-,...but remember that such casting can alter the resultant value:-
     
    When I was younger I felt like a man trapped inside a woman’s body. Then I was born. My twin is a tiny ad:
    professionally read, modify and write PDF files from Java
    https://products.aspose.com/pdf/java
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!