日期:2014-05-20  浏览次数:20643 次

这是在实例化父类还是子类?
请问,下面这句话是什么意思呢?

SuperA p = new SubB();

(其中,SubB是SuperA的子类)

1.等号定义成父类的类型,右边是子类的构造方法,那实例化出来的是子类还是父类啊?

2.这句话应该也是从右边执行到左边的吧,那它的实际内部执行过程是怎样的?比如分配内存空间什么的。

3.这句话执行的过程中会什么时候调用父类的构造函数啊,调用几次?

4.这与左右边都是子类的情况有什么不同吗?

------解决方案--------------------
如果你要搞清楚这个问题首先你要搞清楚三个个问题:
第一、编译时与运行时的区别。
第二、深刻理解面向对象的原理与思想,也就是类与对象的联系与区别。
第三、理解什么引用什么是数据。
在你能够搞清楚这三个问题之前恐怕你不那么好理解上面那句多态的语句到底是干了什么。
不过我现在绕过那三个问题吧答案告诉,至于为什么你搞清楚那三个问题就都明白了:
1、实例化出来的是子类而不是父类。
2、赋值操作符都是从右往左执行,这句话代表想内存申请空间存放对象并执行构造函数。
3、执行构造函数的第一句话就是执行父类的构造函数(也就是立即执行父类构造函数),如果父类不是java.lang.Object对象,那么就继续往上执行父类构造函数,直到java.lang.Object。
4、如果左边是父类引用,那么只能调用对象在父类中声明的方法和属性,如果左边是本类引用,则可以调用所有的方法和属性。
------解决方案--------------------
多态.. 父类引用指向子类对象. 这句话记住..都懂了.
------解决方案--------------------
这么作的 会使子类变窄 就是 子类中有的方法而父类中没有的方法 
在这个以父类引用变量作为引用的子类对象不能在调用其子类有而父类中没有的方法了


public class A {
public static void main(String[] args){
C c=new B();
c.abc();
c.abcd();//会报错找不到此方法

}
}
class B extends C{
void abc(){
System.out.println("d");
}
void abcd(){
System.out.println("dsfdsf");
}
}
class C{
void abc(){
System.out.println("SDFSDFSD");

}

}
------解决方案--------------------
这就是面向对象的多态性之一。在C++中是父类的对象调用子类的方法,在java中等号左边实际上就相当于一个指针,其实是在栈中分配的一个名称,它储存对象的地址,储存拿过对象的地址呢?也就是储存new出来的对象,即等号右边的。只要是new出的东西,一定是在堆里分配的内存
------解决方案--------------------
SuperA p = new SubB(); 是从右到左执行的。首先分析new SubB(),执行new SubB()是调用子类SubB的默认构造方法,即public SubB(){},事实上子类的
构造方法是这样的:public SubB(){ 
SubA() {};
}
子类构造方法里面父类的构造方法是编译器加上的,不需要自己写出来。所以调用子类构造方法时也会调用父类构造方法,且只调用一次,
调用完父类构造方法后再执行子类构造方法剩下的代码,这样就在内存中创建了一个子类对象,里面包含了一个父类对象;
然后用父类类型的引用p去持有这个创建出来的子类对象。通过引用p只能访问子类中从父类中继承的属性和方法,而子类中新增的属性和方法不能
通过引用p去访问,如果引用p是子类类型的,那么通过p可以访问所有子类中的属性和方法。


------解决方案--------------------
是父类引用指向子类对象,会产生多态,其实就创建了一个对象,subperB的对象
父类引用(superA)指向了他。如果你等号两边都是子类类型,则不会产生多态,
当然,你创建的仍然是一个对象,都是在堆中创建的对象
------解决方案--------------------
探讨
没错,继承N层就会产生N的对象,你可以想一想,如果没有上层对象,或者说上层的实例变量没有初始化的话,就初始化子类对象,是会有问题的。
至于你说的Object必须存在的,我认为应该是这样的,Object对象占用的内存得看object的实例变量有多少有多大,这一点我还不确定,不过Object作为顶层类不会有多少实例变量的,还有你说的接口,接口是不用初始化父接口的。

------解决方案--------------------
[Quote=引用:]
请问,我是否可以理解成,SuperA p = new SuperB();

这句话只是实例化出了一个子类的对象p,而等号左边用了父类的引用来指向这个对象,是在限制这个子类对象只能访问从父类继承来的父类的成员,而它虽然是子类的对象,却不能再访问子类自身的成员啦?(可以这样理解,但是要注意对method和field区别对待,调用方法的时候会调用实际对象的类型中定义的方法,这就是多肽。而对于field访问,实际访问到的是从父类中继承下来的field)。

并且,等号右边在实例化出子类的对象时,先调用了父类的构造方法来对子类继承过来的父类成员进行初始化,然后调用子类的构造函数来实例化子类自身成员(但是这句中由于子类…
这里就是父类的引用指向子类对象,new SuperB();就是为子类对象分配空间,调用子类的构造方法。注意对父类的构造方法的调用是通过在子类构造方法中使用super()语句直接调用的。你的理解还是有些问题。

------解决方案--------------------
把引用和对象区分开就没那么多问题了.
建议找本基础的书看看,比如Core Java或者The java programming language,尤其是后者,很多概念问题和原理说的比较清楚,毕竟是设计java语言的人写的。
------解决方案--------------------
个人认为是子类的对象 只是具有的子类自己的属性和方法暂时的不可见 但是当再转型回子类时就又都可见了 如果是父类的对象则是根本没有这些属性以及方法 没有与不可见是两种概念
------解决方案--------------------
List list = new ArrayList();