一
TestInherits.java
package 代码测试2; public class TestInherits { public static void main(String args[]) { Child c = new Child(); } } class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } public Grandparent(String string) { System.out.println("GrandParent Created.String:" + string); } } class Parent extends Grandparent { public Parent() { //super("Hello.Grandparent."); System.out.println("Parent Created"); // super("Hello.Grandparent."); } } class Child extends Parent { public Child() { System.out.println("Child Created"); } }
结论 :1 通过super调用基类构造方法,必须是子类构造方法中的第一个语句;
2 我们可以在子类的构造方法中通过super指定调用父类的哪个构造方法。如果没有指定。在实例化子类对象时候会自动调用父类无参的构造方法。
在Java中的每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的构造方法。这个默认方法没有参数,在其方法体中也没有任何代码。即什么也不做。
但是如果一旦为该类定义了构造方法。系统就不再提供默认的构造方法了
3 构造函数(constructor)是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。构造函数的功能主要用于在类的对象创建时定义初始化的状态。
构造一个对象,先调用其构造方法,来初始化其成员函数和成员变量。
子类拥有父的成员变量和成员方法,如果不调用,则从父类继承而来的成员变量和成员方法得不到正确的初始化。
不能反过来调用也是这个原因,因为父类根本不知道子类有神魔变量而且这样一来子类也得不到初始化的父类变量,导致程序运行出错!
二 ExplorationJDKSource.java
package 代码测试2; public class ExplorationJDKSource { /** * @param args */ public static void main(String[] args) { System.out.println(new A()); } } class A{}
结论:前面示例中,main方法实际上调用的是:public void println(Object x),这一方法内部调用了String类的valueOf方法。valueOf方法内部又调用Object.toString方法:public String toString() { return getClass().getName() +"@" + Integer.toHexString(hashCode());}hashCode方法是本地方法,由JVM设计者实现:public native int hashCode()
三 Friut.java
package 代码测试2; public class Friut { public String toString() { return "Fruit toString."; } public static void main(String args[]) { Friut f=new Friut(); System.out.println("f="+f); System.out.println("f="+f.toString()); } }
结论:在“+”运算中,当任何一个对象与一个String对象,连接时,会隐式地调用其toString()方法,默认情况下,此方法返回“类名 @ + hashCode”。为了返回有意义的信息,子类可以重写toString()方法
四 TestCast.java
package 代码测试2; class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public static void main(String args[]) { Mammal m; Dog d=new Dog(); Cat c=new Cat(); m=d; d=m; d=(Dog)m; d=c; c=(Cat)m; } }
d=m 和d=c会报错
五 ParentChildTest.java
class Parent{ public int myValue=100; public void printValue() { System.out.println("Parent.printValue(),myValue="+myValue); } } class Child extends Parent{ public int myValue=200; public void printValue() { System.out.println("Child.printValue(),myValue="+myValue); } } public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); parent.printValue(); Child child=new Child(); child.printValue(); parent=child; parent.printValue(); parent.printValue(); ((Child)parent).myValue++; parent.printValue(); } }
结论:当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。这个特性实际上就是面向对象“多态”特性的具体表现。
2 如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。如果子类被当作父类使用,则通过子类访问的字段是父类的