我可以将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?
我可以将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?
的char
到int
促进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位值。我不确定为什么这是可以接受的参考类型,而不是原始类型,但它可能与原语所需的所有特殊处理有关。
谢谢埃里克森。我明白了你的观点。因此,当assign和char []对象指向int引用时,它将避免像Exceptions那样的ArrayStoreException。 – namalfernandolk
不确定我能为你提供更多的东西,除了从char []到int []的转换概念在语言规范中不存在。
在低层次上,它可能与迭代数组本身有关。如果我把一个char []像int []一样索引到低级别的内存中,它将无法工作。一个4字节的步骤(像int []那样处理)实际上会在char []中执行2个索引。
你不能以这种方式分配,因为它是一种类型不匹配。类型int []和char []不兼容。
int[] a = new int[4];
int[] b = a;
两个a
和b
将引用相同的阵列 - 没有介入的复制。
如果允许ints=chars
,则应该有一个int[]
变量引用一个16位的数组char
s。诸如ints[0] = 0x12345678
之类的分配是有效的,但结果应该是什么?
然后,为什么我不能指定一个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[]
。
它并不像您期望的那样工作,因为(在第一种情况下)该语言隐藏了您的某些类型转换细节。也就是说,当您将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;
宽元转换不会失去对数值的 总体规模的信息。 _特殊情况_。见@埃里克森的答案。 – paislee
你可以使用ByteBuffer来实现类似的'ByteBuffer.asCharBuffer' - >'char []'和'ByteBuffer.asIntBuffer' - >'int []'。如果您使用相同的底层缓冲区,它们共享相同的内存。 – bestsss