This week's book giveaway is in the Kotlin forum.
We're giving away four copies of Kotlin for Android App Development and have Peter Sommerhoff on-line!
See this thread for details.
Win a copy of Kotlin for Android App Development this week in the Kotlin forum!
  • 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
  • Devaka Cooray
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Junilu Lacar
  • Paul Clapham
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • salvin francis
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Frits Walraven
  • Ganesh Patekar

Why Does Java assume any literal is an int?  RSS feed

 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am working through Chapter 1 of the OCA Study Guide and this came up:

"...Java assumes you are defining an int value with a literal..."

They then give this example:
long max = 312356789; //DOES NOT COMPILE

"Java complains the number is out of range.  And it is for an int."

Yes, *BUT* the number was declared as a long...

I don't understand the reasoning behind having to declare max this way:
long max = 312356789L;

You've already declared it as long...why the "L" at the end of the number?  Is this just because it's a literal?  Would this code be ok?:

long max = x;  // where x is a long value that was passed in

Thanks for the explanation.
-Lisa



 
Saloon Keeper
Posts: 9710
192
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to CodeRanch!

You've declared a variable of type long. You can assign int values to a long variable, and the value will be promoted to a long. However, 312356789 is not a valid int, because it's too large to be an int. It's also not a long, because long literals MUST be suffixed with the letter 'L'.

The Java designers probably could have allowed for all integer literals to be written without a suffix, and have the compiler determine what exact type they're supposed to be. The fact of the matter is that they didn't, and we just have to accept that's the way it is.
 
Saloon Keeper
Posts: 5485
55
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java does not infer the type on the right of the assignment by what's on the left side. Off hand, I can only think of one place where Java does that.
 
Sheriff
Posts: 12994
217
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I were to guess, there could be a couple of reasons:

1. Keeping the parsing/lexing rules simple. I'm guessing that auto-promoting an int literal to long would require the compiler to "look back" at the declaration of the variable being assigned to. This would lead to more complicated rules for auto-promoting with long expressions to stay consistent. I can see the designers deciding to make programmers declare their intent to purposely use a long value instead of int by explicitly adding the "L" suffix.

2. Performance. More complicated parsing/lexing rules, especially where the compiler needs to "look back" and remember too much about the left-hand side of an expression, can impact the compiler's performance. Maybe they decided that eliminating the little inconvenience didn't justify a tradeoff in compiler speed.

It has been a while since I've studied and practiced writing a compiler but I know that writing one for even a simple grammar can be difficult and that performance is a major consideration.
 
Marshal
Posts: 62881
203
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:. . . . Off hand, I can only think of one place where Java does that. . . .

And that is a relatively new construct, being introduced in Java7.

As Jeanne implied, it is reasonably easy for a compiler to infer the type of an expression from its structure, and an integer literal is a kind of expression. But trying to carry over the type from left to right is awkward, particularly if you reassign a variable, and woulld result in slow performance. Look at this sort of code:-It would be awkward to try to specify how to turn the expression to the right of the assignment operator into a long. Which number should receive an imputed L? Should we allow that to change the expression's semantics? It will; try it. Maybe compiler techniques have improved so it is now possible to check for effectively final variables, or impute a type parameter, but imputing an L to that expression would alter the semantics of old code, so it would be a bad idea to add it to new compilers.
 
Bartender
Posts: 20354
111
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, the Java compiler is one of those that parser left-to-right, but in the case of an assignment to a constant, I don't think that's a factor, since if the items were simply tokenized then the assignment's data typing wouldn't come until the semantic analysis phase.

But when I typed "long max = 312356789;" into Eclipse it worked just fine without the "L" qualifier.

Unless something has changed (I think I was using the Java 8 compiler), then it would appear that your text is wrong.
 
Junilu Lacar
Sheriff
Posts: 12994
217
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:But when I typed "long max = 312356789;" into Eclipse it worked just fine without the "L" qualifier.


I did some experiments in JShell and here's what happened:

jshell> Integer.MAX_VALUE
$26 ==> 2147483647

// try Integer.MAX_VALUE

jshell> long val = 2147483647      
val ==> 2147483647   // OK

// try Integer.MAX_VALUE + 1

jshell> long val = 2147483648
| Error:
|  integer number too large
|  long val = 2147483648;
|             ^

// Try Integer.MAX_VALUE + 1 with "L"

jshell> long val = 2147483648L
val ==> 2147483648   // OK

// Overflow when terms are valid ints

