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"); } } public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
结论:通过super调用基类构造方法,必须是子类构造方法中的第一个语句。
子类必须先调用父类的构造方法是因为:
构造函数(constructor)是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。构造函数的功能主要用于在类的对象创建时定义初始化的状态。
构造一个对象,先调用其构造方法,来初始化其成员函数和成员变量。
子类拥有父的成员变量和成员方法,如果不调用,则从父类继承而来的成员变量和成员方法得不到正确的初始化。
不能反过来调用也是这个原因,因为父类根本不知道子类有什么变量而且这样一来子类也得不到初始化的父类变量,导致程序运行出错!
不允许继承的类:
final class 类名
{
}
以final声明的方法不允许覆盖。
以final声明的变量不允许更改。
利用final,可以设计出一种特殊的"只读"的"不可变类"。
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();
方法覆盖:
class Parent extends Grandparent { public int add1(){ return 1; } }
class Child extends Parent { public int add1(){ return 2; } public int superadd1(){ return super.add1() ; } }
结论:方法覆盖要求子类与父类的方法一模一样,否则就是overload(重载)。
在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。
1.覆盖的方法允许访问范围不能小于原方法。
2.覆盖方法所抛出的异常不能比原方法更多。
3.声明为final方法不允许覆盖。 例如,object的getclass()方法不能覆盖。
4.不能覆盖静态方法。
抽象类:
1.abstract修饰的类称为“抽象类”,它只定义了什么方法应该存在,不能创建对象,必须派生出一个子类,并在子类中实现其未实现的方法之后,才能使用new关键字创建对象。
在方法前加上abstract就形成抽象方法,只有方法声明,没有实现代码
2.从抽象类继承的子类必须实现父类的所有抽象方法,否则,它仍然是抽象类
3.以下模式总是成立的:
抽象类 抽象类变量 = new 派生自抽象类的具体子类();
接口:
1.定义一个接口,采用关键字interface,实现一个接口,采用关键字implements
2.接口的成员函数自动成为public的,数据成员自动成为static和final的。
3.如果接口不声明为public的,则自动变为package。
4.一个类可以同时实现多个接口。
5.接口类型 接口类型的变量=new 实现了接口的具体类型()。
接口的扩充:
1.可以通过继承接口来扩充已有接口,并形成一个新的接口。
interface OneInterface { void f1(); } interface TwoInterface extends OneInterface { void f2(); }
2.实现子接口的类,必须实现“父”“子”接口所定义的所有方法,才能被实例化(即new出一个对象)。
接口与抽象类的区别:
1.抽象类是一个不完全的类,而接口只是表明类应该具有哪些“外部”特征,不涉及任何实现细节。
2.接口基本上不具备继承的任何具体特点,它仅仅承诺了外界能够调用的方法。
3.一个类一次可以实现若干个接口,但一个类只能继承一个父类。