无法从char[]转换为int[]。

4
我可以将char赋值给int,具体操作如下:
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?

基本类型的扩宽转换不会丢失有关数字值整体大小的信息。这是一种针对基本类型的特殊情况。请参考 @erickson 的回答。 - calebds
你可以使用 ByteBuffer 来实现类似的功能,ByteBuffer.asCharBuffer 可以将 ByteBuffer 转换为 char[],而 ByteBuffer.asIntBuffer 则可以转换为 int[]。只要使用相同的底层缓冲区,它们就共享相同的内存。 - bestsss
6个回答

4

charint的类型提升是基本类型的一种特殊规定。

关于数组,Java语言规范如下所述:

如果一个数组变量v具有类型A[],其中A是一个引用类型,那么 v可以保存对任何数组类型B[]的实例的引用,前提是 B可以分配给A。这可能会导致运行时异常发生在之后的赋值中;请参见§10.10进行讨论。

这只适用于"A是引用类型"的情况。即使char可以分配给int,但由于它不适用于基本类型,因此该规则不适用。

因此,在没有为分配不兼容类型提供任何特殊规定的情况下,分配将失败。

如果允许这样做,您将引入可能会导致原始数组存储(就像您当前使用引用类型数组一样)引发ArrayStoreException的可能性:

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

这是因为ints是一个别名,指向无法容纳32位值的char[]。我不确定为什么这对于引用类型是可以接受的,而对于基本类型却不行,但这可能与基本类型所需的所有特殊处理有关。

谢谢Erikson。我明白了你的意思。所以,这是为了避免像将assign和char[]对象分配给int引用时出现的ArrayStoreException异常。 - ironwood

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,那么JVM必须截断值使其适应,否则就会抛出异常。
  • 如果它截断了该值,则assert语句将失败。这是如此反直觉以至于它根本是有问题的。

  • 如果它抛出异常,则我们突然间就有了一整类新的错误,而这些错误(根据JLS规则)目前在编译时被检测到。

Java避免了这种不良影响的方法是说你不能将char[]赋给int[]


2

除了char[]转换为int[]的概念在语言规范中不存在之外,我不确定我能为您提供更多内容。

在低级别上,这可能与对数组本身进行迭代有关。如果我将char[]视为int[]并在内存中索引它,则在低级别下无法正常工作。一个4字节的步骤(像int[]一样处理)实际上会在char[]中移动2个索引。


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

两个变量ab都将引用同一个数组 - 不涉及复制。

如果允许ints=chars,则会有一个int[]变量引用16位char数组。这样的赋值如ints[0] = 0x12345678是有效的,但结果应该是什么呢?


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;

0

您无法使用此方式进行分配,因为这是一种类型不匹配。类型int[]和char[]不兼容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接