Primitive Type 'Short' - Casting in Java

Java - short and casting

These are the relevant JLS sections:

JLS 5.1.1 Identity Conversion

A conversion from a type to that same type is permitted for any type.

JLS 5.2 Assignment Conversion

Assignment conversion occurs when the value of an expression is assigned to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of one of the following:

  • Identity conversion
  • [...]

In addition, if the expression is a constant expression 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.

The above rules explain all of the following:

short a = 4;     // representable constant
short b = 5; // representable constant
short c = 5 + 4; // representable constant
short d = a; // identity conversion
short e = a + b; // DOES NOT COMPILE! Result of addition is int

short z = 32767; // representable constant
short z_ = 32768; // DOES NOT COMPILE! Unrepresentable constant

As to why this doesn't compile:

test(7); // DOES NOT COMPILE! There's no test(int) method!

It's because the narrowing conversion with constant is only defined for assignments; not for method invocation, which has entirely different rules.

JLS 5.3. Method Invocation Conversion

Method invocation conversions specifically do not include the implicit narrowing of integer constants which is part of assignment conversion. The designers of the Java programming language felt that including these implicit narrowing conversions would add additional complexity to the overloaded method matching resolution process.

Instead of explaining how method resolution works precisely, I will just quote Effective Java 2nd Edition, Item 41: Use overloading judiciously:

The rules that determine which overloading is selected are extremely complex. They take up thirty-three pages in the language specification, and few programmers understand all of their subtleties.



See also

  • Varying behavior for possible loss of precision
    • short x = 3; x += 4.6; compiles because of semantics of compound assignment

Why does casting a primitive type to a reference type is giving compilation error?

Because this

Long l = 1; 

means assigning an int (literal number without floating part are int) to an Object, here a Long.

The autoboxing feature introduced in Java 5 doesn't allow to box from an int to something else than a Integer. So Long is not acceptable as target type but this one would be :

Integer i = 1;  

In your working example you convert the int to a long : (long)8.

So the compiler can perfectly box long to Long.

Primitive type casting in java (disconcerting examples)

The first two are handled by the same case - JLS section 5.2:

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.

The third is simply a case of regular conversion from a literal in source code to a double: the nearest exact double to 6.0000000000000000000000000000000001 is 6.0. So if you had:

double d = 6.0000000000000000000000000000000001;

that would assign a value of 6.0 to d, as that's the closest representable double to the value specified in the source code.

Conversion of one primitive type to another in java

Int literals (like 1) are expressions of type int.

Overload resolution proceeds in a number of stages, looking for a method which can accept the parameters with the types you are passing.

  1. If there is a single overload where the actual parameters have the same types as the formal parameters, invoke that.
  2. If there is a single non-varargs overload where the actual parameters can be automatically converted (e.g. by widening or un/boxing) to be of the same types as the formal parameters, invoke that.
  3. If there is a single varargs overload where the actual parameters can be automatically converted to be of the same types as the formal parameters invoke that.
  4. Otherwise, error.

These phases are applied in turn, continuing until a match is found.

Since there is an overload of m1 which takes int, a match is found in phase 1, so no conversion of that value to another type needs to happen.

Is there a method in Java that mimics the cast of primitive type to Character?

If you're modifying bytecode, I think you do not need to cast to char. In the bytecode, the char type is a second-class citizen actually handled as an int. From JVMS §4.9.2:

An instruction operating on values of type int is also permitted to operate on values of type boolean, byte, char, and short.

As noted in §2.3.4 and §2.11.1, the Java Virtual Machine internally converts values of types boolean, byte, short, and char to type int.)

So while you can't, say, assign an int to a char in the Java language without an explicit cast, you can do that in the bytecode, since they have the same "verification type", which is int. The bytecode representation of a char is just an int that happens to have its upper two bytes zero. So instead of:

char ch = num.charValue();

You would be able to get away with (in bytecode):

int ch = num.intValue() & 0x0000FFFF;

And then just pretend that ch is a char (e.g., pass it to methods that expect a char or store it in a char field or array).

However, if I understand it correctly, that's what the i2c int to char cast instruction already does, so replacing it by an explicit AND operation is not going to be any simpler.

It's also surprisingly hard to find what actually happens if you cast a (signed)double into an (unsigned)char.

When you cast from float or double to byte, short, or char, it first casts to int, which saturates out-of-range values to Integer.MAX_VALUE or Integer.MIN_VALUE, and then truncates the bytes of the int to fit the final type. See JLS §5.1.3 – Narrowing Primitive Conversion. The truncation step means that conversion of out-of-range floating-point values to byte, short, or char is probably not going to give a useful result.

Directly casting primitive type to object is fine in Java?

Autoboxing is the automatic conversion that the Java compiler makes
between the primitive types and their corresponding object wrapper
classes.

int intValue = 0;
Integer value = intValue; // by Autoboxing

you can also convert it using valueOf method of wrapper class

Integer value = Integer.valueOf(intValue)

Check What code does the compiler generate for autoboxing? if you still have doubts.

Trouble casting integer object to primitive type

Arrays.asList(elements) does not do what you think it does, it returns a list of containing the int[] array, not the elements of the array. You can not create a list of primitives. If you want to use List you must first convert the int to Integer.

You can get a List of Integer with

List<Integer> arrList = Arrays.stream(elements).boxed().collect(Collectors.toList());

however, you still have a bug in your program where you will skip numbers.

for (int j = i + 1; j < arrList.size(); j++) {
if (arrList.get(j).equals(current) && occurrences >= maxOccurrences) {
arrList.remove(j); // This shortens the list causing us to skip the next element
j--; // One hackish way is to go back one step

} else if (arrList.get(j).equals(current)) {
occurrences++;
}
}

One solution is to loop backwards instead

for (int j = arrList.size() - 1; j > i; j--) {
if (arrList.get(j).equals(current) && occurrences >= maxOccurrences) {
arrList.remove(j);
} else if (arrList.get(j).equals(current)) {
occurrences++;
}
}

Why does casting a primitive type to a reference type is giving compilation error?

Because this

Long l = 1; 

means assigning an int (literal number without floating part are int) to an Object, here a Long.

The autoboxing feature introduced in Java 5 doesn't allow to box from an int to something else than a Integer. So Long is not acceptable as target type but this one would be :

Integer i = 1;  

In your working example you convert the int to a long : (long)8.

So the compiler can perfectly box long to Long.



Related Topics



Leave a reply



Submit