Manager[0]此时怎么就不是Manager对象了呢!我明明改变的是staff[0] = new Employee(); 疑惑就在这里!
你改变了staff[0] = new Employee(); 这个,此时Manager[0]中也存的是Employee对象,而不是Manager对象。用staff[0] = new Manager(); 就好了。
也不是你说的这个样子吧!我今天特意把代码写出来看了一下:我是这样理解的,不知道对不对 staff[0] = new Employee(); 这里的staff[0]原来装的是Manager[0]的引用,现在你要把Employee对象的引用赋值给Manager对象的引用会出现向下类型转换错误!也就是装staff[0](栈内存)的地方不适合装Employee对象的引用,所以这个代码运行时会报错... 不晓得我的理解正步正确,希望各位能给指正下..3Q
从楼主提出的问题看,楼主要注意的知识点很多: 1、最直接的一个问题:class Point { int x, y; } class ColoredPoint extends Point { int color; } class Test { public static void main(String[] args) { ColoredPoint[] cpa = new ColoredPoint[10]; Point[] pa = cpa; System.out.println(pa[1] == null); try { pa[0] = new Point(); } catch (ArrayStoreException e) { System.out.println(e); } } } 你看是不是你的问题? 如果是你的老师出的题目,你看一下Java Language Specification 10.10 Array Store Exception2、现在抛开对象数组,仅仅看: Manager m = new Manager(); Employee e =new Employee(); e= m; e.setBound(); 你需要知道“e.setBound();”语句为什么编译错误。
3、 楼主在2楼说:“staff[0] = new Employee(); 指向的是另外一块内存啊~!” 谁指向什么内存?谁与谁指向的是不同内存?4.真正的问题是: static void foo(){ Manager[] managers = new Manager[10]; Employee[] staff = managers; staff[0] = new Manager(); staff[0].setBound();//编译错误 }解答: 1、staff是Employee[]类型变量,它的元素都是Employee类型变量。 2、staff = managers后,staff的元素如staff[0]仅仅能够被赋与managers的类型的值即Manager对象。(At compile time, an assignment to an element of pa is checked to make sure that the value assigned is a Point. But since pa holds a reference to an array of ColoredPoint, the assignment is valid only if the type of the value assigned at run-time is, more specifically, a ColoredPoint. ) 3、但是,staff[0]虽然只能赋予Manager对象的引用,它还是一个Employee类型的变量——丧失子类特性。
static void foo(){ Manager[] managers = new Manager[10]; Employee[] staff = managers; staff[0] = new Employee(); staff[0].setBound();//编译不会有错误,运行时错误. } 其实开始我没有把代码写出来,所以才会有那么乱七八糟的问题.真正的问题在于 staff[0] = new Employee(); //父类引用给子类引用,向下类型转换失败. 其实就是这条规则,父类有的子类一定有,子类有的父类不一定都有.现在你要把父类引用给子类,肯定会出问题.
出错的代码应该是staff[0] = new Employee();
Manager[] managers = new Manager[10];
上面这句话执行完后会在堆上开辟十个存储空间的内存,然后由managers指向这个数组的首地址;
Employee[] staff = managers;
上面这句话执行完后,把数组的首地址赋给了staff变量,也就是说staff和managers指向的是相同的地址staff[0] = new Employee(); 所以运行的时候就会出错,因为staff指向的是子类new Managers[10]时开辟的空间,他的大小只能装子类变量;
而不能装父类new出的实例。r如果把staff[0]=new Manager();就没问题了,关键是会画内存就好理解了
你说的其它的我都明白.我在疑惑的就是这一句.
是不是对象数组在堆内存中分配空间后就不会在动了.
打个比方:
staff[0]原来指向的是Manager[0]
现在staff[0] = new Employee();这个内存是不是强占Manager[0]的内存空间,也就是覆盖调Manager[0],现在这块地方就是装Employee[0].如果不是这样子这个问题就解释不通啊!
如果要使用子类特有的方法,就不要这么声明.
或者进行强制类型转换之后再调用.
学java不用整天关注这些内存的问题.
你这里却要让父类的引用来调用父类没定义的方法,编译器就不让你通过,因为它找不到Manager中定义的setBound()方法.
还没到运行阶段呢,内存的问题就先别分析了
疑惑就在这里!
staff[0] = new Employee();
这里的staff[0]原来装的是Manager[0]的引用,现在你要把Employee对象的引用赋值给Manager对象的引用会出现向下类型转换错误!也就是装staff[0](栈内存)的地方不适合装Employee对象的引用,所以这个代码运行时会报错...
不晓得我的理解正步正确,希望各位能给指正下..3Q
1、最直接的一个问题:class Point { int x, y; }
class ColoredPoint extends Point { int color; }
class Test {
public static void main(String[] args) {
ColoredPoint[] cpa = new ColoredPoint[10];
Point[] pa = cpa;
System.out.println(pa[1] == null);
try {
pa[0] = new Point();
} catch (ArrayStoreException e) {
System.out.println(e);
}
}
}
你看是不是你的问题?
如果是你的老师出的题目,你看一下Java Language Specification 10.10 Array Store Exception2、现在抛开对象数组,仅仅看:
Manager m = new Manager();
Employee e =new Employee();
e= m;
e.setBound(); 你需要知道“e.setBound();”语句为什么编译错误。
楼主在2楼说:“staff[0] = new Employee(); 指向的是另外一块内存啊~!”
谁指向什么内存?谁与谁指向的是不同内存?4.真正的问题是:
static void foo(){
Manager[] managers = new Manager[10];
Employee[] staff = managers;
staff[0] = new Manager();
staff[0].setBound();//编译错误
}解答:
1、staff是Employee[]类型变量,它的元素都是Employee类型变量。
2、staff = managers后,staff的元素如staff[0]仅仅能够被赋与managers的类型的值即Manager对象。(At compile time, an assignment to an element of pa is checked to make sure that the value assigned is a Point. But since pa holds a reference to an array of ColoredPoint, the assignment is valid only if the type of the value assigned at run-time is, more specifically, a ColoredPoint. )
3、但是,staff[0]虽然只能赋予Manager对象的引用,它还是一个Employee类型的变量——丧失子类特性。
Manager[] managers = new Manager[10];
Employee[] staff = managers;
staff[0] = new Employee();
staff[0].setBound();//编译不会有错误,运行时错误.
}
其实开始我没有把代码写出来,所以才会有那么乱七八糟的问题.真正的问题在于
staff[0] = new Employee(); //父类引用给子类引用,向下类型转换失败.
其实就是这条规则,父类有的子类一定有,子类有的父类不一定都有.现在你要把父类引用给子类,肯定会出问题.