动手动脑集合四
题目一:【运行 TestInherits.java 示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大!】
TestInherits.java
1 public class TestInherits{ 2 public static void main(String args[]){ 3 Child c = new Child(); 4 } 5 } 6 7 class Grandparent { 8 public Grandparent(){ 9 System.out.println("GrandParent Created."); 10 } 11 public Grandparent(String string){ 12 System.out.println("GrandParent Created.String:" + string); 13 } 14 } 15 16 class Parent extends Grandparent{ 17 public Parent() { 18 //super("Hello.Grandparent."); 19 System.out.println("Parent Created"); 20 //super("Hello.Grandparent."); 21 } 22 } 23 24 class Child extends Parent { 25 public Child(){ 26 System.out.println("Child Created"); 27 } 28 }
若将第20行的注释去掉,则会报错,因为“构造函数调用必须是构造函数中的第一个语句”
题目二:【参看ExplorationJDKSource.java】
ExplorationJDKSource.java
1 public class ExplorationJDKSource { 2 /** 3 * @param args 4 */ 5 public static void main(String[] args) { 6 System.out.println(new A()); 7 } 8 } 9 10 class A{}
A中没有任何成员,其继承来自于Object
main方法中实际上调用的是public void println(Object x)
这一方法内部调用了String类的valueOf方法
valueOf方法内部又调用了Object.toString方法:
public String toString() {
return getClass().getName()+"@"+Interger.toHexString(hashCode());
}
hashCode方法是本地方法,由JVM设计者实现
题目三:【运行以下测试代码】
1 public class ParentChildTest { 2 public static void main(String[] args) { 3 Parent parent=new Parent(); 4 parent.printValue(); 5 Child child=new Child(); 6 child.printValue(); 7 8 parent=child; 9 parent.printValue(); 10 11 parent.myValue++; 12 parent.printValue(); 13 14 ((Child)parent).myValue++; 15 parent.printValue(); 16 17 } 18 } 19 20 class Parent{ 21 public int myValue=100; 22 public void printValue() { 23 System.out.println("Parent.printValue(),myValue="+myValue); 24 } 25 } 26 class Child extends Parent{ 27 public int myValue=200; 28 public void printValue() { 29 System.out.println("Child.printValue(),myValue="+myValue); 30 } 31 }
总结:
当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。
这个特性实际上就是面向对象“多态”特性的具体表现。
如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
如果子类被当作父类使用,则通过子类访问的字段是父类的!
牢记:在实际开发中,要避免在子类中定义与父类同名的字段。不要自找麻烦!