Java基础知识疑惑

東北扫地僧 2012-05-08 06:28:59
class Person {

public Person() {
this.print();
}
public void print(){}

}

class Student extends Person {
int x=20;
public Student(int x) {
this.x = x;
}
public void print(){
System.out.println(Student.class);
System.out.println("x="+x);
}
}

public class Test1 {
public static void main(String[] args) {
Person p = new Student(200);
}
}



请各位高手帮忙详细分析一下,为什么这段代码的输出会是0呢?

我跟断点也没有理解,哪位高手能帮忙详细分析一下,不胜感激。
...全文
489 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
ylp198296 2012-05-14
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]
这涉及到了类实例化过程中对实例变量进行初始化的问题
LZ代码中通过new关键字来实例化类,因此虚拟机会调用对象的"实例初始化方法"来给对象的实例变量初始化为正确的值.
这个"实例初始化方法"被称为"<init>" 方法,对于lz的这种情况<init>方法包含了三部分:
1.对超类的<init>()方法的调用
2.任意实例变量初始化方法的字节码
3.实现了对应构造方法的方法体的字节码

……
[/Quote]22楼的解答很详细,学习了,说到了点上!!
東北扫地僧 2012-05-11
  • 打赏
  • 举报
回复
感谢(logic_well)、(飞翔猫咪号)、(benben822098)、(Frisky)几位大神的指导,Java应有你们而精彩。
Mourinho 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
这个题到底基础不基础我还真不敢断言
这里边都是关于JVM执行过程类加载器工作原理的东西 敢问哪本java基础书里有介绍过这方面的知识?
[/Quote]

think in java里就有
比这个复杂多了

打印0是因为父类的构造函数还没有结束,Student类没有初始化,x为默认值0
logic_well 2012-05-09
  • 打赏
  • 举报
回复
多谢上边这位热心的仁兄 其实我是一直看不到满意的答案才一直在这里抬杠的 昨天看到这个贴后关于加载原理的东西我又多查了点 心里已经有数了

JVM碰到一个新类的时候首先会对它进行加载和连接
其中连接分三步,第一步是验证class是否符合规格,第二步是准备,就是为类变量分配内存同时设置默认初始值,第三步就是解释.

你会发现在连接这步已经完成了对类变量分配内存并设置默认初始值.

然后只有在对此类进行主动使用的时候开始对其进行初始化,以下的情况都属于主动使用:
以下是视为主动使用一个类,其他情况均视为被动使用!
1):new一个类的实例对象(声明不叫主动使用)
2):直接调用类的静态方法。
3):对类的静态变量进行读取、赋值操作的
4):反射调用一个类的方法。
5):初始化一个类的子类的时候,父类也相当于被程序主动调用了(如果调用子类的静态变量是从父类继承过来并没有复写的,那么也就相当于只用到了父类的东东,和子类无关,所以这个时候子类不需要进行类初始化)。
6):直接运行一个main函数入口的类。

假如该类的直接父类还没有被初始化,则先初始化直接父类.
而初始化的一个很关键的地方是:先执行静态代码块,然后再执行变量.这个顺序是违背了面对对象原则的.这才是楼主困惑的根源.
将成员变量的声明如果改为静态(static int x=20),就会得到预期的结果:x=20.
logic_well 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]
Person p = new Student(200);
这是个典型的多态 父类对象指向子类引用
其实多态很简单 父类指向子类引用的对象 除了非静态方法是用的子类的其余的所有的都是用的父类的
虽然你传的是200 但是父类的初始化是0 所以输出的也就是0咯
[/Quote]

父类初始化什么是0?父类里边有x?下边那个学习了,你这样学东西大丈夫?
BadPattern 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 的回复:]

引用 20 楼 的回复:
引用 7 楼 的回复:
这个题到底基础不基础我还真不敢断言
这里边都是关于JVM执行过程类加载器工作原理的东西 敢问哪本java基础书里有介绍过这方面的知识?


think in java里就有
比这个复杂多了

打印0是因为父类的构造函数还没有结束,Student类没有初始化,x为默认值0

父类构造函数和Student类初始化有什么什么关系……
[/Quote]
必须调用完<init>()方法student类才算初始化完,<init>()方法是编译器根据每个构造器生成的,但它不并仅仅包括构造器的字节码,见我22楼的回复
logic_well 2012-05-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 的回复:]
引用 7 楼 的回复:
这个题到底基础不基础我还真不敢断言
这里边都是关于JVM执行过程类加载器工作原理的东西 敢问哪本java基础书里有介绍过这方面的知识?


think in java里就有
比这个复杂多了

打印0是因为父类的构造函数还没有结束,Student类没有初始化,x为默认值0
[/Quote]
父类构造函数和Student类初始化有什么什么关系?你的意思是必须调用完Student的构造函数Stuedent类才算被初始化?原来初始化的意思是调用构造函数?
BadPattern 2012-05-09
  • 打赏
  • 举报
回复
这涉及到了类实例化过程中对实例变量进行初始化的问题
LZ代码中通过new关键字来实例化类,因此虚拟机会调用对象的"实例初始化方法"来给对象的实例变量初始化为正确的值.
这个"实例初始化方法"被称为"<init>" 方法,对于lz的这种情况<init>方法包含了三部分:
1.对超类的<init>()方法的调用
2.任意实例变量初始化方法的字节码
3.实现了对应构造方法的方法体的字节码

