构造子类对象的时候会先构造父类对象就是说你的子类对象在执行print之前已经执行了父类的f()

解决方案 »

  1.   


    问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
      

  2.   

    编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99
    难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?
    既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊
      

  3.   

    编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99
    难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?
    既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊
    F构造器里修改j改的就是子类对象继承来的j,否则一个对象难道能有两个j变量?
      

  4.   

    继承关系肯定不是执行中确定的,编译时或者之前肯定就有了。 子类本身没有J变量(它只是继承了父类的J变量),子类构造函数输出的那个j=99是就是父类的j变量!
      

  5.   

    import static TinkingJava.Print.*;
    public class Testextends extends F{
    public Testextends(){
     //print("j="+ j);
             print("j="+ super.j); 
             /* 变量j是父类的,子类并没有直接包含这个
             变量,而是包含了父类的引用,因此此处访问的是父类中的变量j*/
    }
    public static void main(String[] args){
    new Testextends();
    }
    }
    class F{
    protected int j; // 此处表示变量j可被子类访问
    public F(){
    print("j="+j);
    j=99;
    print("j="+j);
    }
    }实例化子类对象时,必须实例化其父类。而子类对象会包含一个指向父类对象的引用(super),
    此处变量j只有一个,子类有的只是访问这个变量的引用
    (简单的来说继承不是复制所有的变量和方法到自己的类里,而是包含一个引用)
      

  6.   

    你定义的j是protected,子类继承了都指向同一个引用,父类无参构造先执行,为j赋值。这不就是正确的流程吗
      

  7.   

    编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99
    难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?
    既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊LZ应该区分开继承时机与构造函数的时机。编译时确定了继承关系,因此加载子类时也会把父类加载进内存,把成员的值都设置成默认值(如果定义时未初始化的话),此时j的值为0,且并未执行构造函数。当new一个对象时,执行子类构造函数,先调用父类的构造函数,因此分别输出0和99,执行子类的构造函数,输出99.
      

  8.   

    应该是引用,如果是复制的话,继承和直接复写代码不是一样了吗?具体你看一下马士兵的视频吧,java基础那块,有关内存和引用的方面。我也是看他的视频看的
      

  9.   

    继承的类不是把父类的代码复制来了,只是引用父类成员?父类对象同时存在于内存?子类中如果不重写父类的属性和方法,都只是对父类的引用.只有当你重写了父类的属性和方法,才是属于子类所有(在内存中会重新分配一个空间),如果这时候要调用父类,就得用super.xxx去引用父类.如果你上面的程序.如果在子类重写一下父类j这个属性.如下:import static TinkingJava.Print.*;
    public class Testextends extends F{
        int j; //重写父类的j属性;
        public Testextends(){
            print("打印子类的 j="+j);
            print("打印父类的 j="+super.j);
        }
        public static void main(String[] args){
            new Testextends();
        }//输出j=99,这个值是在F的构造器里赋的,难道Java中是运行时继承?
    }
    class F{
        protected int j;
        public F(){
            print("j="+j);
            j=99;
            print("j="+j);
        }
    }输出子类的j是0;输出父类的j是99。说明子类不重写父类的属性和方法,只是对父类的属性和方法的一个引用。
      

  10.   

    看了上面的回复有点晕了,楼主在看《Thinking In Java》吧
    那你是否记得书上说的一个叫做子对象的概念,
    就是创建子类对象时会先创建父类子对象,您的 j 就在那个子对象里面,
    而整个子类对象中除父类子对象之外已经没有 j 了,所以你的 j 就是父类子对象中的 j
      

  11.   

    java的初始化顺序决定了子类执行之前,父类的构造函数已经执行了
      

  12.   

    加个static修饰下,用类直接打印下j
      

  13.   

    楼主可以用Javap看一下Testextends类的信息,编译子类时不会把父类的所有信息都保存到子类的class文件里,父类的构造方法是如何实现的要在运行时到父类的class文件里看才知道,普通方法也是一样,但这绝不表明java是运行时继承
      

  14.   

    编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99
    难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?
    既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊LZ应该区分开继承时机与构造函数的时机。编译时确定了继承关系,因此加载子类时也会把父类加载进内存,把成员的值都设置成默认值(如果定义时未初始化的话),此时j的值为0,且并未执行构造函数。当new一个对象时,执行子类构造函数,先调用父类的构造函数,因此分别输出0和99,执行子类的构造函数,输出99.加载子类之前,先加载父类,然后楼主不是不明白子父类构造函数的初始化过程,而是j这个成员不是子类自身的,而是继承父类来的,所以他使用的j实际上就是父类的j,所以打印出是99而不是0,楼主冷静下,赶脚走进思维死胡同了,还有,没基础,建议不要太一来think in java这本书,最好是有点基础后再去看,去网上档视频多看看,马士兵的,传智博客毕向东的视频都讲的很清楚