Java's L number (long) specification - java

It appears that when you type in a number in Java, the compiler automatically reads it as an integer, which is why when you type in (long) 6000000000 (not in integer's range) it will complain that 6000000000 is not an integer. To correct this, I had to specify 6000000000L. I just learned about this specification.
Are there other number specifications like for short, byte, float, double? It seems like these would be good to have because (I assume) if you could specify the number you're typing in is a short then java wouldn't have to cast it - that is an assumption, correct me if I'm wrong. I would normally search this question myself, but I don't know what this kind of number specification is even called.

There are specific suffixes for long (e.g. 39832L), float (e.g. 2.4f) and double (e.g. -7.832d).
If there is no suffix, and it is an integral type (e.g. 5623), it is assumed to be an int. If it is not an integral type (e.g. 3.14159), it is assumed to be a double.
In all other cases (byte, short, char), you need the cast as there is no specific suffix.
The Java spec allows both upper and lower case suffixes, but the upper case version for longs is preferred, as the upper case L is less easy to confuse with a numeral 1 than the lower case l.
See the JLS section 3.10 for the gory details (see the definition of IntegerTypeSuffix).

By default any integral primitive data type (byte, short, int, long) will be treated as int type by java compiler. For byte and short, as long as value assigned to them is in their range, there is no problem and no suffix required. If value assigned to byte and short exceeds their range, explicit type casting is required.
Ex:
byte b = 130; // CE: range is exceeding.
to overcome this perform type casting.
byte b = (byte)130; //valid, but chances of losing data is there.
In case of long data type, it can accept the integer value without any hassle. Suppose we assign like
long l = 2147483647; //which is max value of int
in this case no suffix like L/l is required. By default value 2147483647 is considered by java compiler is int type. Internal type casting is done by compiler and int is auto promoted to Long type.
long l = 2147483648; //CE: value is treated as int but out of range
Here we need to put suffix as L to treat the literal 2147483648 as long type by java compiler.
so finally
long l = 2147483648L;// works fine.

I hope you won't mind a slight tangent, but thought you may be interested to know that besides F (for float), D (for double), and L (for long), a proposal has been made to add suffixes for byte and short—Y and S respectively. This would eliminate to the need to cast to bytes when using literal syntax for byte (or short) arrays. Quoting the example from the proposal:
MAJOR BENEFIT: Why is the platform
better if the proposal is adopted?
cruddy code like
byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF};
can be recoded as
byte[] ufum7 = { 0x00y, 0x7Fy, 0x80y, 0xFFy };
Joe Darcy is overseeing Project Coin for Java 7, and his blog has been an easy way to track these proposals.

These are literals and are described in section 3.10 of the Java language spec.

It seems like these would be good to
have because (I assume) if you could
specify the number you're typing in is
a short then java wouldn't have to
cast it
Since the parsing of literals happens at compile time, this is absolutely irrelevant in regard to performance. The only reason having short and byte suffixes would be nice is that it lead to more compact code.

Java has two types of data type :
Primitive Data-Type
Non-Primitive Data-Type
Certain data types require specifications like long, float, and double.
While assigning any of the above data types to any variable always remember to....
End the value with a "d" in double data type.
End the value with a "L" in long data type.
End the value with a "f" in float data type.
Example:
long number = 15000000000L;
float mysecondnum = 5.75f;
double mynumber = 19.99d;
More info:
The size of the long data type is 8 bytes.
The size of the float data type is 4 bytes.
The size of the double data type is 8 bytes.
The precision level of the long data type is up to 7-8 decimal points while the float data type is up to 15 decimal points.
Edit:
Along with this typecasting can be used to change the primitive data type from one to another.
Widening Casting(automatically): smaller type to a larger type size
Narrowing Casting(manually): larger type to a smaller size type

