今天看到这样一篇文,是一道Java程序运行结果的问题,据有关专家调查,结果是98%的Java程序员都搞不懂,看了的确好奇怪,请大家也来看看,证实下是否属实,很疑惑... 问题:public class Parent
{
public void test()
{} public Parent()
{
test();
} public static void main(String[] args)
{
new Child();
}
}class Child extends Parent
{
private int instanceValue = 20;
public void test()
{
System.out.println("instance value is: " + instanceValue);
}
} 各位先猜猜打印的结果是多少呢?为什么呢?
{
public void test()
{} public Parent()
{
test();
} public static void main(String[] args)
{
new Child();
}
}class Child extends Parent
{
private int instanceValue = 20;
public void test()
{
System.out.println("instance value is: " + instanceValue);
}
} 各位先猜猜打印的结果是多少呢?为什么呢?
{
String school = ”it315”;// 显式初始化
……
} 将“it315”赋值给school成员变量。 (6)执行当前构造方法的方法体中的程序代码,如: public Student extends Person
{
public Student(String name,int age,String school)
{
super(name,age);
this.school = school;
}
}
转www.javajia.com
int instanceValue; // 构造之前执行,这时没有赋值为0
instanceValue= 20; //构造之后执行
public void test() {}
是我理解有问题,还是......
构造过程如下:
父类成员初始化
父类构造器
子类成员初始化
子类构造器啊,
new Child();会先去初始化父类成员,调用test()方法,但是此方法子类实现了override,所以执行子类中的test()方法,此时子类字段未初始化,系统自动初始化为0。
整个初始化过程我还是明白。开始有点模糊的是父类中的test方法为什么执行的是子类?
结果是什么也没有显示,所以根本就没有执行println 语句!
测试环境: XP2+JAVA SDK5。0!
经过上机验证,输入 java Parent
结果是什么也没有显示,所以根本就没有执行println 语句!
测试环境: XP2+JAVA SDK5。0!
正确答案是:instance value is: 0对不起,上次我输入代码Child 时少输了extends Parent,所以才造成什么也没有输出!!
因为你创建的对象是Child类的不是Parent的
首先,有一点肯定的是Java会为没有构造函数的类家一个没有参数的构造函数。
其次,构造函数的第一个语句不是super(...)的话,Java会为它加一个默认的super();调用
第三,我又新建了一个Runner雷,专门负责运行。以便独立观察Parent,Child的行为。
第四,我在Parent类里也加了静态的成员,并对各类稍作修改。
第五,执行顺序见代码注释,JDK1.4.2_13public class Runner {
public static void main(String[] args) {
new Child(); //1
}
}class Parent {
public static int PARENT_STATIC;
{
PARENT_STATIC = 0; //3
} public void test() {
} public Parent() {
test(); //4
}}class Child extends Parent {
public int CHILD_STATIC; {
CHILD_STATIC = 0; //6
} public Child() {
super(); //2
} public void test() {
System.out.println("instance value is: " + CHILD_STATIC); //5
}
}
2、构造函数的第一个语句不是super(...)的话,Java会为它加一个默认的super();的调用,所以,做题的时候自己加上一个吧。
3、类的块语句,会在构造函数的super调用后执行。切记,不是static块,static块在加载类的时候运行。若要彻底明白这道题,看看下面的代码:public class Runner {
public static void main(String[] args) {
new Child(); //1
}
}class Parent {
public static int PARENT_STATIC;
static {
PARENT_STATIC = 0; //2
} public int parentVar;
{
parentVar = 0; //6
} public void test() {
} public Parent() {
super(); //5
test(); //7
}}class Child extends Parent {
public static int CHILD_STATIC; static {
CHILD_STATIC = 0; //3
} public int childVar; {
childVar = 0; //9
} public Child() {
super(); //4
} public void test() {
System.out.println("instance value is: " + CHILD_STATIC); //8
}
}
我觉得int instanceValue = 20;定义应看成两部分:第一部分是定义变量 变量默认为0,第二部分是给变量赋值 因为变量在内存中先声明区域 再初始化分配大小
首先是有2个类 又有继承 从main()进 先调用父类的构造方法 我相信大家都知道把
再就是构造方法里调用子类的text()方法 多太 重写
再打印为0
希望高手指点下 我也是刚学 谢谢
我觉得int instanceValue = 20;定义应看成两部分:第一部分是定义变量 变量默认为0,第二部分是给变量赋值 因为变量在内存中先声明区域 再初始化分配大小
首先是有2个类 又有继承 从main()进 先调用父类的构造方法 我相信大家都知道把
再就是构造方法里调用子类的text()方法 因为根据 多态 重写
再打印为0
希望高手指点下 我也是刚学 谢谢
JAVA技术群!愿意的加!36310034!!!!
JAVA技术群!愿意的加!36310034!!!!
vJAVA技术群!愿意的加!36310034!!!!
JAVA技术群!愿意的加!36310034!!!!
被人家骗了吧!补充一句,yupengfei_110() 的答案我认为才是正确的。
经过上机验证,输入 java Parent
结果是什么也没有显示,所以根本就没有执行println 语句!
测试环境: XP2+JAVA SDK5。0!
执行父类的test()方法
我认为是这样,没有尝试
{
public void test(){
}
public static void main(String [] args)
{
new B();
}
}class B extends C
{
int num=20;
public void test()
{
System.out.println("num : "+num);
}
}
没有输出
{
public void test(){
}
public C()
{
test();
}
public static void main(String [] args)
{
new B();
}
}class B extends C
{
int num=20;
public void test()
{
System.out.println("num : "+num);
}
}num : 0刚才少打了父类构造函数
{
public void test(){
System.out.println("Parent.test()");
}
public Parent()
{
System.out.println("Parent");
test();
}
public static void main(String[] args){
System.out.println("main");
new Child();
}
}
public class Child extends Parent {
public Child(){
System.out.println("Child");
}
private int instanceValue = 20;
public void test()
{
System.out.println("Chile.test()");
System.out.println("instance value is: " + instanceValue);
}}
我加了以下打印,输出结果为:
main
Parent
Chile.test()
instance value is: 0
Child
public class Parent
{
public void test() {} public Parent() {
test();
} public static void main(String[] args) {
Child child=new Child();
child.test();
}
}class Child extends Parent {
private int instanceValue = 20;
public void test() {
System.out.println("instance value is: " + instanceValue);
}
}
是这样的 其实很简单大家反编译以下class 文件看生成的字节码就很清楚了
首先 new Child() 会生成2条语句 :
new #20 <Class Child>
invokespecial #21 <Method void Child()>
先创建对象顺序 Object->Parent->Child 这个时候根据JAVA的规则赋默认值比如int 类型为0
然后才调用 够造函数
这样大家就明白多了吧。
其实够造函数和其他的普通方法没有什么区别,你把他当作普通的方法一样。只不过new 以后虚拟机会自动调用它而已。
写成以下的伪代码大家
class Parent{
public void test() {} public void Parent() {//编译器会转换够找函数为这样
test();
}
}
class Child extends Parent {//其实是这样
private int instanceValue = 20;
public void Child(){
//调用Parent() ;方法
instanceValue=20;
};
public void test() {
System.out.println("instance value is: " + instanceValue);
}
}
new Child() 转换为 new child;
调用方法Child();一直到执行结束
至于静态语句 只在第一次主动调用的时候执行。大家要记住 创建对象与初始化是2个步骤
很显然,在构造parent的时候,test没有具体实现;而child的无参构造没有重写,所以child的test没有作用(你要是用eclipse会发现此test有一条黄线标示,说明没有被调用。。)
java Parent
会先运行main,
new Child()初始化Child
首先声明和初始所有的final域
然后声明其他的域
然后调用构造函数
因为Child没有明确构造函数,它将调用父类的默认构造函数
这时候,child其实变为
class Child
{
private int indstancdValue=20;
public Child
{
test();
}
public void test
{
System.out.println("instanceValue="+instanceValue);
}
}
child的构造函数直接调用child的test方法
这时候因为只是声明了instanceValue,它会被赋予默认值,数字为0
然后调用println方法打印
然后才执行instanceValue=20可以在main中初始化一个child实例,然后再调用其test方法
结果将打印为20一般情况下,如果想在初始化化之间就给变量赋值
可以声明其为final
但这样就无法再修改其值了例如如果改为
final int instanceValue=20;
打印结果将会是20
$ z(o-.-o)(o-.-o) . $
$ ┏~﹊︸ ̄~﹊︸ ̄~┓ $
$ IT者-IT开发者的网站-- $
$ 10万篇技术资料--天天更新 $
$ -----www.itzhe.cn----- $
new Child();//调用子类首先先调用父类的构造函数 这时调用的test()Child的构造函数还没有被调用 所以输出为0
public class Parent
{
public void test(){}
public Parent()
{
test();
}
public static void main(String[] args)
{
new Child();//调用子类首先先调用父类的构造函数
}
}class Child extends Parent
{
private int instanceValue = 20;
public void test()
{
System.out.println("instance value is: " + instanceValue);
}
}
//Parent的字节码
public class Parent extends java.lang.Object{
public void test();
Code:
0: returnpublic Parent();
Code:
0: aload_0
1: invokespecial #13; //Method java/lang/Object."<init>":()V
4: aload_0
5: invokevirtual #15; //Method test:()V //看这个invokevirtual指令会多态调用,再转到Child的 test()方法去
8: returnpublic static void main(java.lang.String[]);
Code:
0: new #19; //class Child
3: invokespecial #21; //Method Child."<init>":()V
6: return}//Child的字节码
class Child extends Parent{
Child();
Code:
0: aload_0
1: invokespecial #10; //Method Parent."<init>":()V
4: aload_0
5: bipush 20 //构造Parent的时候,常量20还没有压到栈里
7: putfield #12; //Field instanceValue:I
10: returnpublic void test();
Code:
0: getstatic #19; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #25; //class java/lang/StringBuilder
6: dup
7: ldc #27; //String instance value is:
9: invokespecial #29; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
12: aload_0 //整数零赋值为 instanceValue
13: getfield #12; //Field instanceValue:I //取到的是0
16: invokevirtual #32; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
19: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: invokevirtual #40; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: return}可以看出在 new Child()->Parent.test()->Child.test()的过程中Child的构造函数并没有执行,所有instanceValue是一个默认值,Parent构造之后才去构造Child(),会给instanceValue赋上20
Parent和Child的关系是:
Child isA Parent
Child hasA Parent