之所以贴出这道题,是因为觉得真的好,真的值得整理总结,因为它覆盖了Java的许多语法知识点,可以说,只要有一点没有透彻弄懂,这题就很难做到全对
有这样的血泪教训,是因为,我在还没完全彻彻底底明白所有语法点之前,我凭着感觉做时,做了3次,都和答案不一样。于是决定好好把知识点理一理,帮助自己日后复习,也希望给初学者一些帮助~
-------------------------------其他相关文章------------------------------
[Java学习 ] 类的其他文章汇总(都是超链接,可直接点击):
[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 001
[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 002
[ Java学习 ] 破除思维定势之 C++ 和 Java 的差异 003
[ Java学习 ] 包语句 package等语句的汇总整理
[ Java学习 ] “goto语句“ 和 “continue + 标号” 的不同待遇
[ Java学习 ] toString方法 和 equals方法
-------------------------------言归正传,进入本文的内容-------------------------------
先上题目,题目是一段Java代码,要求我们写出它的输出
(先别急着在eclipse上跑程序,先自己把答案写答案出来
因为…如果你对知识点不是特别烂熟于心,你自己第一次做的答案,很可能会错很多,就像我一样)
//题目是一段Java代码,要求我们写出它的输出结果 class A { int a = 10; static int b = 20; A() { } void f1() { System.out.println("A.a=" + a++); } static void f2() { System.out.println("A.b=" + b++); } } public class test extends A { int a = 100; static int b = 200; void f1() { System.out.println("test.a=" + a++); } static void f2() { System.out.println("test.b=" + b++); } public static void main(String args[]) { A t= new test(); t.f1(); t.f2(); System.out.println("a=" + t.a); System.out.println("b=" + t.b); test s = new test(); System.out.println("a=" + s.a); System.out.println("b=" + s.b); } }
//我们先把最后三句代码屏蔽掉,先只看上转型变量的部分,待会再来单独分析最后三句的输出 //我的这个程序可以在eclipse上跑一下,因为我加了很多注释,来说明每步的结果,为什么会是那样 package test; class A { int a = 10; static int b = 20; A() { System.out.println("a=" + a + ", b=" + b); System.out.println("加上这句,可以很清楚地看出,初始化了A类以后,才调用A的构造函数"); System.out.println("略微提一下,初始化的意思是,调用 int a = 10; 和 static int b = 20; 这两句代码"); } void f1() { System.out.println("A.a=" + a++); } static void f2() { System.out.println("A.b=" + b++); System.out.println("上句代码的输出,体现的知识点是:"); System.out.println("如果子类重写了父类静态方法,那么子类对象的上转型对象,不能调用子类的静态方法,只能调用父类的静态方法。"); } void printABNow() { System.out.println("a=" + a + ", b=" + b); } } public class test extends A { int a = 100; static int b = 200; test() { System.out.println("a=" + a + ", b=" + b); System.out.println("加上这句,可以很清楚地看出,初始化了test类以后,才调用test的构造函数"); System.out.println("并且我们还发现,a和b的值都和之前不一样了"); System.out.println(); System.out.println("这时你可能会猜测说,是不是a和b的值被覆盖了,但其实没有覆盖,只是父类中的a和b,被子类中的a和b隐藏了而已。"); System.out.println("并且,父类中的a和b,仍然还可以通过,调用从父类继承的方法,操作隐藏的成员变量,我们可以来做个测试"); printABNow(); System.out.println("这个测试告诉我们,其实 100 和 200,分别只是test类的a和b,而 A类中的a和b,还是仍然保留着,并且能通过A调用A类的函数来观察"); System.out.println(); } void f1() { System.out.println("test.a=" + a++); System.out.println("上句代码的输出,体现的知识点是:"); System.out.println("如果子类重写了父类的某个实例方法后,当对象的上转型调用这个实例方法时,一定是调用了子类重写的实例方法。"); } static void f2() { System.out.println("test.b=" + b++); } public static void main(String args[]) { A t= new test(); t.f1(); t.f2(); System.out.println("a=" + t.a); System.out.println("b=" + t.b); System.out.println("上两句不是调用方法,而是输出类中的值,它体现的知识点是:"); System.out.println("可以通过上转型变量访问父类中被子类隐藏的成员变量。"); System.out.println("这是因为上转型变量通过父类模板去寻找相应的成员变量,找到的正是父类中被子类隐藏的成员变量。"); System.out.println("不过需要注意一下的是,之前调用函数时,是有后++自增符号的,所以值发生了小变化"); // test s = new test(); // System.out.println("a=" + s.a); // System.out.println("b=" + s.b); } }
//在eclipse上跑完得到的结果是: a=10, b=20 加上这句,可以很清楚地看出,初始化了A类以后,才调用A的构造函数 略微提一下,初始化的意思是,调用 int a = 10; 和 static int b = 20; 这两句代码 a=100, b=200 加上这句,可以很清楚地看出,初始化了test类以后,才调用test的构造函数 并且我们还发现,a和b的值都和之前不一样了 这时你可能会猜测说,是不是a和b的值被覆盖了,但其实没有覆盖,只是父类中的a和b,被子类中的a和b隐藏了而已。 并且,父类中的a和b,仍然还可以通过,调用从父类继承的方法,操作隐藏的成员变量,我们可以来做个测试 a=10, b=20 这个测试告诉我们,其实 100 和 200,分别只是test类的a和b,而 A类中的a和b,还是仍然保留着,并且能通过A调用A类的函数来观察 test.a=100 上句代码的输出,体现的知识点是: 如果子类重写了父类的某个实例方法后,当对象的上转型调用这个实例方法时,一定是调用了子类重写的实例方法。 A.b=20 上句代码的输出,体现的知识点是: 如果子类重写了父类静态方法,那么子类对象的上转型对象,不能调用子类的静态方法,只能调用父类的静态方法。 a=10 b=21 上两句不是调用方法,而是输出类中的值,它体现的知识点是: 可以通过上转型变量访问父类中被子类隐藏的成员变量。 这是因为上转型变量通过父类模板去寻找相应的成员变量,找到的正是父类中被子类隐藏的成员变量。 不过需要注意一下的是,之前调用函数时,是有后++自增符号的,所以值发生了小变化
//再来分析刚刚屏蔽掉的最后3句代码 package test; class A { int a = 10; static int b = 20; A() { } void f1() { System.out.println("A.a=" + a++); } static void f2() { System.out.println("A.b=" + b++); } } public class test extends A { int a = 100; static int b = 200; void f1() { System.out.println("test.a=" + a++); } static void f2() { System.out.println("test.b=" + b++); } public static void main(String args[]) { // A t= new test(); // t.f1(); // t.f2(); // System.out.println("a=" + t.a); // System.out.println("b=" + t.b); test s = new test(); System.out.println("a=" + s.a); System.out.println("b=" + s.b); System.out.println("上面两句代码的输出,体现的知识点是:"); System.out.println("在Java中,子类也可以隐藏由父类继承来的成员变量,只要子类中声明的成员变量和父类的成员变量同名,就可以将其隐藏。 "); } }
//在eclipse上跑完得到的结果是: a=100 b=200 上面两句代码的输出,体现的知识点是: 在Java中,子类也可以隐藏由父类继承来的成员变量,只要子类中声明的成员变量和父类的成员变量同名,就可以将其隐藏。
最后,再把我查阅过的资料一并附上:(都是超链接,可直接点击):
最后的最后,我想附带说一下的就是,这题主要是难在上转型变量的部分,因为语法规则比较多,稍不注意就很可能弄错,至于普通的继承,其实和C++大同小异。
所以,我个人的感觉是,学习Java的继承时,有必要把上转型变量的语法透彻清楚地弄得明明白白,因为…
上转型变量真的是稍不注意就能踩肯多坑的知识点啊!
^(* ̄(oo) ̄)^