jshell> long val = 1 + 2147483647
val ==> -2147483648

// No overflow when first term is a long

jshell> long val = 1L + 2147483647
val ==> 2147483648

// Try with an invalid int term

jshell> long val = 1 + 2147483648
| Error:
|  integer number too large
|  long val = 1 + 2147483648;
|                 ^

// Try with a long value and invalid int

jshell> long val = 1L + 2147483648
| Error:
|  integer number too large
|  long val = 1L + 2147483648;
|                  ^

// Try the other way around

jshell> long val = 1 + 2147483648L
val ==> 2147483649   // OK

// Try both terms as long values

jshell> long val = 1L + 2147483648L
val ==> 2147483649   // OK

From the above, it appears that the compiler applies the type promotion rules on a term-by-term basis. I'm sure this is specified somewhere in the JLS but I don't have time to look for the exact sections right now.
 
Tim Holloway
Bartender
Posts: 20354
111
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I went back to Eclipse. 312,356,789, without actually doing the math, is apparently less than MAX_INT. Actually, having put in the separators, it's OBVIOUSLY less than MAX_INT, which is something like 10x larger than that. So the text example is defective.

An actual literal long value without the long qualifier cannot be assigned at compile time without being flagged as being in error. In fact, you cannot ever cast it on the right-hand side without it being flagged as in error.

Please remember that not only Java, but also C/C++ assume that arithmetic expressions of any usage are considered as being of type "int" unless there is something that explicitly promotes them to a long or float/double type. And from my test that includes the casting operation: the cast refused to accept a long integer value even though it was perfectly happy with the same value carrying a "L" type specifier.

I realize that this level of pickiness may seem silly, but if you want a language that allows you to type in just any old slop have have it "work", choose one of the quick-and-dirty ones so popular these days. Java was intended to be rigorous from the ground up, and that includes not allowing assuming that a large integer literal might actually be a long. This includes expressions that can be reduced at compile type, such as:

long max = (long) (31235678922 / 2200);

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

Tim Holloway wrote:. . . long max = (long) (31235678922 / 2200);

Afraid that won't compile, nor will it compile if you take the () off and apply the cast to 31235678922, because you are overflowing the range of an int. The only way you can get that to compile is to append an L to the number literal (case‑insensitive, but never use lower‑case). More details in the Java® Language Specification (=JLS). It doesn't matter which order you compile the different tokens; you will eventually encounter the token “31235678922”, which is outwith the syntactic rules in that JLS section. This is what you find if you scroll down about two pages:-

That JLS section wrote:It is a compile-time error if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator; or if a decimal literal of type int is larger than 2147483648 (2³¹).

Remember that the range of octal, binary, and hexadecimal int literals is twice as large as for decimal literals.
 
Ranch Hand
Posts: 127
5
MS IE Notepad Suse
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i know that some of the mods maybe not so cool with this reply, but most topics wich title is "why is X the way it is and not Y?" and repeat that question in the post can be answered with: "because someone decided so" or "cause it has to / can't be Y"

so to come back to the main question, why long literals have to have trailing L and why the otherwise seen as int: because someone in the past decided so - just take it as given instead of try to argue about it - you can't change it anyway (well, for most of those questions)
 
Campbell Ritchie
Marshal
Posts: 62881
203
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Matt Wong wrote:. . . someone in the past decided so . . .

Who? Probably Brian Kernighan and Dennis Ritchie; I think the same conventions applied in C, but maybe they are even older than C. I think Gosling tried to keep Java® syntax looking as similar to C/C++ as possible, so we are given the L.

you can't change it anyway . . .

Good point.
 
Sheriff
Posts: 24089
54
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Matt Wong wrote:i know that some of the mods maybe not so cool with this reply, but most topics wich title is "why is X the way it is and not Y?" and repeat that question in the post can be answered with: "because someone decided so" or "cause it has to / can't be Y"



Yeah, I don't have a problem with that.

I just learned this month that the question "Why X?" can be interpreted in two ways. One is "How come X?" which is the same as "How did it come about that X?" and the other is "What for X?" which is the same as "What is the reason for (or purpose of) X?" So yeah, for questions like the OP it's always easier to choose "How come X?" which can always be answered "Because the Java designers decided so."

Sometimes it's possible to make up an answer which explains the Java designer's reason for X, but that to me smells of mind-reading a lot of the time. Even though a lot of the time it's possible to come up with plausible reasons, as for example in this thread.
 