To understand why it is necessary to distinguish between int and long literals, consider:
long l = -1 >>> 1;
versus
int a = -1;
long l = a >>> 1;
Now as you would rightly expect, both code fragments give the same value to variable l. Without being able to distinguish int and long literals, what is the interpretation of -1 >>> 1?
-1L >>> 1 // ?
or
(int)-1 >>> 1 // ?
So even if the number is in the common range, we need to specify type. If the default changed with magnitude of the literal, then there would be a weird change in the interpretations of expressions just from changing the digits.
This does not occur for byte, short and char because they are always promoted before performing arithmetic and bitwise operations. Arguably their should be integer type suffixes for use in, say, array initialisation expressions, but there isn't. float uses suffix f and double d. Other literals have unambiguous types, with there being a special type for null.

Related

Why don't we add an "s" suffix to short types?

Why don't we write s with short data type like short s = 2s; as we write with float e.g float f = 1.23f?
I know when we write float by default the compiler treats it as double and assigns 8 temporary bytes to it, and when it tries to copy that 8 byte to float's 4 that results in a type error, so that is why we write f after initializing a float, but why we don't do something similar with short as by default int is a literal type?
The Java Language Specification allows a type suffix of L or l for long literals. However, it does not provide a type suffix for short values. It's not necessary because:
Any value that could be represented by a short can also by represented by the default integral type int.
Assignments of an int value to a short variable are allowed if the value is a constant expression, whose value can be represented by a short. See the Java Language Specification, "Assignment Contexts":
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.
Why don't we add an “s” suffix to short types?
Because the Java language is inconsistent on this point.
The JLS is more flexible for no floating numeric primitive types as for floating numeric primitive types :
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.
I think that doing a distinction between byte, short, char, or int and float and double in the way to declare and manipulate them was not really required. It creates inconsistency and so potential mistakes in the use of them.
if short s = 10; is valid because the narrowing primitive conversion is validated by the compiler that it has no lost information, so float f = 10.0; would also have been valid for exactly the same reason.
That is because coming from double to a float is truncating value and losing data so the compiler doesn't do that automatically, you have to explicitly tell it. But when going from a smaller size, short, to a larger size, int, it is done automatically as the compiler just has to pad the data and there is no potential loss of data, as opposed to the former case.

A bit confused about java datatypes and literals

So I understand what a dataype and literal is but I am confused about one thing.
Why do I have to put an L when the datatype is long? How come I don't have to do that for short or byte?
// Why does a not work but b does? Both are longs?
long a = 9223372036854775807;
long b = 9223372036854775807L;
There are only two integer literals types defined in Java: int and long. The latter is distinguished from the former by a suffix L or l. (A character literal is also of integral type (can be assigned to an int, for example) but the Java Language Specification (JLS) treats it separately from integer literals.)
Remember that (apart from inferring generic type parameters), the type of the left hand side of an assignment has no effect on the evaluation of the right-hand side. Therefore, if you assign something to a variable of type long, the expression will be evaluated first and only then will the result be converted to long (if possible and necessary).
The statement
long a = 10;
is perfectly valid. The right hand side expression consisting only of the integer literal 10 will be evaluated and then promoted to long which is then assigned to the variable a. This works well unless you want to assign a value that is too large to be represented in an int in which case you'll have to make the literal of type long as well.
This “problem” is not limited to literals. Consider the following statement that frequently bites new users:
long a = Integer.MAX_VALUE + 1;
The expression on the right hand side is evaluated using int arithmetic and therefore overflows. Only then the result (−2147483648) is promoted to long and assigned to a but it is too late by now. Had the 1 been written as 1L, the overflow would not have happened.
How come I don't have to do that for short or byte?
First, note that a literal of type int can hold any value you could possibly assign to a short or byte so the problem described above cannot occur. Moreover, it is not as much that you “don't have to” use a short or byte literal but that you cannot because such literals are not defined. This has always bothered me because it means that we often have to cast to byte if we want to call a function with a literal argument.
If you like reading standardese, you can look up the chapter about Integer Literals (§ 3.10.1) in the JLS.
Clearly stated in the documentation:
"An integer literal is of type long if it ends with the letter L or l; otherwise it is of type int. It is recommended that you use the upper case letter L because the lower case letter l is hard to distinguish from the digit 1."
Your 2nd question is answered there as well:
"Values of the integral types byte, short, int, and long can be created from int literals"
If you didn't set L, the compiler will try to parse the literal as an int like as below sample scenario.
long accepts a value between the ranges of: -9,223,372,036,854 to +9,223,372,036,854,775,807. Now I have create a Long variable called testLong, although when I insert 9223372036854775807 as the value, I get an error stating:
"The literal of int 9223372036854775807 is out of range."
Solution is add a capital L to the end:

