char c = 'a';
int a = 0;
a = c;
那么,为什么我不能将char[]赋值给int[]?
int[] ints= new int[4];
char[] chars= new char[4];
ints = chars; // Cannot convert from char[] to int[] ?? But why?
char c = 'a';
int a = 0;
a = c;
int[] ints= new int[4];
char[] chars= new char[4];
ints = chars; // Cannot convert from char[] to int[] ?? But why?
char
到int
的类型提升是基本类型的一种特殊规定。
关于数组,Java语言规范如下所述:
如果一个数组变量v具有类型A[],其中A是一个引用类型,那么 v可以保存对任何数组类型B[]的实例的引用,前提是 B可以分配给A。这可能会导致运行时异常发生在之后的赋值中;请参见§10.10进行讨论。
这只适用于"A是引用类型"的情况。即使char
可以分配给int
,但由于它不适用于基本类型,因此该规则不适用。
因此,在没有为分配不兼容类型提供任何特殊规定的情况下,分配将失败。
如果允许这样做,您将引入可能会导致原始数组存储(就像您当前使用引用类型数组一样)引发ArrayStoreException
的可能性:
ints[0] = Integer.MAX_VALUE; /* Exception! */
ints
是一个别名,指向无法容纳32位值的char[]
。我不确定为什么这对于引用类型是可以接受的,而对于基本类型却不行,但这可能与基本类型所需的所有特殊处理有关。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
,那么JVM必须截断值使其适应,否则就会抛出异常。
如果它截断了该值,则assert
语句将失败。这是如此反直觉以至于它根本是有问题的。
如果它抛出异常,则我们突然间就有了一整类新的错误,而这些错误(根据JLS规则)目前在编译时被检测到。
Java避免了这种不良影响的方法是说你不能将char[]
赋给int[]
。
除了char[]转换为int[]的概念在语言规范中不存在之外,我不确定我能为您提供更多内容。
在低级别上,这可能与对数组本身进行迭代有关。如果我将char[]视为int[]并在内存中索引它,则在低级别下无法正常工作。一个4字节的步骤(像int[]一样处理)实际上会在char[]中移动2个索引。
int[] a = new int[4];
int[] b = a;
两个变量a
和b
都将引用同一个数组 - 不涉及复制。
如果允许ints=chars
,则会有一个int[]
变量引用16位char
数组。这样的赋值如ints[0] = 0x12345678
是有效的,但结果应该是什么呢?
它不能按照你的期望工作,因为(在第一种情况下)语言会向你隐藏一些类型转换的细节。也就是说,当你将一个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;
您无法使用此方式进行分配,因为这是一种类型不匹配。类型int[]和char[]不兼容。
ByteBuffer.asCharBuffer
可以将 ByteBuffer 转换为char[]
,而ByteBuffer.asIntBuffer
则可以转换为int[]
。只要使用相同的底层缓冲区,它们就共享相同的内存。 - bestsss