Tim Holloway
Bartender
Posts: 20354
111
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Every so often, one of these fellows gets interviewed. Not uncommonly, the answer ranges from, "It seemed like a good idea at the time" to "Darned if I can remember", to "I think I was drunk."

However, I think that in this case, you can look to the hardware. In C, an "int" is defined as an object that is the natural word size of the machine. Usually. The original MC68000-based MacIntosh and one of the popular Amiga C compilers considered an int to be 16 bits, although the official hardware word size was 32 bits. It was mostly a 16-bit world back then - IBM was still using segment registers on their PCs.

The ability to get clever with resources was incredibly limited by today's standards, and the amount of research into compiler and language design, while significant, was still not what it is today. A lot of work had been done on integer-only basic machine designs. Floating-point was often done by software libraries, and character/string manipulation was very idiosyncratic. The IBM System/360 was fairly uncommon in the 1960s in its ability to address memory at the byte level. Languages like Fortran had no native character support even on machines that did have byte addressing, and memory was so precious that variable-length strings were extremely uncommon even in more character-friendly languages like COBOL.

So when Dennis Ritchie designed C, he took a little bit of Fortran, a little bit of Algol, perhaps a smidgen of a few other languages, and designed the root of what has since become one of the primary programming language syntax and operational paradigms of the modern day. In particular, the native computational system was integer arithmetic. We're talking compilers that often had to run as multiple overlays in a 4 Kilobyte memory space, so being all things to all people wasn't a practical option. Any deviation from straight integer arithmetic came at extra cost.

Of course, one of the other consequences of having limited resources to work with is that error checking and reporting was often minimalistic. You can see its residue in the ever(-not)-so-helpful error messages that Oracle (originally a mainframe DBMS) returns and stuff like IBM's infamous IEC141I/IEC000I ERROPT = ABE OR AN INVALID CODE, which in English means A) you coded an improper record length in your program or B) Tape Drive is on Fire. Further dump analysis required to determine which.

So often you wouldn't get dressed down back then if you got sloppy mixing data types and in fact usually it would compile and surprise you at run time. In unpleasant ways.

Java came on the heels of the extremely formal Ada programming language, and since it was designed with the Internet in mind, and anticipating the abuses that it might enable was designed fairly strictly. So in short, this is the history that has contributed to its strictness.
 
Campbell Ritchie
Marshal
Posts: 62881
203
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . answer ranges from . . . to "I think I was drunk." . . .

Surely that's the reason for agreeing to the interview

when Dennis Ritchie designed C, he took a little bit of Fortran, a little bit of Algol, perhaps a smidgen of a few other languages, . . .

I believe he was also influenced by a language called BCPL, but I know absolutely nothing about it.

had to run as multiple overlays in a 4 Kilobyte memory space, . . .

. . . and that 4kB cost about the same as buying a whole street round here; nowadays I can buy 1,000,000× that memory for the price of dinner with the Missus.

Java . . . was designed fairly strictly. . . . .

But you find that the stricter the language, the more errors are caught early and the fewer errors escape into the big wide world.
 
Tim Holloway
Bartender
Posts: 20354
111
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I believe he was also influenced by a language called BCPL, but I know absolutely nothing about it.



Ah yes, the British Cruddy Programming Language. Actually, both were preceded by B, I believe. I've never seen B.

The "DOS" part of Commodore's AmigaDOS was originally someone's University degree project named "Tripos". It was, in fact written in BCPL, and while I never saw the actual BCPL source (that I recall), you could tell that it was extremely integer-oriented. Also, it grew its stack in precisely the opposite direction from the underlying Amiga Exec, which was written in object-oriented C and assembly language. Writing custom DOS device drivers on that platform was a challenge.

Incidentally, Carl Sassenrath told me that although C++ was not known to him when he designed Exec, he got inspiration from Smalltalk, so he coded C in a way that I was later able to map with great precision onto C++ when I developed what would eventually be sold as Lattice C++ for Amiga.

Campbell Ritchie wrote:But you find that the stricter the language, the more errors are caught early and the fewer errors escape into the big wide world.



And the more you get ragged on by management to produce "results", hence the popularity of languages which are the exact opposite.
 
Campbell Ritchie
Marshal
Posts: 62881
203
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:. . . British Cruddy Programming Language. . . . .

Hahahahahahahahaha!
 
ice is for people that are not already cool. Chill with this tiny ad:
Programmatically Create PDF Using Free Spire.PDF with Java
https://coderanch.com/wiki/703735/Programmatically-Create-PDF-Free-Spire
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!