declaring floating and long types correctly in java?

So I understand the point that if I am declaring a long variable I need to add a L in the end of number.
long x = 123L;
Same with float type also, I need to add a F at the end of variable.
float x = 1.1F;
but I was wondering why its done differently in these two cases?
I mean If i am declaring a int or any other data-type its done simply
int x = 1;
why declaration of these two data-types is done in a certain (for long and float types). I know its done this way I just want to understand why this is done in this way?
The difference is in literal values. According to Primitive values, literal numeric values belong for int and double types.
From Java Language Specification. Chapter 3. Lexical Structure. 3.10 Literals:
An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1)
(...)
A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d (§4.2.3).
It's all about type safety, in this way you have the control over the constants. Since int can contain less information than long it would be improper to write something like this:
int variable = 1000000000000;
It is allowed in C/C++ language, but the value is shinked anyway. Since Java cares about all of mistakes you need to specify L at the end of the number constant and that way you would have type mismatch error and you need to correct either value or variable type.
For integer literals (int, long), the default is int.
However, for floating point literals (float, double) the default is double. This is because using double potentially allows safer arithmetic on the stored values.
That is why while declaring a float or a long, you need to specifically specify them at the time of declaration using L or F.
In the examples you mention the suffixes seem redundant, but there are other cases such as with two overloaded methods test(long x) and test(int x). Whether or not a literal argument uses suffix L will determine which one gets called, e.g. test(123L) will call the first, whereas test(123) will call the second. And you don't want cluttered code with unnecessary suffixes, so there is no suffix I (nor D), and 123 will do just fine for a literal of type int.
Simple and Clear
Think like this, In an application I have declared int a = 10;, but in future, my application needed to store value something like a = 987,654,321,321,321 then this is not possible. Compiler will throw a error message
Example
public class Z {
public static void main(String[] args){
int a=10;
a=987654321321321;
System.out.println(a);
}
}
Compilation
G:\Java>javac Z.java
Z.java:4: error: integer number too large: 987654321321321
a=987654321321321;
^
1 error
To over come above problem, we while declaring the variable, clearly tell the compiler that the value we are going to store is of long type and not int ( So, compiler will not hava any confusion in resolving the problem)
public class Z {
public static void main(String[] args){
long a=10L;
a=987654321321321L;
System.out.println(a);
}
}
Compiling and Executing The Above Code
G:\Java>javac Z.java
G:\Java>java Z
987654321321321
int:
Int data type is a 32-bit signed two's complement integer.
Minimum value is - 2,147,483,648.(-2^31)
Maximum value is 2,147,483,647(inclusive).(2^31 -1)
Int is generally used as the default data type for integral values unless there is a concern about memory.
The default value is 0.
Example: int a = 100000, int b = -200000
long:
Long data type is a 64-bit signed two's complement integer.
Minimum value is -9,223,372,036,854,775,808.(-2^63)
Maximum value is 9,223,372,036,854,775,807 (inclusive). (2^63 -1)
This type is used when a wider range than int is needed.
Default value is 0L.
Example: long a = 100000L, int b = -200000L
It is not about the declaration at all. I'm not going into a verbose answer. Just simply try this first
System.out.println(123L);
and then
System.out.println(123F);
That should clear things for you :)

declaring long types correctly in java?

