Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is casting to short to char is a narrowing conversion?

Tags:

java

casting

A narrowing conversion is when putting a data type that can hold a bigger value into a data type that can hold at max a lesser value.

long l = 4L;
int i = (int)l;

However I don't understand why a short into a char is a narrowing conversion but I've the intuition it is related to signed/unsigned of those two datatypes but I can't explain why.

short s = 4; // short max value is 32767
char c = (char)s; // char max value is 65535 

It looks like it would be a widening conversion or at the very least neither narrowing neither widening since they are both 16 bits and can hold the same number of values.

    System.out.println((int)Character.MIN_VALUE); //0
    System.out.println((int)Character.MAX_VALUE); //65535 
    System.out.println(Short.MIN_VALUE); //-32768
    System.out.println(Short.MAX_VALUE); //32767
    //65535 = 32768+32767
like image 522
Ced Avatar asked Jun 13 '16 05:06

Ced


2 Answers

This is because a short is capable of holding negative values while char isn't as you might have seen from Character.MIN_VALUE. Let me give a few examples.

  short s = -124;
  char c = 124; // OK, no compile time error
  char d = -124; // NOT OK, compile time error since char cannot hold -ve values
  char e = s; // NOT OK, compile time error since a short might have -ve values which char won't be able to hold
  char f = (char)s; // OK, type casting. The negative number -124 gets converted to 65412 so that char can hold it
  System.out.println((short)f); // -124, gets converted back to a number short can hold because short won't be able to hold 65412
  System.out.println((int)f); // 65412, gets converted to 65412 because int can easily hold it.  

A (negative) number -n when cast to char, becomes 2^16-n. So, -124 becomes
2^16-124 = 65412

I hope this helps.

like image 81
Abdul Fatir Avatar answered Sep 30 '22 20:09

Abdul Fatir


The point of narrowing isn't about the bit size, but that some values cannot be properly represented in the new type.

As you have shown in the last piece of code, Short.MIN_VALUE < Character.MIN_VALUE, i.e. some short values cannot be represented in char.

Since you can't use char to faithfully represent negative numbers (the cast will cause a negative number be represented by its 2's complement, which isn't the same number), we consider the cast "loses information" and thus narrowing.

From the Java Language Specification, §5.1.3:

22 specific conversions on primitive types are called the narrowing primitive conversions:

  • short to byte or char
  • char to byte or short
  • ...

A narrowing primitive conversion may lose information about the overall magnitude of a numeric value and may also lose precision and range.

...

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

A narrowing conversion of a char to an integral type T likewise simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the resulting value to be a negative number, even though chars represent 16-bit unsigned integer values.

like image 28
kennytm Avatar answered Sep 30 '22 21:09

kennytm