有人可以解释为什么下面代码中的最后一项作业无效
类ScjpTest扩展BounceObject实现了Bouncable {
static int ac = 5;
static char ab = 'd';
static int[] a = new int[]{1,2,3};
static int[] b = new int[]{1,2,3};
static char[] c = new char[]{'a','b'};
public static void main(String[] args){
a = b;
b = a;
ac = ab; //This is accepted
a = c; //This is rejected
}
}
编译器抱怨以下错误
ScjpTest.java:10: incompatible types
found : char[]
required: int[]
a = c;
^
1 error
以下也被接受
class Animal{}
class Horse extends Animal{]
Animal[] animals = new Animal[2];
Horse[] horses = new Horses[2];
animals = horses;
为什么我不能将char数组赋给int数组?
答案 0 :(得分:8)
因为语言规范禁止它。它在运行时工作以将String []视为Object [],因为它们在内存中具有相同的表示。但是char []和int []有不同的内存表示,如果int []上的每个操作都必须检查它是否真的是伪装的char [],那就慢得令人无法接受。
引用类型的数组必须对赋值执行运行时检查,以便知道是否抛出ArrayStoreException,但至少从它们读取与元素类型无关。
答案 1 :(得分:4)
数组本身就是一个类型,并且转换的工作方式与原语不同。因此,您必须循环所有元素并将它们分配给另一个数组的相应元素。
答案 2 :(得分:1)
您可以将char变量分配给int变量,因为编译器应用扩展转换。基础是int大于char,因此转换中不存在丢失信息的可能性。如果您尝试将int分配给您的char,您会注意到编译器拒绝您的代码,直到您进入特定的类型转换。这是因为缩小转换几乎总是涉及数据丢失,因此编译器要求程序员明确指出这是你打算做的事情。
同样的原则适用于对象。允许扩大转换是隐含的,缩小转换需要进行类型转换。请注意,任何时候都不能通过超类/子类层次结构转换彼此不相关的对象。
Number n = null;
Integer i = null;
n = i ; // Allowed without casting, Number is superclass of Integer
i = n; // Compiler error, Integer is sub-class of Number
i= (Integer)n; // Allowed due to the type-cast
在上面的示例中,Number是Integer的超类。在没有类型转换的情况下,允许将Integer实例分配给Number实例,因为这是一个“扩展”转换。将Number实例分配给Integer实例需要特定的转换,因为这是一个缩小的转换(Number可能代表Float或其他一些子类)。这些规则延续到数组。因此,您可以执行以下操作:
Number[] numArr = null;
Integer[] intArr = null;
numArr = intArr;
intArr = numArr; //Compile error
intArr = (Integer[]) numArr;
对于原始数组,在数组元素上有 no 扩展转换,即使在你认为它有意义的情况下(即char到int,或字节到char等)。虽然这看起来似乎没有意义,但如果你看一下类似的对象,它就会变得更加清晰:
Double[] doubleArr = null;
Integer[] intArr = null;
doubleArr = intArr ; // Compile error, Double,Integer are sibling classes
doubleArr = (Double[]) intArr; // Compile error, same reason
intArr = doubleArr; // Compile error, same reason
intArr = (Integer[]) doubleArr; // Compile error, same reason
你不能将Double转换为整数,反之亦然,从编译器的角度来看,它们是完全不同的类(例如,与String和Float不同)。