extends
Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类
当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类
1 2 3 4 5 6 7 8 9 10 11 12 | public class Animal { private String name; private int id; public Animal(String myName, String myid) { // init } public void eat() {...} public void sleep() {...} }
public class Penguin extends Animal{ } |
成员变量
①可以继承父类的public和protected类型的成员变量
②子类定义与父类同名的成员变量,并没有覆盖父类的成员变量,而是两个成员变量共存
③子类成员变量直接访问或使用this.,父类成员变量的访问使用super.
implements
implements可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
1 2 3 4 5 6 7 8 9 10 11 | public interface A { public void eat(); public void sleep(); }
public interface B { public void show(); }
public class C implements A,B { } |
super与this
super关键字:实现对父类成员(成员变量和成员方法)的访问,用来引用当前对象的父类
this关键字:指向自己的引用(e.g. this.name = name; this.eat())
super和this可以看作子类或者父类的类名
super()和this()是对应类的构造函数
final
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写
声明类:final class 类名 {//类体}
声明方法:修饰符(public/private/default/protected) final 返回值类型 方法名() {//方法体}
实例变量也可以被定义为 final,被定义为 final 的变量不能被修改
被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final
构造函数
子类的所有构造方法内部, 第一行会(隐式)自动先调用父类的无参构造函数super()
如果子类构造方法第一行显式调用了父类构造方法,系统就不再调用无参的super()了
注意:如果父类没有无参构造函数(父类自己只定义了带参构造函数),创建子类时,不能编译,除非在构造函数代码体中的第一行显式调用父类有参构造函数
①e.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Base { public Base() { System.out.println("Base--默认构造方法"); }
public Base(int c){ System.out.println("Base--有参构造方法--" + c); } } public class Derived extends Base { public Derived() { // super(); //系统会自动隐式先调用父类的无参构造函数 super(); //必须是第一行,否则不能编译 System.out.println("Derived--默认构造方法"); }
public Derived(int c) { // super(); //系统会自动隐式先调用父类的无参构造函数 super(); //必须是第一行,否则不能编译 System.out.println("Derived--有参构造方法" + c); }
public Derived(int a, int b) { super(a); //如果子类构造方法第一行显式调用了父类构造方法,系统就不再调用无参的super()了。 System.out.println("Derived--有参构造方法--" + b); }
public static void main(String[] args) { System.out.println("============子类无参============"); Derived no = new Derived(); System.out.println("============子类有参============"); Derived have = new Derived(33); System.out.println("============子类有参============"); Derived have2 = new Derived(33, 55); } } |
输出:
============子类无参============
Base--默认构造方法
Derived--默认构造方法
============子类有参============
Base--默认构造方法
Derived--有参构造方法33
============子类有参============
Base--有参构造方法--33
Derived--有参构造方法--55
②e.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | class SuperClass { private int n; SuperClass(){ System.out.println("SuperClass()"); } SuperClass(int n) { System.out.println("SuperClass(int n)"); this.n = n; } } // SubClass 类继承 class SubClass extends SuperClass{ private int n;
SubClass(){ // 自动调用父类的无参数构造器 System.out.println("SubClass"); }
public SubClass(int n){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass(int n):"+n); this.n = n; } } // SubClass2 类继承 class SubClass2 extends SuperClass{ private int n;
SubClass2(){ super(300); // 调用父类中带有参数的构造器 System.out.println("SubClass2"); }
public SubClass2(int n){ // 自动调用父类的无参数构造器 System.out.println("SubClass2(int n):"+n); this.n = n; } } public class TestSuperSub{ public static void main (String args[]){ System.out.println("------SubClass 类继承------"); SubClass sc1 = new SubClass(); SubClass sc2 = new SubClass(100); System.out.println("------SubClass2 类继承------"); SubClass2 sc3 = new SubClass2(); SubClass2 sc4 = new SubClass2(200); } } |
输出:
------SubClass 类继承------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 类继承------
SuperClass(int n)
SubClass2
SuperClass()
SubClass2(int n):200