I was reading about the topic base types from the book datastructures and algorithms in java.
I am quoting some text from the topic which might help:
"A variable declared to have one of these types simply stores a value of that type,
rather than a reference to some object. Integer constants, like 14 or 195, are of type
int, unless followed immediately by an 'L' or 'l', in which case they are of type long.
Floating-point constants, like 3.1415 or 2.158e5, are of type double, unless
followed immediately by an 'F' or 'f', in which case they are of type float. We show
a simple class in Code Fragment 1.2 that defines a number of base types as local
variables for the main method." - form the book
and then in the example code:
long l = 890L;
my question is why do I need to put a L in the end if the type of l(variable) is already declared as long?
for example if I do:
long l = 890;
it still works so why in the example code its written as long l = 890L;
There is a distinction between the types of the variables and the types of the literals.
In this case:
long l = 890L;
You have a variable of type long and a literal of type long. Naturally this works.
In this case:
long l = 890;
You have a variable of type long and a literal of type int. The integer is automatically promoted to a long (because it will fit) and this works too. It's the same as this:
int i = 890;
long l = i;
Note that you can't do this:
int i = 890L;
This is because although in this case 890 is small enough to fit in an integer, there is no general rule to convert longs automatically to integers because that is not always the case.
Note that you can't do this either:
long l = 3000000000;
This is because you're trying to declare a literal of type int, but the number is too big to fit in an int.
This is a widening implicit conversion. Java can clearly tell that you are attempting assign the int value 890 to the long l. This is successful (without a cast) because it can be done without any data loss.
I cannot tell you why the example uses 890l. I can hypothesize that it is doing so to be explicit, but this is simply a guess.
I don't know exactly why it was designed like that, but if you have an integer without the L after it, it is assumed that that is an int. Try a defining a big number (outside the int scope) without the L, the compiler will tell you there's something wrong.
Same goes for numbers that are not integers: if you want a float, you gotta add a F suffix (such as 3.1415F) otherwise it is assumed that it's a double.
why in the example code its written as long l = 890L;
To be more explicit that the author expects the value to be a long.
Personally I prefer brevity and leave it to the developer to work out the value will be a long, if they care, and most likely they won't even think about it.

Narrowing Type Conversion: Why is assignment of int to a byte in a declaration allowed?

This may sound too trivial for an intermediate Java programmer. But during my process of reviewing Java fundamentals, found a question:
Why is narrowing conversion like:
byte b = 13;
will be allowed while
int i = 13;
byte b = i;
will be complained by the compiler?
Because byte b = 13 ; is assignment of a constant. Its value is known at compile time, so the compiler can/should/will whine if assignment of the constant's value would result in overflow (try byte b = 123456789 ; and see what happens.)
Once you assign it to a variable, you're assigning the value of an expression, which, while it may well be invariant, the compiler doesn't know that. That expression might result in overflow and so the compiler whines.
From here:
Assignment conversion occurs when the
value of an expression is assigned
(§15.26) to a variable: the type of
the expression must be converted to
the type of the variable. Assignment
contexts allow the use of an identity
conversion (§5.1.1), a widening
primitive conversion (§5.1.2), or a
widening reference conversion
(§5.1.4). In addition, a narrowing
primitive conversion may be used if
all of the following conditions are
satisfied:
The expression is a constant expression of type byte, short, char or int.
The type of the variable is byte, short, or char.
The value of the expression (which is known at compile time, because it is a constant expression) is representable in the type of the variable.
In your example all three conditions are satisfied, so the narrowing conversion is allowed.
P.S. I know the source I'm quoting is old, but this aspect of the language hasn't changed since.
Because a literal number has no type.
Once you give it a type it must be casted to the other one:
int i = 13;
byte b = (byte) i;
A byte has 8 bits. An int, 32 bits, and it is a signed number.
Conversion from a number with a smaller range of magnitude ( like int to long or long to float ) is called widening. The goal of widening conversions is to produce no change in the magnitude of the number while preserving as much of the precision as possible. For example, converting the int 2147483647 to float produces 2.14748365e9 or 2,147,483,650. The difference is usually small, but it may be significant.
Conversely, conversion where there is the possibility of losing information about the magnitude of the number ( like long to int or double to long ) is called narrowing. With narrowing conversions, some information may be lost, but the nearest representation is found whenever possible. For example, converting the float 3.0e19 to long yields -9223372036854775807, a very different number.

Categories

Resources