为什么这段程序输出是18而不是是17?

lgbupt 2008-06-02 06:30:15
为什么这段程序输出是18而不是是17?


class J_SuperClass
{
int m_data;

J_SuperClass()
{
mb_add(1);
}

public void mb_add(int i)
{
m_data += i;
}

public void mb_print()
{
System.out.println(m_data);
}
}

class J_SubClass extends J_SuperClass
{
J_SubClass()
{
mb_add(2);
}

public void mb_add(int i)
{
m_data += i*2;
}
}

public class J_TestClass
{
public static void mb_method(J_SuperClass a)
{
a.mb_add(6);
a.mb_print();
}

public static void main(String args[])
{
mb_method(new J_SubClass());
}
}
...全文
163 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lgbupt 2008-06-03
  • 打赏
  • 举报
回复
谢谢各位关心,因刚开始分给的太少,无法全给分,谢谢。
七年 2008-06-02
  • 打赏
  • 举报
回复
今天在《java面试宝典》上看到这题了,其实问题是关键是在进入父类的构造方法是所执行的方法到底是执行父类的还是执行子类的,如果说按多态来说就像是父类指向了之类对象,在父类的构造方法中其实是调用了之类中覆盖了父类的那个方法。
建议:楼主以后碰到这种问题可以自己debug一下,这种问题可以通过debug来查看程序的执行过程。
lanzheking 2008-06-02
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 zhaoyong209 的回复:]
引用 4 楼 lanzheking 的回复:
当然是18啦
首先进入主方法;
在mb_method(new J_SubClass()); 中,因为创建了类new J_SubClass() ,而J_SubClass()继承了J_SuperClass,
所以就先执行J_SuperClass的无参构造函数,及mb_add(1),只是mb_add(1)并不是把1传到J_SuperClass类中的mb_add方法,
而是传到J_SubClass类中的mb_add方法,因为我们前面常见的是J_SubClass类,J_SuperClass类中的的方法已被覆盖,
这样后 m_data …
[/Quote]

也不用怎么多代码的,要看到过程,因为这里是学习用,给每个方法加上一个打印编号,然后根据编号就可以知道程序执行了哪步了

class J_SuperClass
{
int m_data;

J_SuperClass()
{
System.out.println("1");
mb_add(1);
}

public void mb_add(int i)
{
System.out.println("2");
m_data += i;
}

public void mb_print()
{
System.out.println("3");
System.out.println(m_data);
}
}

class J_SubClass extends J_SuperClass
{
J_SubClass()
{
System.out.println("4");
mb_add(2);
}

public void mb_add(int i)
{
System.out.println("5");
m_data += i*2;
}
}

public class J_TestClass
{
public static void mb_method(J_SuperClass a)
{
System.out.println("6");
a.mb_add(6);
a.mb_print();
}

public static void main(String args[])
{
System.out.println("7");
mb_method(new J_SubClass());
}
}


这样看待输出的代号序列就可以知道程序所执行的方法的过程了,
haoxiongok 2008-06-02
  • 打赏
  • 举报
回复
当然是18啦
首先进入主方法;
在mb_method(new J_SubClass()); 中,因为创建了类new J_SubClass() ,而J_SubClass()继承了J_SuperClass,
所以就先执行J_SuperClass的无参构造函数,及mb_add(1),只是mb_add(1)并不是把1传到J_SuperClass类中的mb_add方法,
而是传到J_SubClass类中的mb_add方法,因为我们前面常见的是J_SubClass类,J_SuperClass类中的的方法已被覆盖,
这样后 m_data = 2+2*2 = 6;
最后才能执行J_TestClass类中的mb_method方法中的语句a.mb_add(6); 然后m_data = 6+6*2 = 18;
最后a.mb_print();打印

所以结果是18
zhaoyong209 2008-06-02
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 lanzheking 的回复:]
当然是18啦
首先进入主方法;
在mb_method(new J_SubClass()); 中,因为创建了类new J_SubClass() ,而J_SubClass()继承了J_SuperClass,
所以就先执行J_SuperClass的无参构造函数,及mb_add(1),只是mb_add(1)并不是把1传到J_SuperClass类中的mb_add方法,
而是传到J_SubClass类中的mb_add方法,因为我们前面常见的是J_SubClass类,J_SuperClass类中的的方法已被覆盖,
这样后 m_data = 2+2*2 = 6;
最后才能执行J_T…
[/Quote]

正解

运行下面代码就可以清楚地看到整个类的运行过程。


class J_SuperClass
{
int m_data;

J_SuperClass()
{
System.out.println("Super1 "+m_data);

mb_add(1);
System.out.println("Super1 "+m_data);
}

public void mb_add(int i)
{
System.out.println("Super2 "+m_data);
m_data += i;
System.out.println("Super2 "+m_data);
}

public void mb_print()
{
System.out.println("Super3 "+m_data);
}
}

