namalfernandolk
namalfernandolk

Reputation: 9134

Cannot convert from char[] to int[]

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?

Upvotes: 4

Views: 2559

Answers (6)

Stephen C
Stephen C

Reputation: 718788

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[].

Upvotes: 2

mpontillo
mpontillo

Reputation: 13947

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;

Upvotes: 0

erickson
erickson

Reputation: 269667

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.

Upvotes: 4

Vlad
Vlad

Reputation: 18633

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?

Upvotes: 1

ncmathsadist
ncmathsadist

Reputation: 4891

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

Upvotes: 0

rfeak
rfeak

Reputation: 8204

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[].

Upvotes: 2

Related Questions