Cannot convert from char[] to int[] - java

I can assign char to int as follows.
char c = 'a';
int a = 0;
a = c;
Then, why I can't assign a char[] to int[]?
int[] ints= new int[4];
char[] chars= new char[4];
ints = chars; // Cannot convert from char[] to int[] ?? But why?

The char to int promotion is a special provision for primitive types.
Regarding arrays, the Java Language Specification says this:
If an array variable v has type A[], where A is a reference type, then
v can hold a reference to an instance of any array type B[], provided
B can be assigned to A. This may result in a run-time exception on a
later assignment; see §10.10 for a discussion.
This works only "if A is a reference type." Even though char can be assigned to int, this rule doesn't apply because it doesn't apply to primitive types.
So, without any special provision for assigning incompatible types, the assignment fails.
If it were allowed, you'd introduce the possibility of ArrayStoreException being raised on stores to primitive arrays (just like you currently have with arrays of reference types):
ints[0] = Integer.MAX_VALUE; /* Exception! */
This happens because ints is an alias to a char[] that can't accommodate a 32-bit value. I'm not sure why this is acceptable for reference types, and not for primitives, but it probably has to do with all of the special treatment already required for primitives.

Not sure I can supply more for you other than the concept of casting from char[] to int[] doesn't exist in the language specification.
At a low level, it probably has to do with iteration through the array itself. If I treat a char[] like an int[] indexing through it in memory at a low level wouldn't work. A step of 4 bytes (treating like int[]) would actually step 2 indices in a char[].