class J_SubClass extends J_SuperClass
{
J_SubClass()
{
System.out.println("Sub1 "+m_data);

mb_add(2);
System.out.println("Sub1 "+m_data);
}

public void mb_add(int i)
{
System.out.println("Sub2 "+m_data);
m_data += i*2;
System.out.println("Sub2 "+m_data);
}
}

public class J_TestClass
{
public static void mb_method(J_SuperClass a)
{
a.mb_add(6);
a.mb_print();
}

public static void main(String args[])
{
mb_method(new J_SubClass());
}
}
fredboy 2008-06-02
  • 打赏
  • 举报
回复
看了,发现自己和楼主一样觉得应该是17,所以关注一下,希望知道一下为什么。
ldt_love_java 2008-06-02
  • 打赏
  • 举报
回复
执行顺序:
class J_SuperClass
{
int m_data;

J_SuperClass()
{
mb_add(1); //1
}

public void mb_add(int i)
{
m_data += i;
}

public void mb_print()
{
System.out.println(m_data);
}
}

class J_SubClass extends J_SuperClass
{
J_SubClass()
{
mb_add(2); //2
}

public void mb_add(int i)
{
m_data += i*2; //3.传6进来
}
}

public class J_TestClass
{
public static void mb_method(J_SuperClass a)
{
a.mb_add(6);
a.mb_print();
}

public static void main(String args[])
{
mb_method(new J_SubClass());
}
}
lanzheking 2008-06-02
  • 打赏
  • 举报
回复
当然是18啦
首先进入主方法;
在mb_method(new J_SubClass()); 中,因为创建了类new J_SubClass() ,而J_SubClass()继承了J_SuperClass,
所以就先执行J_SuperClass的无参构造函数,及mb_add(1),只是mb_add(1)并不是把1传到J_SuperClass类中的mb_add方法,
而是传到J_SubClass类中的mb_add方法,因为我们前面常见的是J_SubClass类,J_SuperClass类中的的方法已被覆盖,
这样后 m_data = 2+2*2 = 6;
最后才能执行J_TestClass类中的mb_method方法中的语句a.mb_add(6); 然后m_data = 6+6*2 = 18;
最后a.mb_print();打印

所以结果是18
Jue_Xin 2008-06-02
  • 打赏
  • 举报
回复
我猜lz是烦这个问题吧;
Java语言和C的不同:自增(自减)和隐式类型转换



来源:辰迪亚 时间:2007-4-18


[摘 要] Java语言作为一种用于网络编程的纯面向对象的程序设计语言,随着互联网络的延伸而风靡世界。在Java语言的学习中,抓住难点运用比较的方法无疑会事倍功半。Java语言是由C语言演变发展而来的,C语言中提供的运算符几乎完全适合于Java语言,但具体用法上又有本质的区别。通过典型例子程序的设计、运行,来比较学习,是掌握一门新的计算机语言的最佳途径。

[关键词] Java语言;运算符;自增(自减)

Distingush for Increase (or Decrease) Operator in Java Language

HAN Rui-feng

(Xinzhou Teacher’s University , Shanxi Xinzhou 034000)

Abstract: As a sort of virtual OOP (Orient Object Programming ) language , Java becomes current with Internet’s spreading out . During the course of learning Java , it is important to grasp the main difficult points . Java language inherit almost operators from C language , but their usage are different in fact . It is the best approach to learn a new computer language by designing and running a typical program , and comparing it with a old one .

一、引言

Java语言是由C语言演变发展而来的,C语言中提供的运算符几乎完全适合于Java语言,但是也有不同之处,比如:Java是强类型语言,其类型限制就比C语言严格。看一个例子:

假定 int a = 1;

float b;

要实现把a的值赋给b的赋值运算,在C语言中,直接使用“b = a;”的表达式语句是合法的,而在Java语言中必须使用“b = ( float ) a;”这样的语句才能通过编译。这是因为C语言支持隐式类型转换运算,所以在进行赋值运算时允许赋值运算符“=”两侧的运算对象是不同的数据类型。而Java语言不支持隐式类型转换运算,必须是相同类型的数据才能进行赋值运算。这就是上面的Java语言语句中,不同数据类型的数据之间要完成赋值运算,为什么必须首先进行显式的强制类型转换运算的原因。

在Java语言中,自增(自减)运算符仍然象C语言中一样是一个教学难点,其用法也与C语言中相似,有前置和后置两种用法。但在Java语言中,它们不仅可用于整型数,还可用于浮点数(此时的增减量为1.0)。在教学中有一个典型的问题是,Java语言在继承了C语言的自增(自减)运算符以后,它们的求值方式是否保持不变?我们以自增运算符为例,分别设计Java程序和C程序来进行比较分析,得出的结论可推广到减量运算符。



二、比较分析程序设计

典型地,假定我们要计算表达式

k1 = ( i++ ) + ( i++ ) + ( i++ )

和k2 = ( ++i ) + ( ++i ) + ( ++i )在i=3时的值,对应的源程序设计如下:



