Java: must cast to short, cannot use shorthand 'S' - java

I am trying to call a function that requires a short value. The following works:
i.setDamage((short) 10);
However, this does not:
i.setDamage(10S);
According to the IDE I am using, this should work. Why does it not? I am using Maven and Java 7.

According to the Java Language Specification, Section 3.10.1, the only integer type suffix for integer literals is L (or lower case l).
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).
The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one).
You'll just have to stick with a cast. (Although you may be able to just use the integer literal without a cast if the value is in range.)

According to the Java Language the long value will only hold the suffix of L.
Refer
Java Primitive Data types

JAVA doesn't provide any suffix like S or s for short. You need to cast to shortusing (short)100.
Possible values are
int num = 20; //Decimal
int num = 020; //octal
int num = 0x20; //Hexadecimal
int num = 0b1010; //binary
long num = 563L; //long
In JDK 7, you can embed one or more underscores in an integer literal like
int num = 19_90;

Related

Promotion of primitive types

I have a question about the promotion of primitive types in Java. As we can see in the following example, one of the methods does not compile due to an error of type mismatch. Each method returns the same value but in different types.
The version of primitive long method works without error while the version of wrapper class Long fails. This is because the int literal in the return statement will be first promoted to a broader primitive type (e.g. long) and then to the corresponding wrapper class Integer and so on. Since Integer is not a subclass of Long the compiler gives an error.
But why does the version of wrapper class Byte works without any error? What exactly does the compiler do at this point?
long getPrimitiveLong() {
return 12; // valid
}
Long getWrapperLong() {
return 12; // Error: type mismatch
}
Byte getWrapperByte() {
return 12; // valid
}
The version with Byte works through some compiler magic.
Unlike long numeric literals which can be constructed with a L suffix, e.g. 12L, there is no such thing as a byte literal. That is why Java compiler treats numeric literals that fit in a byte as byte literals. Hence, 12 in your last example is considered a constant of type byte.
Java Language Specification offers a description of this conversion in section 5.2:
A narrowing primitive conversion followed by a boxing conversion may be used
if the type of the variable is:
Byte and the value of the constant expression is representable in the type byte.
Short and the value of the constant expression is representable in the type short.
Character and the value of the constant expression is representable in the type char.
This is because Java allows 1 conversion or Autoboxing, not more.
Java can do all these:
int i = 5;
double d = i; // int to double
long l = i; // int to long
long l = d; // double to long
Or autobox:
Integer i = 5; // int to Integer
Double d = 5.0; // double to Double
Long l = 5L; // long to Long
Converting twice, say int to Double, gives Java a hard time.
number like 12 consider as int by default by the compiler that is why the error
To fix that you can use casting for byte and place L after the value of long variable.
Read following post for more details
http://javaseeeedu.blogspot.com/2015/12/casting-part-1.html
As a short answer - try to replace 12 with 128 (byte is in range -128 to 127).
It won't compile, right?
The outcome here is that the compiler knows about byte boundaries.
For the in-depth answer you can do a deep dive into OpenJDK.

Why initialization of new Long Wrapper with int literal is valid?

