2012-01-26 74 views
4

我可以将char指定给int,如下所示。无法从char []转换为int []

char c = 'a'; 
int a = 0; 
    a = c; 

那么,为什么我不能指定一个字符[]为int []

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars; // Cannot convert from char[] to int[] ?? But why? 
+0

宽元转换不会失去对数值的 总体规模的信息。 _特殊情况_。见@埃里克森的答案。 – paislee

+0

你可以使用ByteBuffer来实现类似的'ByteBuffer.asCharBuffer' - >'char []'和'ByteBuffer.asIntBuffer' - >'int []'。如果您使用相同的底层缓冲区,它们共享相同的内存。 – bestsss

回答

4

charint促进is a special provision for primitive types.

关于阵列中,Java Language Specification says this:

如果数组变量v具有类型A [],其中A是一个引用类型,然后 -v可以保持一个参考提供给任何数组类型B []的实例,只要提供 B就可以分配给A.这可能会导致运行时异常在以后的分配上执行 ;参见§10.10进行讨论。

这只适用于“如果A是参考类型”。尽管char可以分配给int,但是该规则不适用,因为它不适用于基元类型。

因此,没有任何特殊的规定来分配不兼容的类型,分配失败。

如果允许,你会介绍ArrayStoreException的可能性调高商店基本数组(就像您目前有引用类型的数组):

ints[0] = Integer.MAX_VALUE; /* Exception! */ 

这是因为ints是别名为char[],无法容纳32位值。我不确定为什么这是可以接受的参考类型,而不是原始类型,但它可能与原语所需的所有特殊处理有关。

+0

谢谢埃里克森。我明白了你的观点。因此,当assign和char []对象指向int引用时,它将避免像Exceptions那样的ArrayStoreException。 – namalfernandolk

2

不确定我能为你提供更多的东西,除了从char []到int []的转换概念在语言规范中不存在。

在低层次上,它可能与迭代数组本身有关。如果我把一个char []像int []一样索引到低级别的内存中,它将无法工作。一个4字节的步骤(像int []那样处理)实际上会在char []中执行2个索引。

0

你不能以这种方式分配,因为它是一种类型不匹配。类型int []和char []不兼容。

1
int[] a = new int[4]; 
int[] b = a; 

两个ab将引用相同的阵列 - 没有介入的复制。

如果允许ints=chars,则应该有一个int[]变量引用一个16位的数组char s。诸如ints[0] = 0x12345678之类的分配是有效的,但结果应该是什么?

2

然后,为什么我不能指定一个char [] int []?

第一个答案是因为Java语言规范禁止这样做。关键部分是4.10.3.,它指定了数组类型的子类型规则。规则意味着没有原始数组类型是另一个(不同的)原始数组类型的子类型。这样做的一个后果是任务被禁止。

第二个答案(以及JLS禁止它的原因)是,如果允许,它会打破类型系统。考虑这个例子:

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars; 

该赋值是一个引用赋值。这意味着ints现在将指向上一行由new char[4]创建的数组对象。 (它不是相当于一个循环,chars“元素的值分配给ints。)

现在让我们来添加的方法:

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]; 
    } 
} 

,并允许与前面的代码结合起来:

int[] ints= new int[4]; 
char[] chars= new char[4]; 
ints = chars;    // assume this is legal ... 
paranoidIncrement(ints); 

那么这是什么意思?那么paranoidIncrement会将参数(它实际上是char[])视为int[]。但是当我们做ints[i] = ints[i] + 1;会发生什么?如果实际的阵列的单元格实际上是char s,那么JVM 已将截断值以使它们合适或引发异常。

  • 如果它截断该值,那么assert语句将失败。这是非常直观的,它只是简单的破碎。

  • 如果它抛出一个异常,那么我们突然收到了一整类新的错误,它们是在编译时检测到的(在JLS规则下)。

的方式,Java的避免了破碎是说,你不能分配char[]int[]

0

它并不像您期望的那样工作,因为(在第一种情况下)该语言隐藏了您的某些类型转换细节。也就是说,当您将char分配给int时,有时将其称为隐式转换。这相当于这样做:

char c = 'a'; 
int a = 0; 
    a = (int) c; 

...这将很好地工作,但语言不强迫你每次写(int)演员。

在第二个示例中,演员表不起作用。如果试图在添加明确演员,你会得到一个错误,如:

Foo.java:9: inconvertible types 
found : char[] 
required: int[] 
     int[] ints = (int[]) chars;