解决方案 »
- 请问内部类有哪些作用
- 代码质量的疑问...
- 升★★了,放分庆祝,不过要先回答问题:JDK5.0比之前版本增加了些什么特性
- 大家帮我看看,关于Statement对象批量执行sql问题
- java 字符转化问题
- 持久层是什么?为什么要用到持久层。
- 请说说servlet,jsp与多线程的关系,菜鸟愿出高分喔!
- 那位高人给详细介绍一下java+SQLServer2000的配置整合过程!(高分求助,不够再加!!)
- 请教大家一个用socket传送图片的问题。。。。。
- JDBC连接数据库问题!!!
- htmlparse抓取网页里面的想要信息
- 如何让Eclipse自动 import java.util.stream.Stream;
创建子类不会创建父类对象吧!详情http://liujinpan75.iteye.com/blog/785136
---------------------------------------------------------
C实例化之前会先实例化F
那么
最后得到的C对象是包含了F对象?
还是
仅仅在C对象中包含了F对象的引用??如果是这种情况,是不是说:实例化一个子类对象,会把他所有的父类实例化并且保存下来,这样是不是会很浪费内存,毕竟好多类是有很多父类的。问题应该也可以等同于
当通过C对象调用没有被覆写的方法时,是直接调用了C对象中的方法?
还是通过引用调用了F对象的方法?
=====================================================================
首先,他们是继承关系!这里的继承和实例对象是两个维度,可以理解为代码的复用。所以子类实例化并不会实例化一个父类,而是会初始化父类,原因很简单他要复用父类的属性和方法。
第二,你所说的方法调用那么要从字节码class深入理解,你可以看一下生成的class文件,如果子类没有重写父类的方法,那么是不会包含父类的方法信息(就是说子类没有父类的方法代码),那么他是怎么调用的呢?很简单,字节码里边生成的时候有个所属父类索引信息,jvm执行的时候就是通过这些属性执行方法流程的,当然这个在编写java程序时不可见,楼主可以u看看jvm的深入理解便会明白很多。
非常谢谢,也就是说:
实例化C后,F并没有实例化,而仅仅是初始化,那么F就没有形成对象了,这样F的成员变量也就不会分配内存空间是吧??
我做了一个小实验:C,F都有Private int id; 那么C的对象是可以对C和F的id进行Set和Get的。
那么是不是说,在C实例化时,会把F的成员变量(比如id)给继承下来,即使名字一样,即使是private,也会进行处理保存??而F的方法则是放在代码区,在C对象需要调用时会按照索引按步骤查找,1。如果方法在C的方法区(额,存放代码的地方,不知诌的对不对)里找到就执行C的,2。如果在C的方法中没有找到就会自动寻找它的父类的方法区3。以此类推
谢谢,被网上一些资料误导了。
那么:
实例化C后,F并没有实例化,而仅仅是初始化,那么F就没有形成对象了,这样F的成员变量也就不会分配内存空间是吧??
我做了一个小实验:C,F都有Private int id; 那么C的对象是可以对C和F的id进行Set和Get的。
那么是不是说,
在C实例化时,会把F的成员变量(比如id)给继承下来,即使名字一样,即使是private,也会进行处理保存??
而F的方法则是放在代码区,在C对象需要调用时会按照索引按步骤查找,1。如果方法在C的方法区(额,存放代码的地方,不知诌的对不对)里找到就执行C的,2。如果在C的方法中没有找到就会自动寻找它的父类的方法区3。以此类推
public void setsuperId(int id){
super.id=id;
}
C:
public void setId(int id){
this.id=id;
}
public void setsuperId(int id){
super.id=id;
}
C:
public void setId(int id){
this.id=id;
}
-----------------------
---------------不好意思,写错了。---------------
//以下都在C类中写
//F
public void setsuperId(int id){
super.setId(id);
}
//C:
public void setId(int id){
this.id=id;
}
public void setsuperId(int id){
super.id=id;
}
C:
public void setId(int id){
this.id=id;
}如果父类的属性为private的,子类是无法通过super访问的吧!
public void setsuperId(int id){
super.id=id;
}
C:
public void setId(int id){
this.id=id;
}如果父类的属性为private的,子类是无法通过super访问的吧!
---------------不好意思,写错了。---------------
//以下都在C类中写
//F
public void setsuperId(int id){
super.setId(id);
}
//C:
public void setId(int id){
this.id=id;
}
*
* @author Administrator
*/
public class Test {
public static int Number=1;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Child ppa=new Child();
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/package extendtest;/**
*
* @author FathersFatherdministrator
*/
public class FathersFather {
private String i;
private static String s;
{
this.i="FathersFather";
System.out.println(Test.Number+++" "+i+"实例变量初始化");
}
static {
s="FathersFather";
System.out.println(Test.Number+++" "+s+"类变量初始化");
}
public FathersFather() {
System.out.println(Test.Number+++" "+"FathersFather构造器调用");
}
}/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/package extendtest;/**
*
* @author Administrator
*/
public class Father extends FathersFather{
private String i;
private static String s;
{
this.i="Father";
System.out.println(Test.Number+++" "+i+"实例变量初始化");
}
static {
s="Father";
System.out.println(Test.Number+++" "+s+"类变量初始化");
}
public Father() {
System.out.println(Test.Number+++" "+"Father构造器调用");
}
}/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/package extendtest;/**
*
* @author Administrator
*/
public class Child extends Father{
private String i;
private static String s;
{
this.i="Child";
System.out.println(Test.Number+++" "+i+"实例变量初始化");
}
static {
s="Child";
System.out.println(Test.Number+++" "+s+"类变量初始化");
} public Child() {
System.out.println(Test.Number+++" "+"Child构造器调用");
}
}
运行结果:
1 FathersFather类变量初始化
2 Father类变量初始化
3 Child类变量初始化
4 FathersFather实例变量初始化
5 FathersFather构造器调用
6 Father实例变量初始化
7 Father构造器调用
8 Child实例变量初始化
9 Child构造器调用=========================
结论:子类实例化必然伴随父类实例化,也就是说产生了父类的对象。但是父类对象的引用不可传递。也就是说只能通过super关键字从子类中访问父类的方法、字段。构造器等,当然,是在权限许可的情况下。但是无法将super赋值给新的引用变量。
谢谢,被网上一些资料误导了。
那么:
实例化C后,F并没有实例化,而仅仅是初始化,那么F就没有形成对象了,这样F的成员变量也就不会分配内存空间是吧??
我做了一个小实验:C,F都有Private int id; 那么C的对象是可以对C和F的id进行Set和Get的。
那么是不是说,
在C实例化时,会把F的成员变量(比如id)给继承下来,即使名字一样,即使是private,也会进行处理保存??
而F的方法则是放在代码区,在C对象需要调用时会按照索引按步骤查找,1。如果方法在C的方法区(额,存放代码的地方,不知诌的对不对)里找到就执行C的,2。如果在C的方法中没有找到就会自动寻找它的父类的方法区3。以此类推没错~你的理解是对的。
对象初始化的时候如果发现父类没有被初始化,就会先初始化父类,依次类推,但是如果父类是接口则不会去初始化父类
类的初始化是由类被主动使用导致的,new是一种,Class.forName()是一种,还有就是调用一个类的方法、属性或延迟的常量(就像下面的例子)public class InitialTest { public static void main(String[] args) {
Entity e = new Entity();
Good g = e.CONST;//此处注释就不会打印"Good initial!"
} static class Entity implements Bean { @Override
public void execute() {
// TODO Auto-generated method stub }
static{
System.out.println("Entity initial!");
}
} interface Bean { Good CONST = new Good(); void execute();
} static class Good { static {
System.out.println("Good initial!");
}
}
}
因为是继承,所以子类继承了父类除构造方法以外的所有方法,实例化谁就调用谁里面的方法,也就是new后面的那部分。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
1 实例化是指对象的创建,即生成类的对象;
2 初始化是指类的对应Class对象的创建以及静态成员、静态初始化块的执行;
3 父类对象不同于一般的对象,它并非单独在堆上创建,而是内嵌在子类对象之中,所以不可以从外部引用它;它的所有状态都能够保持,即使是不能够访问的private字段(没有公有get set方法)。所以,虽然它不是独立的对象,但是对于子类对象来说,它在功能上和独立对象没有什么区别。你可以把它当成独立的对象。当然,java的语言关系错综复杂,有时候可能会有微妙的限制,本人水平有限,也无法说清楚它的全部不同之处。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
1.父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?既有父类类初始化,也有实例化,二者是不同的概念。当你实例化一个子类的时候,JVM在解析的过程中加载、链接(类变量分配内存并初始化为默认值)、初始化(为类变量赋值,包括直接赋值语句,静态块赋值语句等),这是一个递归的过程,直到回到当前类。然后进行实例化,实例化也有一个类似的过程,首先调用父类的<init>方法,父类<init>方法最多包括三个部分,其中就有父类的构造函数,所以说我前面回答相当于实例化了父类。2.那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
肯定是有的,至于子类对象在堆中怎么组织,不同的JVM实现可以采取不同的方式。3.也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?回答同上面一样,你问的这些问题肯定也是JVM设计者们曾经考虑的问题。有的实现是把父类中的属性和方法按照顺序排列到子类中,子类如果重写了对应的方法,则将父类的覆盖,内部通过指针实现,这样在访问从父类继承的方法时,减少了一次指针访问,加快了速度。 父类实例化后不会立刻消亡,因为子类中可以使用super访问父类成员(相当于super引用父类,所以不会被垃圾回收),而且当我们使用super调用父类成员时,父类并没有再次调用构造函数进行初始化,这些可以作为证明(最后一句是个人推测而已,仅供参考)。
class Parent{
FooClass c;
Parent(){
this.c = new FooClass();
System.out.println("Parent\t" + c.hashCode());
}
}class Child extends Parent{
Child(){
System.out.println("Child\t" + this.c.hashCode());
}}public class MyTest {
public static void main(String[] args) {
Child c = new Child();
}
}
是引用
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。我做过一个小测试:C,F都有Private int id; 那么C的对象是可以对C和F的id进行Set和Get的。恩,谢谢。有人说是父类初始化,有人说是实例化,那么最终意思是不是:
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
1 实例化是指对象的创建,即生成类的对象;
2 初始化是指类的对应Class对象的创建以及静态成员、静态初始化块的执行;
3 父类对象不同于一般的对象,它并非单独在堆上创建,而是内嵌在子类对象之中,所以不可以从外部引用它;它的所有状态都能够保持,即使是不能够访问的private字段(没有公有get set方法)。所以,虽然它不是独立的对象,但是对于子类对象来说,它在功能上和独立对象没有什么区别。你可以把它当成独立的对象。当然,java的语言关系错综复杂,有时候可能会有微妙的限制,本人水平有限,也无法说清楚它的全部不同之处。
恩,谢谢。看了不少回复,推测(不知对不对):
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。
父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?
那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?希望有看过子类实例化在jvm中具体过程的人认真回答,谢谢。其实我感觉有点钻牛角尖了。
1.父类开辟了(至少开辟过)内存来存放父类的成员变量,并且进行了初始化赋值?既有父类类初始化,也有实例化,二者是不同的概念。当你实例化一个子类的时候,JVM在解析的过程中加载、链接(类变量分配内存并初始化为默认值)、初始化(为类变量赋值,包括直接赋值语句,静态块赋值语句等),这是一个递归的过程,直到回到当前类。然后进行实例化,实例化也有一个类似的过程,首先调用父类的<init>方法,父类<init>方法最多包括三个部分,其中就有父类的构造函数,所以说我前面回答相当于实例化了父类。2.那么子类对象最终在堆内形成后,子类对象内有没有(刚刚在堆内初始化的)父类的成员变量?
肯定是有的,至于子类对象在堆中怎么组织,不同的JVM实现可以采取不同的方式。3.也可以说,子类对象的形成是把父类成员变量复制进来一份然后让父类之前的成员变量随风而去?
还是说子类对象仅仅持有父类的引用,要用父类成员变量时再通过引用去找,父类对象相当于隐形的存在着?回答同上面一样,你问的这些问题肯定也是JVM设计者们曾经考虑的问题。有的实现是把父类中的属性和方法按照顺序排列到子类中,子类如果重写了对应的方法,则将父类的覆盖,内部通过指针实现,这样在访问从父类继承的方法时,减少了一次指针访问,加快了速度。 父类实例化后不会立刻消亡,因为子类中可以使用super访问父类成员(相当于super引用父类,所以不会被垃圾回收),而且当我们使用super调用父类成员时,父类并没有再次调用构造函数进行初始化,这些可以作为证明(最后一句是个人推测而已,仅供参考)。
恩,谢谢。看了不少回复,推测(不知对不对):
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。我也不敢说理解的对错!至少我感觉是没有错误的!对于多态:只有普通方法存在动态绑定!如果父类的方法是staic或者final的,用父类引用指向子类对象,调用static或者final方法,都是执行的父类中方法!还有对象的成员变量也没有动态绑定!
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。我也不敢说理解的对错!至少我感觉是没有错误的!对于多态:只有普通方法存在动态绑定!如果父类的方法是staic或者final的,用父类引用指向子类对象,调用static或者final方法,都是执行的父类中方法!还有对象的成员变量也没有动态绑定!
恩,谢谢。static方法属于类,所以父类引用可以调用static方法,这和子类父类没什么必然关系吧?final方法不能被override。
我的意思是说:父类引用指向子类对象,但子类对象中存在与父类相同的static方法或者final方法,此时父类引用调用的static或者final方法,都是调用父类方法,不会执行子类中的static或者final方法,就是没有像普通方法那样动态绑定!
我的意思是说:父类引用指向子类对象,但子类对象中存在与父类相同的static方法或者final方法,此时父类引用调用的static或者final方法,都是调用父类方法,不会执行子类中的static或者final方法,就是没有像普通方法那样动态绑定!
恩,是的。
你看下C++的实现#include <iostream>
using namespace std;
class A{
public:
A(){
this->value = 2;
printf("Parent %p %p\n ",this, &(this->value));
}public:
int value;
};
class B: public A{
public:
B(){
this->value = 0;
this->mChildValue = 1;
printf("Child %p %p\n\n", this, &(this->mChildValue));
}
private:
int mChildValue;
};int main(int argc, char *argv[])
{
B b;
return 0;
}Parent 0x7fff5fbffc88 0x7fff5fbffc88
Child 0x7fff5fbffc88 0x7fff5fbffc8c
0x7fff5fbffc88 这个是父子进程的内存首地址,2者是一样的,构造的时候先构造了父类,接着在后面的内存区上构建子类 对应的java对象这个构建在堆上 0x7fff5fbffc8c 这个由于子类自己加了一个4字节的成员变量,可以看到子类和父类的field的偏移量就是这个4字节的对象
对于子类对象
1.从外部来看父类对象此时已经融入到了子类当中,不论是通过引用的方式还是把父类对象包装好放到子类当中,总之此时它们是一个整体。这个融合包含两个方面:从成员变量的角度,看不管是父类对象的什么成员变量(包括private的),都会包含在里面;从方法的角度看,当方法有覆写时,可能在子类对象中还存在着父类的方法,只是在通过子类对象访问时不会找父类的方法,而去找子类的方法(或许这里面有个寻找方法的过程),当然也可能父类方法直接就被覆盖了。
总之,从外部看它们是一个整体,子类父类的成员变量简单叠加(不论是否重名),子类父类的方法不知是简单叠加还是简单覆盖
2.从内部看,子类对象可以通过super访问父类的成员变量(不包括private)以及方法,(看起来更像是用引用来实现了父类成员变量的包含)。我更趋向于的答案:子类实例化之前父类进行了初始化,最后子类对象中包含了一些引用(这些引用可能编译时是自动添加上的)指向了父类的成员变量以及方法。所以看起来子类对象拥有父类的private属性,而多态的实现我猜想:子类对象会先寻找自己的方法看有没有,没有就会去父类的方法区寻找(就近寻找)。最后,子类实例化前父类仅仅初始化,还没有形成对象(我对对象研究不多,可能形成一个对象会包含很多信息),因此在子类的实例化后不会存在两个或更多对象,它就是一个对象,只是实例化过程复杂了一些。=========================================看前面测试程序结果:
子类实例化前先实例化父类;
最后整个对象包括:在父类中声明的所有实例变量、在子类中声明的所有实例变量。这样,未被覆盖的变量只有一份;覆盖的变量包括子类和父类中的各自一份。