Looking at the Java Doc for Long, it only has two constructors:
1) primitive long as param --> new Long(10L);
2) String as param --> new Long("23");
But this works
new Long(23);
But if the literal is more than the int MAX VALUE (2147483647), the L suffix becomes mandatory so this: (
new Long(2147483648) will now require an L after the value
However:
new Long(Integer.MAX_VALUE + 1) is OK
Who can explain this?
The first part of your question is straightforward: passing int where long is required is allowed because any number that can be represented as an int can also be represented as a long. This is a so-called widening conversion.
The second part, about new Long(Integer.MAX_VALUE + 1), is trickier. Although the widening conversion occurs here as well, it is not of the value that one might think: if you run this program
Long x = new Long(Integer.MAX_VALUE + 1);
System.out.println(x);
you get -2147483648, not the expected 2147483648, because of int overflowing on addition (demo).
The compiler is not smart enough to promote parts of the expression to long before performing addition. Widening conversion occurs after the addition has been performed, on the result of the addition with an overflow.
You can find the answer in javadocs:
A widening primitive conversion from an integral type to another integral type, or from float to double in a strictfp expression (§15.4), does not lose any information at all; the numeric value is preserved exactly.
The integer value 23 can be converted to long 23L without loss of any information at all. Thus with the use of through widening primitive conversions, JVM implicitly converts it to 23L.
So when you call
new Long(23)
It becomes
new Long(23L)
When we write new Long(23) , you can think of it as something like the following happening :
int i = 23;
long l = i; // widening primitive conversion
Long newLong = new Long(l);
Widening conversions are allowed as per the JLS 5.1.2 , so there are no issues with it.
When we try instead , new Long(2147483648) , the first step itself fails, as the value is more than what can fit in an int
int i = 2147483648; // doesn't fit in int
When we try new Long(Integer.MAX_VALUE + 1), you can think of it as something like the following happening:
int i = Integer.MAX_VALUE + 1; // This gives the INTEGER.MIN_VALUE -2147483648
long l = i ; // widening primitive conversion
Long newLong = new Long(l);
So, this is allowed. Hope this helps.
The differences come from using literal or not.
By using a literal,
long1 = new Long(2147483648)
The code will not compile as the compiler checks the validity of the literal again the type of the variable that receives the literal value and 2147483648 is out of range for an int. So the compiler emits an error.
It is valid for any literal.
As the compiler expects to have a specific type as value of the literals, so it does the check :
The type of a literal is determined as follows:
The type of an integer literal (§3.10.1) that ends with L or l is long
(§4.2.1).
The type of any other integer literal is int (§4.2.1).
...
By using a computation :
long1 = new Long(Integer.MAX_VALUE + 1);
the compiler doesn't check if the size of the Long argument constructor is in the int range.
It is not a literal declaration.
At runtime, an int to long widening primitive conversion occurs.
It produces so a int with Integer.MAX_VALUE + 1 that is -2147483648 (overflow of int) that is converted to a long value.

compile error, too large integer. CreditCardAnalysis.Java

I'm struggling to figure out what the compile/syntax error is in my code.
public class CreditCardValidation {
public static void main (String[] args){
System.out.print(prefixMatched(4388576018402626, 4388));
}
/*
Return the number of digits in d
*/
public static int getSize(long d) {
int size = 0 ;
while( d > 0 ) {
d = d / 10 ;
size = size + 1 ;
}
return size ;
}
/*
Return the first k number of digits from number. If the number of digits in number is
less than k, return the number.
*/
public static long getPrefix(long n, int k) {
int f = getSize(n)-k;
long prefix = n/((int)(Math.pow(10, f)));
return prefix;
}
/*
Return true if the digit d is a prefix for number.
*/
public static boolean prefixMatched( long number, int d ) {
if ( d == getPrefix(number, 4))
return true ;
else
return false ;
}
}
As you can see I'm trying to call prefixMatched to check whether the credit card number meets the requiremen; if digit d is a prefix for number. However, the only thing I get back from the compiler is:
"CreditCardValidation.java:6: integer number too large: 4388576018402626
System.out.print(prefixMatched(4388576018402626, 4388));
^"
I'm sorry if my question is too vauge, this is my first post.
You need to indicate to the compiler that your constant (the CC number) is a long. Put an L on the end of the constant.
It's actually a little easier to treat CC numbers as strings and use charAt(x) to calculate check digits.
The problem is that you are specifying an integer literal 4388576018402626 and that number is larger than the maximum integer, 2147483647.
You are attempting to pass it to a method that takes a long, so make it a long literal by appending L:
System.out.print(prefixMatched(4388576018402626L, 4388));
The JLS specifies this behavior in Section 3.10.1:
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).
and
It is a compile-time error if a decimal literal of type int is larger than 2147483648 (231), or if the decimal literal 2147483648 appears anywhere other than as the operand of the unary minus operator (§15.15.4).
add L at the end of your literal :
4388576018402626L
You should use Long instead of Integer
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 264-1. The unsigned long has a minimum value of 0 and maximum value of 264-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
You should use following to avoid exception:
System.out.print(prefixMatched(4388576018402626L, 4388));
The L indicates given value is long. You can use either l or L but I prefer to use L because it looks goods while looking code.
Source: Oracle Docs.
For this code, I would recommend using String instead of dealing with long and int. It's far easier when trying to match the first four digits, which can be isolated easily using String#substring: (String_name).substring(0,4) will be return first four digits of the String. This can then be parsed as an int using Integer#parseInt, or simply compared to another String (if the prefix were a String as well).

Java - Error on: long n = 8751475143;

This number falls into the long range, so why do I get the error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The literal 8751475143 of type int is out of range
Make it
long n = 8751475143L;
L will make it long literal
by default its int
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). The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one). [..]
The target of the assignment isn't taken into account when parsing the literal - so you need the L suffix:
long n = 8751475143L;
For the most part - and there are a few notable exceptions - the type of an expression is determined without much reference to its context. So as per section 3.10.1 of the JLS, an integer literal is of type int unless it has an l or L suffix, and the range of an integer literal of type int is of course limited to the range of int itslf.
All numbers in java are treated as integers, unless you say otherwise (or you use a decimal separator - then they are treated as a floats).
So, if you write
long i = 1234;
java will tread the number 1234 as integer, and do the type-cast to long for you.
However, if you type:
long n = 8751475143;
Java cannot treat 8751475143 as integer, because it's out of range. You need to specify, that what you meant was long, by adding 'L' at the end:
long n = 8751475143L;

Initialize a long in Java

Primitive Data Types - oracle doc says the range of long in Java is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
But when I do something like this in my eclipse
long i = 12345678910;
it shows me "The literal 12345678910 of type int is out of range" error.
There are 2 questions.
1) How do I initialize the long with the value 12345678910?
2) Are all numeric literals by default of type int?
You should add L: long i = 12345678910L;.
Yes.
BTW: it doesn't have to be an upper case L, but lower case is confused with 1 many times :).
You need to add the L character to the end of the number to make Java recognize it as a long.
long i = 12345678910L;
Yes.
See Primitive Data Types which says "An integer literal is of type long if it ends with the letter L or l; otherwise it is of type int."
You need to add uppercase L at the end like so
long i = 12345678910L;
Same goes true for float with 3.0f
Which should answer both of your questions
To initialize long you need to append "L" to the end.
It can be either uppercase or lowercase.
All the numeric values are by default int. Even when you do any operation of byte with any integer, byte is first promoted to int and then any operations are performed.
Try this
byte a = 1; // declare a byte
a = a*2; // you will get error here
You get error because 2 is by default int.
Hence you are trying to multiply byte with int.
Hence result gets typecasted to int which can't be assigned back to byte.

Categories