Java中的继承是运行时继承吗?看下面代码

程猿薇茑
优质创作者: Java技术领域
领域专家: 后端开发技术领域
2014-04-14 06:45:19

import static TinkingJava.Print.*;
public class Testextends extends F{
public Testextends(){
print("j="+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啊!
...全文
584 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
lliiqiang 2014-04-29
  • 打赏
  • 举报
回复
先执行父类构造方法,此时j已经是99
xuebichongkafei 2014-04-27
  • 打赏
  • 举报
回复
引用 15 楼 zzwab99 的回复:
[quote=引用 8 楼 zpcandzhj 的回复:] [quote=引用 5 楼 waynexuan 的回复:] [quote=引用 4 楼 zpcandzhj 的回复:] 问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99 难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?[/quote] 既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊[/quote] LZ应该区分开继承时机与构造函数的时机。编译时确定了继承关系,因此加载子类时也会把父类加载进内存,把成员的值都设置成默认值(如果定义时未初始化的话),此时j的值为0,且并未执行构造函数。当new一个对象时,执行子类构造函数,先调用父类的构造函数,因此分别输出0和99,执行子类的构造函数,输出99.[/quote]加载子类之前,先加载父类,然后楼主不是不明白子父类构造函数的初始化过程,而是j这个成员不是子类自身的,而是继承父类来的,所以他使用的j实际上就是父类的j,所以打印出是99而不是0,楼主冷静下,赶脚走进思维死胡同了,还有,没基础,建议不要太一来think in java这本书,最好是有点基础后再去看,去网上档视频多看看,马士兵的,传智博客毕向东的视频都讲的很清楚
WayneXuan 2014-04-27
  • 打赏
  • 举报
回复
楼主可以用Javap看一下Testextends类的信息,编译子类时不会把父类的所有信息都保存到子类的class文件里,父类的构造方法是如何实现的要在运行时到父类的class文件里看才知道,普通方法也是一样,但这绝不表明java是运行时继承
巫巫巫 2014-04-16
  • 打赏
  • 举报
回复
引用 12 楼 wangliyunzero 的回复:


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只有一个,子类有的只是访问这个变量的引用 (简单的来说继承不是复制所有的变量和方法到自己的类里,而是包含一个引用)
++
巫巫巫 2014-04-16
  • 打赏
  • 举报
回复
java的初始化顺序决定了子类执行之前,父类的构造函数已经执行了
ququ9696 2014-04-16
  • 打赏
  • 举报
回复
加个static修饰下,用类直接打印下j
yueyuexiong 2014-04-15
  • 打赏
  • 举报
回复
你定义的j是protected,子类继承了都指向同一个引用,父类无参构造先执行,为j赋值。这不就是正确的流程吗
「已注销」 2014-04-15
  • 打赏
  • 举报
回复


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只有一个,子类有的只是访问这个变量的引用 (简单的来说继承不是复制所有的变量和方法到自己的类里,而是包含一个引用)
gansigandou 2014-04-15
  • 打赏
  • 举报
回复
继承关系肯定不是执行中确定的,编译时或者之前肯定就有了。 子类本身没有J变量(它只是继承了父类的J变量),子类构造函数输出的那个j=99是就是父类的j变量!
放码过来吧 2014-04-15
  • 打赏
  • 举报
回复
肯定是先执行父类的构造函数,子类在继承父类的值,子类也可以覆写父类的函数
張Eason- 2014-04-15
  • 打赏
  • 举报
回复
在调用子类构造器的时候会先调用父类的构造器
WayneXuan 2014-04-15
  • 打赏
  • 举报
回复
引用 8 楼 zpcandzhj 的回复:
[quote=引用 5 楼 waynexuan 的回复:] [quote=引用 4 楼 zpcandzhj 的回复:] 问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99 难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?[/quote] 既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊[/quote] F构造器里修改j改的就是子类对象继承来的j,否则一个对象难道能有两个j变量?
sleeplacker 2014-04-15
  • 打赏
  • 举报
回复
看了上面的回复有点晕了,楼主在看《Thinking In Java》吧 那你是否记得书上说的一个叫做子对象的概念, 就是创建子类对象时会先创建父类子对象,您的 j 就在那个子对象里面, 而整个子类对象中除父类子对象之外已经没有 j 了,所以你的 j 就是父类子对象中的 j
momoyssy 2014-04-15
  • 打赏
  • 举报
回复
引用 14 楼 zpcandzhj 的回复:
[quote=引用 13 楼 u011201384 的回复:] 你定义的j是protected,子类继承了都指向同一个引用,父类无参构造先执行,为j赋值。这不就是正确的流程吗
继承的类不是把父类的代码复制来了,只是引用父类成员?父类对象同时存在于内存?[/quote]子类中如果不重写父类的属性和方法,都只是对父类的引用.只有当你重写了父类的属性和方法,才是属于子类所有(在内存中会重新分配一个空间),如果这时候要调用父类,就得用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。说明子类不重写父类的属性和方法,只是对父类的属性和方法的一个引用。
yueyuexiong 2014-04-15
  • 打赏
  • 举报
回复
应该是引用,如果是复制的话,继承和直接复写代码不是一样了吗?具体你看一下马士兵的视频吧,java基础那块,有关内存和引用的方面。我也是看他的视频看的
zzwab99 2014-04-15
  • 打赏
  • 举报
回复
引用 8 楼 zpcandzhj 的回复:
[quote=引用 5 楼 waynexuan 的回复:] [quote=引用 4 楼 zpcandzhj 的回复:] 问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99 难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?[/quote] 既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊[/quote] LZ应该区分开继承时机与构造函数的时机。编译时确定了继承关系,因此加载子类时也会把父类加载进内存,把成员的值都设置成默认值(如果定义时未初始化的话),此时j的值为0,且并未执行构造函数。当new一个对象时,执行子类构造函数,先调用父类的构造函数,因此分别输出0和99,执行子类的构造函数,输出99.
程猿薇茑 2014-04-15
  • 打赏
  • 举报
回复
引用 13 楼 u011201384 的回复:
你定义的j是protected,子类继承了都指向同一个引用,父类无参构造先执行,为j赋值。这不就是正确的流程吗
继承的类不是把父类的代码复制来了,只是引用父类成员?父类对象同时存在于内存?
程猿薇茑 2014-04-14
  • 打赏
  • 举报
回复
引用 5 楼 waynexuan 的回复:
[quote=引用 4 楼 zpcandzhj 的回复:] 问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
编译时就确定了继承关系,子类有了j变量,但是运行父类的构造方法后j的值成了99 难道现在把父类改成98,你还想让子类输出99?99这个数是哪儿蹦出来的?[/quote] 既然是编译时就确定了继承关系,子类有了j变量,在F构造器里修改j之后怎么还影响子类的j,子类的j应该是默认值0啊
Sauron1 2014-04-14
  • 打赏
  • 举报
回复
先执行父类的构造函数,子类再继承父类,父类的构造函数构造完时j已经变为99,所以子类也继续父类的这个j,为99
alan19931103 2014-04-14
  • 打赏
  • 举报
回复
引用 4 楼 zpcandzhj 的回复:
问题不在这,我知道先执行了父类构造函数不错,但是子类有自己的j啊,父类里改变j影响子类继承的j啊?问题是继承这个动作是发生在调用父类构造器之前还是之后?
子类的j继承自父类,在内存里是同一个
加载更多回复(5)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