一步步来分析:
当new一个对象的时候,虚拟机需要为新对象分配内存和为实例变量赋初始值,这里x就被赋予了0
接下来进入<init>()方法进行实例变量的初始化
进入第一步,调用了超类的<init>方法,需要打印x的值,因此打印出来0
进入第二步,执行任意实例变量初始化方法的字节码,这里为"x=20"
进入第三步,执行构造方法将x赋值为200

描述够清楚了吧
panjinming11 2012-05-08
  • 打赏
  • 举报
回复
最直观的理解 应该就是这个了 学习了


[Quote=引用 12 楼 的回复:]
在你new student(200) 的时候 先调用父类无参的构造方法 父类无参的构造方法 调用this.print() 但是存在多态 调用的其实是子类student的print()方法 此时 x还没有被赋值 int类型默认的是0 所以打印0
[/Quote]
Rooter 2012-05-08
  • 打赏
  • 举报
回复
Person p = new Student(200);
这是个典型的多态 父类对象指向子类引用
其实多态很简单 父类指向子类引用的对象 除了非静态方法是用的子类的其余的所有的都是用的父类的
虽然你传的是200 但是父类的初始化是0 所以输出的也就是0咯
rulky 2012-05-08
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]
在你new student(200) 的时候 先调用父类无参的构造方法 父类无参的构造方法 调用this.print() 但是存在多态 调用的其实是子类student的print()方法 此时 x还没有被赋值 int类型默认的是0 所以打印0
[/Quote]
+++
ylp198296 2012-05-08
  • 打赏
  • 举报
回复
看看这个贴子 一个道理
http://topic.csdn.net/u/20120503/00/5c883ddb-3a61-43be-bf77-448795357759.html
夜子 2012-05-08
  • 打赏
  • 举报
回复
在你new student(200) 的时候 先调用父类无参的构造方法 父类无参的构造方法 调用this.print() 但是存在多态 调用的其实是子类student的print()方法 此时 x还没有被赋值 int类型默认的是0 所以打印0
woshinigeno1 2012-05-08
  • 打赏
  • 举报
回复
这应该是子类与父类的加载顺序吧,先加载父类的构造方法,再加载子类的构造方法。。。
acai 2012-05-08
  • 打赏
  • 举报
回复
Java中类的初始化顺序:
1、类在第一次调用时被加载且只被加载一次(第一次调用类的构造函数or静态域or静态方法),如果类的信息未被加载到方法区,则加载.class;
2、如果该类有父类,则检查父类是否被加载,如果木有,则加载父类,如果父类有父类,依次类推;
3、按textual order(暂且说定义)顺序初始化父类中的静态成员,静态域;最后按声明初始化当前类中的静态信息;
4、此时,所需的类的信息都被加载,可以创建对象了;
5、如果此时new对象,那么所有的primitives都被设置成default values(你懂得),object设置成null;
6、如果有父类,调用父类构造函数,同理,如果父类有父类,依次类推;
7、父类构造函数执行完成以后,初始化成员变量;
8、执行剩下的构造函数。

class Person {

public Person() {
this.print();
}
public void print(){}

}

class Student extends Person {
int x=20;
public Student(int x) {
//成员变量分配空间并初始化为默认值:x=0;
//执行Super();
//Super()执行完之后初始化x=20;
this.x = x;
}
public void print(){
System.out.println(Student.class);
System.out.println("x="+x);
}
}

public class Test1 {
public static void main(String[] args) {
Person p = new Student(200);
}
}

acai 2012-05-08
  • 打赏
  • 举报
回复
Java中类的初始化顺序:
1、类在第一次调用时被加载且只被加载一次(第一次调用类的构造函数or静态域or静态方法),如果类的信息未被加载到方法区,则加载.class;
2、如果该类有父类,则检查父类是否被加载,如果木有,则加载父类,如果父类有父类,依次类推;
3、按textual order(暂且说定义)顺序初始化父类中的静态成员,静态域;最后按声明初始化当前类中的静态信息;
4、此时,所需的类的信息都被加载,可以创建对象了;
5、如果此时new对象,那么所有的primitives都被设置成default values(你懂得),object设置成null;
6、如果有父类,调用父类构造函数,同理,如果父类有父类,依次类推;
7、父类构造函数执行完成以后,初始化成员变量;
8、执行剩下的构造函数。

class Person {

public Person() {
this.print();
}
public void print(){}

}

class Student extends Person {
int x=20;
public Student(int x) {
//成员变量分配空间并初始化为默认值:x=0;
//执行Super();
//Super()执行完之后初始化x=20;
this.x = x;
}
public void print(){
System.out.println(Student.class);
System.out.println("x="+x);
}
}

public class Test1 {
public static void main(String[] args) {
Person p = new Student(200);
}
}

logic_well 2012-05-08
  • 打赏
  • 举报
回复
一篇名为<<解读ClassLoader>>的文章 里边有你想要的答案
http://www.iteye.com/topic/83978
logic_well 2012-05-08
  • 打赏
  • 举报
回复
这个题到底基础不基础我还真不敢断言
这里边都是关于JVM执行过程类加载器工作原理的东西 敢问哪本java基础书里有介绍过这方面的知识?
棒棒不是糖_ 2012-05-08
  • 打赏
  • 举报
回复
这个简单
因为
Person p = new Student(200);
执行子类的构造方法时,先执行父类的构造方法,即super()
X还没有赋值呢。

如果你在
Person p = new Student(200);
后面再加一句
p.print();
则可以看到x是被赋值了的、
FFF9527 2012-05-08
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

这段代码的输出会是0呢?


我觉得是楼主人品的问题
[/Quote]

我试了下的确是0,是如果类没实例化就调用的话,int值是0,实例化之后才为20
加载更多回复(4)

62,615

社区成员

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

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