请问,下面这句话是什么意思呢?SuperA p = new SubB();(其中,SubB是SuperA的子类)1.等号定义成父类的类型,右边是子类的构造方法,那实例化出来的是子类还是父类啊?2.这句话应该也是从右边执行到左边的吧,那它的实际内部执行过程是怎样的?比如分配内存空间什么的。3.这句话执行的过程中会什么时候调用父类的构造函数啊,调用几次?4.这与左右边都是子类的情况有什么不同吗?
解决方案 »
- 到底要学什么?程序员的竞争点在哪?
- 关于毕业设计的问题,请大家帮忙
- 求助!!!用线程控制划随鼠标移动随即显示的线,报错了!
- 用eclipse定义一个变量static final COMM_ERR_NONE = 0x00000000; 为何编译器报错说final无法解析?
- JAVA按钮组件问题
- GUI开发工具
- classpath=D:\java;.;D:\tomcat\common\lib\servlet-api.jar 寻找classpath路径是不是从前到后找的啊?
- 一个非常有用的东东(不论菜鸟还是高手)
- 我是JAVA的初学者有一些特别简单的问题需要解决,分可是一点都不少,希望会的同志来领分。
- 哪里有JAVA好书(一个很简单的问题啊,各位高手,15分)
- 什么是单例模式 什么工厂模式 能否举例!~?~~面试该怎么回答?
- 关于方法前加 static 的精确定义
第一、编译时与运行时的区别。
第二、深刻理解面向对象的原理与思想,也就是类与对象的联系与区别。
第三、理解什么引用什么是数据。
在你能够搞清楚这三个问题之前恐怕你不那么好理解上面那句多态的语句到底是干了什么。
不过我现在绕过那三个问题吧答案告诉,至于为什么你搞清楚那三个问题就都明白了:
1、实例化出来的是子类而不是父类。
2、赋值操作符都是从右往左执行,这句话代表想内存申请空间存放对象并执行构造函数。
3、执行构造函数的第一句话就是执行父类的构造函数(也就是立即执行父类构造函数),如果父类不是java.lang.Object对象,那么就继续往上执行父类构造函数,直到java.lang.Object。
4、如果左边是父类引用,那么只能调用对象在父类中声明的方法和属性,如果左边是本类引用,则可以调用所有的方法和属性。
还有,new B() 内部操作有点复杂:先是为最顶端父类对象分配内存空间,
然后对这个对象进行默认初始化,
然后执行构造体代码。
然后逐步向下(向子类方向)进行同样的动作,直到执行完成B对象的构造方法。
建议楼主在看看think in java。
在这个以父类引用变量作为引用的子类对象不能在调用其子类有而父类中没有的方法了
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");
}
}
要理解什么是编译时什么是运行时,他们会有什么区别。
你们所说的多态其实都是编译时的概念,父类引用引用子类对象不存在什么转型,这种转型的说法只是一种被编译时的表面现象所误导而一厢情愿的猜测而已,不会有这种转型语句的存在,它是那种类型的对象在内存中就会一直是那种内存的对象,无论引用它的是哪个数据类型的引用。还有8楼的那位,你的理解是很多学习java的人都会出现的一个理解错误,按照你的那种说法,如果一个类继承了N层那么它实例化就会有N个对象,那么一个类的实例化至少会有两个对象,因为至少继承Object类。你不觉得这样太消耗内存了么,你认为java的实现者们会这么去实现java机制么?而且这种说法也存在明显的漏洞,如果父类是一个接口或者是抽象类呢,很明显它们不能被实例化,你要如何解释这种情况的存在;还有另外一个漏洞就是如果因为这样存在大量对象在内存中,岂不是更加增加了虚拟机对对象管理负担?如果把这个问题再细想下去,会发现不合理性和漏洞越来越多,你不会认为那些设计java语言的人都是白痴吧。总结一句,其实学习java很多特性在开始的时候确实很难理解,特别是多态的理解与继承的机制,因为这牵扯到很多底层的机制,这些机制是这些实现思想的基础,但是他们对一个初学者来说又比较难以掌握,所以我建议还是慢慢来,不要急着一口吃成胖子,学得多练得多了以后就慢慢理解了,这总要有个过程的。
没错,继承N层就会产生N的对象,你可以想一想,如果没有上层对象,或者说上层的实例变量没有初始化的话,就初始化子类对象,是会有问题的。
至于你说的Object必须存在的,我认为应该是这样的,Object对象占用的内存得看object的实例变量有多少有多大,这一点我还不确定,不过Object作为顶层类不会有多少实例变量的,还有你说的接口,接口是不用初始化父接口的。
也许用继承N层就实例化N个对象也许同样能够实现继承机制,但是java是不是这样做的还是需要继续学习,给自己一个确定的答案。再总结一句,有了猜想就要去验证,不能觉得猜想行得通他就是对的,正确的答案需要自己去寻找,就算我告诉你们答案你们也不理解,而且你们也不会同意我告诉你们的答案,而且我的答案也未必是正确的。
因此:孙子的对象空间里含有一个完整的爸爸对象(直接作为孙子对象中的一个部分),爸爸对象空间中含有一个完整的爸爸的爸爸(爷爷),爷爷的对象空间中含有一个完整的爷爷的爸爸(祖爷爷),......,一直下去,直到最后是Object老祖宗.
SuperA p = new SubB();
后面还可以接一句:
SubB p2=(SubB)p;这样是合法的。如果p是父类的话,怎么可以强制转型到子类呢?
因此,p一定是子类对象
Fruit obj = .....;
..
..
if(obj instanceof Apple) {
Apple apple = (Apple)obj;
}同在一个“家族”中的兄弟类型之间是不能赋值的,也不能强制类型转换,否则会报编译错误。比如:苹果绝对不可能是香焦,所以下面的代码编译不过:
Apple app = new Banana();同样的道理,想让不相干的类型之间进行转换也会报编译错误,比如一辆汽车绝对不可能是一个苹果,因此:
Apple app = new Car();
是会报编译错误的。
1. 实例化出来的是子类的对象
2. 内部执行过程:
1)新建一个父类的引用p,指向null;
2)调用java.lang.Object构造函数,调用Object的子类构造函数一次类推调用父类构造函数,调用子类构造函数,新建出一个子类的对象,对象初始化;
3)把子类的对象分配给引用p
3. 新建子类对象时调用父类构造函数,调用一次
4. 多态,具体用途很多,请参考教科书建议楼主找本书看看多态这一章,或者找个视频教程看看有关内容
那所有类在实例化的时候,最高父类Object都会生成一个Object的对象吧,但是Object对象已经在实例化一个类的时候生成了,已经存在了的话,那再实例化其他类时,是不是就不用再生成Object对象,而只是生成一个OBject对象的引用呢?
构造方法是这样的:public SubB(){
SubA() {};
}
子类构造方法里面父类的构造方法是编译器加上的,不需要自己写出来。所以调用子类构造方法时也会调用父类构造方法,且只调用一次,
调用完父类构造方法后再执行子类构造方法剩下的代码,这样就在内存中创建了一个子类对象,里面包含了一个父类对象;
然后用父类类型的引用p去持有这个创建出来的子类对象。通过引用p只能访问子类中从父类中继承的属性和方法,而子类中新增的属性和方法不能
通过引用p去访问,如果引用p是子类类型的,那么通过p可以访问所有子类中的属性和方法。
父类引用(superA)指向了他。如果你等号两边都是子类类型,则不会产生多态,
当然,你创建的仍然是一个对象,都是在堆中创建的对象
请问,我是否可以理解成,SuperA p = new SuperB();这句话只是实例化出了一个子类的对象p,而等号左边用了父类的引用来指向这个对象,是在限制这个子类对象只能访问从父类继承来的父类的成员,而它虽然是子类的对象,却不能再访问子类自身的成员啦?(可以这样理解,但是要注意对method和field区别对待,调用方法的时候会调用实际对象的类型中定义的方法,这就是多肽。而对于field访问,实际访问到的是从父类中继承下来的field)。并且,等号右边在实例化出子类的对象时,先调用了父类的构造方法来对子类继承过来的父类成员进行初始化,然后调用子类的构造函数来实例化子类自身成员(但是这句中由于子类…
这里就是父类的引用指向子类对象,new SuperB();就是为子类对象分配空间,调用子类的构造方法。注意对父类的构造方法的调用是通过在子类构造方法中使用super()语句直接调用的。你的理解还是有些问题。
说的是下面这个意思吗?子类对象只能调用继承来的父类的field,不能调用自身的field,而子类对象却可以连自身的method也可以调用?为什么method和field会不同呢?
建议找本基础的书看看,比如Core Java或者The java programming language,尤其是后者,很多概念问题和原理说的比较清楚,毕竟是设计java语言的人写的。
2.先执行SuperA p,仅仅是定义一个引用,在内存中占4byte。后执行new SubB(),创建出实例对象,分配相应的内存。最后将p指向了刚才创建的对象内存空间的首地址。
3.new SubB()时,在创建SubB类时会调用构造方法SubB(),而方法SubB()首先执行的操作时调用父类构造方法。调用一次。
4.创建对象的过程没什么区别,只是一个是父类引用指向对象,一个是子类引用指向对象。
这是多态的体现
new SubB();
Super p;
相当于于 SubB b = new SubB();
Super p = b;
上面的两句话只产生了一个对象b, 而p只是对b对象的一个引用。
所以,我们说一个“桔子”也是一个“水果”,所以水果 变量1 = new 桔子();是很合理的
A(){
System.out.println(this);
}
}public class B extends A {
B() {
System.out.println(this);
} public static void main(String[] args) {
A a =new B();
}
}你运行上段代码就可以知道答案了 打印的对象都是子类的 也就是说没有生成父类对象