Then, why I can't assign a char[] to int[]?
The first answer is because the Java Language Specification forbids this. The key section is 4.10.3. which specifies the subtyping rules for array types. The rules mean that no primitive array type is a subtype of another (different) primitive array type. One consequence of that is the assignment is forbidden.
The second answer (and the reason that the JLS forbids it) is that it would break the type system if it was allowed. Consider this example:
int[] ints= new int[4];
char[] chars= new char[4];
ints = chars;
The assignment is a reference assignment. What this means is that ints would now point to the array object that was created by new char[4] on the previous line. (It is NOT equivalent to a loop that assigns the values of chars' elements to ints.)
Now lets add a method:
public void paranoidIncrement(int[] ints) {
for (int i = 0; i < ints.length; i++) {
int tmp = int[i];
ints[i] = ints[i] + 1;
assert tmp + 1 == ints[i];
}
}
and lets combine it with the previous code:
int[] ints= new int[4];
char[] chars= new char[4];
ints = chars; // assume this is legal ...
paranoidIncrement(ints);
So what does this mean? Well paranoidIncrement is going to treat the argument (which is really a char[]) as if it was an int[]. But what happens when we do ints[i] = ints[i] + 1;? If the cells of the actual array are really chars then the JVM has to truncate the values to make them fit, or throw an exception.
If it truncates the value, then the assert statement will fail. And that is so counter-intuitive that it is just plain broken.
If it throws an exception, then we've suddenly got a whole class of new bugs that are (under the JLS rules) currently detected at compile time.
The way that Java avoids that brokenness is to say that you can't assign a char[] to an int[].

int[] a = new int[4];
int[] b = a;
Both a and b will reference the same array - there is no copying involved.
If ints=chars were allowed, you would have an int[] variable referencing an array of 16-bit chars. An assignment such as ints[0] = 0x12345678 would be valid, yet what should the outcome be?

You cannot assign in this manner because it is a type mismatch. The types int[] and char[] are not compatible.

It doesn't work as you expect because (in the first case) the language is hiding some of the type conversion details from you. That is, when you assign a char to an int it's sometimes called an implicit cast. It's equivalent to doing this:
char c = 'a';
int a = 0;
a = (int) c;
... which would work fine, but the language doesn't force you to write the (int) cast every time.
In the second example, a cast will not work. If you try to add an explicit cast in, you would get an error such as:
Foo.java:9: inconvertible types
found : char[]
required: int[]
int[] ints = (int[]) chars;

Related

Can we convert int to Byte using wrapper class, without type casting?

I was learning wrapper class, here I learned how to convert int to Interger wrapper class.
But I want to convert int to Byte using Byte wrapper class.
I have tried
int a =10;
Byte c = Byte; //(Not getting suggestion in eclipse)
for example, I know how to convert int to Interger refer code below.
int a =10;
Integer b = Integer.valueOf(a);
You could add an additional cast to the integer like this:
int a = 10;
Byte c = Byte.valueOf((byte)a);
Try it online.
Btw, going from a primitive to an Boxed value is done implicitly by the compiler. So the code above doesn't necessary need the .valueOf:
int a = 10;
Byte c = (byte)a;
Try it online.
But, when you're explicitly casting values, always keep in mind that it can hold unexpected results when doing it wrong. In this case for example, the size of a a byte is smaller than an integer (the range of a byte is [-128, 127] and of an int is [-2147483648, 2147483647]), so something like this wouldn't give the expected result:
int a = 200;
Byte c = Byte.valueOf((byte)a); // Results in -56
Try it online.
This is also the reason why you usually can't go to a smaller type, since it might not fit, but you can go to a larger one without needing the cast:
byte a = 10;
Integer c = Integer.valueOf(a);
Try it online.
int x=30;
Byte c = (byte)x; // Java has auto boxing for wrapper class Byte to byte and opposite automatically
You can cast the same way you normally do with Integer wrapper.
int a =10;
Byte b = Byte.valueOf((byte)a);
//b = 10
An int is 4 bytes. So you can't convert an integer to a byte without losing some data.
int a =1000;
Byte b = Byte.valueOf((byte)a);
//b = -24
You can, however, convert an int to an array of bytes.
Java - Convert int to Byte Array of 4 Bytes?
Same you can do for Byte too:
1. autoboxing
Byte b = (byte) a;
2. valueOf(byte b)
Byte b = Byte.valueOf((byte)a)
Returns a Byte instance representing the specified byte value. If a new Byte instance is not required, this method should generally be used in preference to the constructor Byte(byte), as this method is likely to yield significantly better space and time performance since all byte values are cached.
From JLS 5.0-2. Conversions In Various Contexts so you can't perform 5.1.3. Narrowing Primitive Conversion without cast operator.
// Casting conversion (5.4) of a float literal to
// type int. Without the cast operator, this would
// be a compile-time error, because this is a
// narrowing conversion (5.1.3):
int i = (int)12.5f;

Why is the compiler not giving a compiler error since I am comparing int[] array with a string value?

In the commented line compiler does not give any errors and I'm confused why? Should I not have done and casting? I guess not since it seems to be working just fine but I don't know why!
public class Stack {
int[] array;
public Stack(int n)
{
maxsize = n;
length = maxsize;
array = new int[maxsize];
top = 0;
}
public void Delete()
{
if( array[0] != '\0' ) // \0 is string while array is of type int
{
array[top-1] = 0;
top= top-1;
}
}
}
'\0' is a char, not a string.
You can compare int with a char
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).
char is a 16-bit unsigned integer
You are actually comparing an int with a char, because you use single brackets.
This is possible, since typecasting allows you to convert a higher data type into lower.
Comparing a String to an int, or int[] for that matter, gives you a compile error.
'/0' is a char not a string, and when you are comparing them, then that char is automatically converted to int value (which is its ASCII value), and there is no exception.

add two char data type in java

