Java中父类和子类中的方法调用和参数传递探讨
来源:互联网 发布:有些通信网络维护 编辑:程序博客网 时间:2024/06/06 03:47
有这样一段程序,看看它会输出什么结果
public class Test { public static void main(String [] args){ System.out.println(new B().getValue()); } static class A{ protected int value; public A(int v) { setValue(v); } public void setValue(int value){ this.value = value; } public int getValue(){ try{ value++; return value; } catch(Exception e){ System.out.println(e.toString()); } finally { this.setValue(value); System.out.println(value); } return value; } } static class B extends A{ public B() { super(5); setValue(getValue() - 3); } public void setValue(int value){ super.setValue(2 * value); } } }
输出:
223417
这段程序咋一看没什么特殊的,但是细细分析下来,发现想搞清楚它的运行过程还真不简单。通过Eclipse单步调试,得出其运行流程如下:(序号1、2就表示运行次序)
public class Test { public static void main(String[] args) { System.out.println(new B().getValue());//1、程序开始 } static class A { protected int value;// public A(int v) {//4、调用A的构造方法,v=5 setValue(v);//5、调用setValue方法(关键是调用A中的方法还是B中的?) /* * 这其实涉及到编译时类型和运行时类型的问题,就setValue(v);这条语句而言, * 调用这条语句的对象实际上是this。而this的编译时类型是A(编译时这条语句在A类中), * 但是运行时类型却是B。main方法中只有一条语句,我们分析的所有操作都是因为 * new B().getValue()这个语句引起的。所以运行时类的类型是B。那么我们调用的自然 * 是B中的setValue方法。只有当B中没有setValue方法时,才会调用父类A中的setValue方法。 */ } public void setValue(int value) {//8、子类B通过super显示调用该方法,输入参数value=10 this.value = value;//9、与第5步类似,这里this还是指B类,但是B类中并没有显式定义名为value的成员,但是因为B类继承了A, //而A中的value修饰符为protect,所以B类也继承了这个value成员。而且,这时A,B中持有的value引用是一样的,是指向同一内存区域。 //换句话说,无论两者谁修改了value的值,都会影响到对方。 //this.value=value是把B类中value值设为10,同时A中的value值受到影响,也变为10(因为是同一个value引用) } public int getValue() {//11、执行getValue方法,此时A的成员变量value值为10 try { value++;//12、A的value值变为11,同时B中的value值变为11 return value;//13、返回value=11,但不会立即返回,会先执行finally语句块 } catch (Exception e) { System.out.println(e.toString()); } finally {//14、finally语句块 this.setValue(value);//15、调用B的setValue方法 System.out.println(value);//16、输出value值,此时A(B)中的value为22 /* * finally语句块执行完毕后会执行try语句块中的return语句,虽然value的值变为22,但是getValue()的返回值仍然是11。 * 这是因为在try语句块中的return语句执行时把返回值保存在局部变量里,需要返回时再取出来。 * 但是假如在finally语句中也有return语句的话,返回值就是finally语句块中的return返回值,而try语句块中的返回值被覆盖(失效) */ } return value;//不会执行该句 } } static class B extends A { public B() {//2、先调用B的构造方法 super(5);//3、调用父类A的构造方法并传入参数5 setValue(getValue() - 3);//10、执行该句,首先计算getValue() - 3的值,这将调用A的getValue()方法。 //11、计算得到getValue() - 3=8,然后执行setValue(8), } public void setValue(int value) {//6、调用子类的setValue方法 super.setValue(2 * value);//7、通过super显式调用父类的setValue方法,传入参数10 } }}
通过对上述程序的分析,可以得到如下信息:
1、当子类对象调用一个方法时,会优先在子类中查找,然后才回去父类中查找。如果子类调用了父类的方法method1,而method1又调用了method2,那么这个method2还是会优先在子类中查找,找不到才会去父类中查找。
2、如果子类继承了父类的成员变量(前提是可以继承public和protected),而子类没有显示覆盖该成员变量,那么子类访问到的成员变量和父类访问到的成员变量是同一个变量。任何一个修改后都会影响到另一个。
3、try中的return会在finally语句块之后运行,如果finally语句块中有return语句,那个就直接返回这个return值。如果没有,就返回try中的return值(finally块中的任何非return操作都不会影响到try中的return值)。
阅读全文
1 0
- Java中父类和子类中的方法调用和参数传递探讨
- Java中父类和子类中的方法调用和参数传递总结
- 在java中父类调用子类中的方法
- Java中的值传递和引用传递(参数传递)
- java中父类和子类构造调用方式
- Java中的变量赋值和参数传递
- Java和C++中的参数传递
- Java中的参数传递问题和图解
- 关于C语言中函数调用和参数传递机制的探讨(一 .无参数传递)
- 关于C语言中函数调用和参数传递机制的探讨(二 .传递一个参数)
- 关于C语言中函数调用和参数传递机制的探讨(三 .传递多个参数等)
- 子类调用父类方法:c++和java的不同
- 使用Java的子类调用构造方法super()和this()
- Java父、子类成员变量和方法的调用关系
- java子类如何调用父类变量和方法
- 关于C语言中函数调用和参数传递机制的探讨
- 关于C语言中函数调用和参数传递机制的探讨
- 关于C语言中函数调用和参数传递机制的探讨
- 获取当前年份前后各五年的数据与双击选中方法的使用
- beego源码分析——配置文件
- hbase 源代码分析 (12) Master和RegionService 启动过程
- Caffe源码解析1:Blob
- (六)1609.4协议详解
- Java中父类和子类中的方法调用和参数传递探讨
- python pyqt组件学习(1)
- 二维数组访问问题
- JavaSE_笔试题_判断题1
- c++模块间传递参数的一些经验教训
- Caffe源码解析2:SycedMem
- C++ 多态 (virtual)
- DC-6:数组逆序的两种思路
- Lua学习-语句