程序文件1:Java语言源程序(hrf . java)

class TestInc {

public static void main ( String arg [ ] ) {

int i = 3,k1 ,k2 ; /*变量定义、初始化*/

k1 = ( i++ ) + ( i++ ) + ( i++ ); /*计算表达式k1的值*/

System . out . println ( “ k1 = ” + k1 + “ \t i = ” + i );/*计算结果输出*/

i = 3; /*变量i重新赋值*/

k2 = ( ++i ) + ( ++i ) + ( ++i ); /*计算表达式k2的值*/

System . out . println ( “ k2 = ” + k2 + “ \t i = ” + i );/*计算结果输出*/

}

}



程序文件2:C语言源程序(hrf .c)

void main ( ) {

int i = 3,k1 ,k2 ; /*变量定义、初始化*/

k1 = ( i++ ) + ( i++ ) + ( i++ ); /*计算表达式k1的值*/

printf ( “ k1 = %d , i = %d ” , k1 , i ); /*计算结果输出*/

i = 3 ; /*变量i重新赋值*/

k2 = (++i ) + (++i ) + (++i ); /*计算表达式k2的值*/

printf ( “ k2 = %d , i = %d ” , k2 , i ); /*计算结果输出*/

}



三、运行结果及分析

程序文件1(hrf .java)在编译后生成类文件(扩展名为“.class”),解释执行结果为:

k1 = 12 i = 6

k2 = 15 i = 6

程序文件2(hrf .c)在编译、连接后生成可执行文件(扩展名为“.exe”),运行结果为:

k1 = 9, i = 6

k2 = 18,i = 6

从两种程序的源代码来看,求值的程序是类似的。但由上面的运行结果差异可见,自增(自减)运算符在Java语言中的求值方式与在C语言中的求值方式根本不同。

造成自增(自减)运算符在Java语言中与在C语言中的求值方式不同的原因是,两种语言的性质不同(C语言是面向过程的程序设计语言,而Java语言是面向对象的程序设计语言)。在C语言中变量的内存空间是在编译时分配的,而且在变量的生命周期内,一个变量名只对应一块内存区域。如程序文件2(hrf .c)中的变量i,编译时分配内存并初始化为整数3。在计算表达式k1和k2的值时,首先要计算i++和++ i的值,根据自增(自减)运算符在前置和后置时的求值方式(前置时先计算后使用,后置时先使用后计算),在计算k1表达式的值时,变量i被引用三次参与加法运算以后,才进行三次自增运算;而在计算k2表达式的值时,变量i三次自增运算以后的结果6,被引用三次参与加法运算,所以:

k1 = ( i++ ) + ( i++ ) + ( i++ ) = 3 + 3 + 3 = 9

k2 = ( ++i ) + ( ++i ) + ( ++i ) = 6 + 6 + 6 = 18

可见,在C语言的程序运行过程中,变量在每一次自增运算或赋值运算之后,其所对应内存区域中的内容就被重写,在变量的生命周期内的每一瞬间只能有唯一一个确定的值。

而在Java语言中,编译时并没有为变量分配内存,仅仅是创建了一种类型变量的对象模板,在类文件被解释执行时,每次都要为所执行到的变量创建一个临时对象(分配内存)。如程序文件1(hrf .java)中的变量i,编译时并未分配内存,在运行时执行到赋值语句i = 3时,创建一个整型变量对象并初始化为3。在计算表达式k1和k2的值时,由于表达式的右端为三个自增运算表达式的和,对自增运算表达式而言,仍然与C语言中一样,是前置时先计算后使用,后置时先使用后计算。变量I分别使用了三次,就会分别创建三个临时的整型变量对象,分配相应的内存空间,用来存储每次对自增运算表达式的计算结果。所以:

k1 = ( i++ ) + ( i++ ) + ( i++ ) = 3 + 4 + 5 = 12

k2 = ( ++i ) + ( ++i ) + ( ++i ) = 4 + 5 + 6 = 15

可见,在Java语言的程序运行过程中,变量在每一次被引用时,都会创建相应的对象实例,分配相应的内存区域,其中的内容不会被重写,在变量的生命周期内的每一次引用就会有一个临时的实例对象被建立,它们的值互不影响。

通过上面的分析,很容易发现面向对象程序设计语言(如Java语言)与面向过程程序设计语言(如C语言)的区别,并能从中感受相同的运算符在使用时各自的不同特征,从而为语言的学习和运用奠定良好的基础。

参考文献

⑴张永奎等.《Internet与Java程序设计》.北京:科学出版社,2001.

⑵潭浩强.《C程序设计》(第二版).北京:清华大学出版社,2001.

⑶王士元.《C高级程序设计》.北京:清华大学出版社,1997.


lgbupt 2008-06-02
  • 打赏
  • 举报
回复
J_TestClass
Sou2012 2008-06-02
  • 打赏
  • 举报
回复
楼主执行的是哪个类

62,614

社区成员

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

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