case 1:
char c='A'+'A';
System.out.println(c); // print question mark (?)
case 2:
char c1='A';
char c2='A'+c1; // Compile time error
System.out.println(c2);
In case1 I have logic When I am adding two char literals, the sum of ascii value is printing which is equivalent to ascii value of question mark.
But in case2 why compile time error is showing that 'cannot convert from int to char'
if char+char=int then this rule must be apply for both cases.
In the first case two final chars are added and at compile time it is checked that the resulting int does not overflow a char.
In the second case one operand is not final, and the compiler refuses to do a sum.
A bit dumb, but considering multithreading and other cases, maybe justifiable. At least an easily understood rule.
Doing
final char c1 = '0';
char c2 = '1' + c1; // 'a'
should compile.
(It goes without say, that one should never do something like '0'+'1'.)
Addition or 2 or more variables which are of type int or lower than int results in the type int.
So what you are doing with char c2 = 'A' + c1; is actually not giving you a char result. It is giving you int result which you are trying to implicitly type cast to byte, which gives you the compile time error.
Summary
Char + Char = Int
And Char cannot directly store Int.
Try and do this instead
char c2 = (char)('A' + c1);
Here you explicitly type cast the int value to char type
Telling the compiler that you are ready to accept the Lossy Conversion that may happen
In the second case there is an error because, by JLS 5.6.2 both operands of the binary expression are converted to int.
To make it work you should add explicit cast:
char c2=(char)('A'+c1);
The result of adding Java chars, shorts, or bytes is an int
See the detailed answers on this post:
In Java, is the result of the addition of two chars an int or a char?

Why no explicit casting is required while assigning int to char [duplicate]

I wanted to know why this snippet works.
char ch1;
ch1 = 'a' + 1;
System.out.println(ch1);
In line 2, isn't the right hand side promoted to an int and then for assigning int to char, won't we need an explicit cast?
Similarly, I understand what happens when you do ch1 = 65. But since Java does not allow automatic down type conversion, don't we need explicit cast from int to char?
Because the Java Language Specification says:
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.
So you're right in that the expression is promoted to int, but because it's a constant expression, the cast is not necessary. If it involved a variable (or its value did not fit into a char), it would be different.
For this kind of question it's best to look at the language specification right away, as it's the authoritative source and quite readable for a specification.
I'm using Eclipse at the moment. There are two things to note:
The compiler checks for bounds during initialization.
The compiler calculates the values of constant expressions, such as 3 * (2 + 1).
This works:
byte b = 127; // works, range of a byte is [-128, 127]
But this does not:
byte b = 128; // does not work, outside of range
This works:
byte b = 100 + -228; // works, 100 + -228 = -128
But this does not:
byte b = 1;
byte c = b + 1; // does not work, why not?
And this does not, either:
byte b = 1;
byte c = b + (byte) 1; // does not work, why not?
Note that b is a variable expression. If a variable expression is involved, the result of the operator + is at least as large as an int. Therefore, you can't assign it to c. Unlike constant expressions, the compiler does not calculate variable expressions.
The compiler would similarly complain for short and char - try it out yourself.
And finally, using final on a variable effectively turns it into a constant expression, so this would work:
final byte b = 1;
byte c = b + 1; // works

Why can I assign an int to a char variable without an explicit cast?

I wanted to know why this snippet works.
char ch1;
ch1 = 'a' + 1;
System.out.println(ch1);
In line 2, isn't the right hand side promoted to an int and then for assigning int to char, won't we need an explicit cast?
Similarly, I understand what happens when you do ch1 = 65. But since Java does not allow automatic down type conversion, don't we need explicit cast from int to char?
Because the Java Language Specification says:
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.
So you're right in that the expression is promoted to int, but because it's a constant expression, the cast is not necessary. If it involved a variable (or its value did not fit into a char), it would be different.
For this kind of question it's best to look at the language specification right away, as it's the authoritative source and quite readable for a specification.
I'm using Eclipse at the moment. There are two things to note:
The compiler checks for bounds during initialization.
The compiler calculates the values of constant expressions, such as 3 * (2 + 1).
This works:
byte b = 127; // works, range of a byte is [-128, 127]
But this does not:
byte b = 128; // does not work, outside of range
This works:
byte b = 100 + -228; // works, 100 + -228 = -128
But this does not:
byte b = 1;
byte c = b + 1; // does not work, why not?
And this does not, either:
byte b = 1;
byte c = b + (byte) 1; // does not work, why not?
Note that b is a variable expression. If a variable expression is involved, the result of the operator + is at least as large as an int. Therefore, you can't assign it to c. Unlike constant expressions, the compiler does not calculate variable expressions.
The compiler would similarly complain for short and char - try it out yourself.
And finally, using final on a variable effectively turns it into a constant expression, so this would work:
final byte b = 1;
byte c = b + 1; // works

Categories

Resources