继承的概念
继承体现为两个类之间的一般与特殊的关系。如果A类是一种特殊的B类,则A继承B。我们将B称为父类,A称为子类。继承使用extends关键字。子类继承了父类,子类就称为一种特殊的父类,子类便具有了父类的功能,即子类会继承父类的成员。
如果没有显式的使用extends继承任何类,则该类隐式继承Object类。Object是所有类的父类。任何类(除Object自身)都是Object类的直接或间接子类。
在Java中,类只支持单继承。一个子类只能继承一个父类。
继承的优势:
通过继承,可以有效减少代码的重复。有利于程序的维护。
public class Inherit {
public static void main(String[] args) {
Vehicle v = new Vehicle();
v.run();
Bus b = new Bus();
b.run();
}
}
class Vehicle {
public void run() {
//System.out.println("run()");
System.out.println("run1()");
}
}
//子类继承父类之后,子类还可添加自身方法。
class Bus extends Vehicle {
//子类所特有的功能
public void openDoor() {
System.out.println("开门");
}
}
成员的继承
当子类与父类在同一个包中时,子类可以继承父类public, protected, 默认访问权限的成员。不能继承private访问权限的成员。
当子类与父类不在同一个包中时,子类可以继承父类public,protected访问权限的成员,不能继承默认的,private访问权限的成员。
构造器不是方法,也不是类的成员。构造器不能被子类继承。
//同一个包中
package com.lvamber;
public class A {
public int a;
protected int b;
int c;
private int d;
public void a() {
}
protected void b() {
}
void c() {
}
private void d() {
}
public A() {
System.out.println("构造器");
}
}
class A extends B {
public void access() {
//this.a = 1;
a = 1;
b = 1;
c = 1;
//d = 1;
a();
b();
c();
//d();
//错误
//new B();
}
public B(int x) {
}
}
//不同包中
package com.lvamber.lah;
import com.lvamber.A;
public class C extends A {
public void access() {
a = 1;
b = 1;
//不同的包,子类不能继承父类中定义的默认的和
//private的属性
//c = 1;
//d = 1;
a();
b();
//不同的包,子类不能继承父类中定义的默认的和
//private的方法
//c();
//d();
}
}
构造器
尽管子类不会继承父类的任何构造器,但是,子类会在构造器中首先调用父类的构造器。而父类也会在其构造器中调用其自己父类的构造器。直到调用到Object类的构造器为止。
父类构造器的调用:
子类通过super来调用父类的构造器。当我们在子类的构造器
中没有显式的使用super来调用父类的构造器时,编译器会自动
为我们补上super()来调用父类无参的构造器。
注意:
当没有声明构造器时,编译器会补充默认的的构造器。同时,在默认的构造器中,会使用super来调用父类无参的构造器。
子类调用父类构造器的语法要求:
1 需要通过super调用父类的构造器,而不能通过父类构造器的名字调用。
2 调用父类的构造器必须出现在子类的构造器中,而不能出现在子类的构造器之外。
3 调用父类的构造器必须出现在子类构造器中的第一条语句。
补充说明:(编译器补充super)
当在子类构造器中使用this调用子类其他构造器时,编译器此时不会再补充super来调用父类的无参构造器。(为了避免重复的初始化)
public class Super {
public static void main(String[] args) {
//new Sub();
}
}
class Super {
//父类构造器就在子类构造器执行之前得到执行。
//子类构造器中会首先调用父类的构造器。
/*public Super() {
System.out.println("父类构造器执行");
}*/
public Super(int x) {
}
}
class Sub extends Super {
/*public Sub() {
//super();
//显式调用父类含有参数的构造器。
super(10);
System.out.println("子类构造器执行");
}*/
/*
//默认的构造器
public Sub() {
this(3);
super();
}
*/
}
super的使用
1 调用父类的构造器
2 通过super可以访问父类的成员
public class SuperUse {
public static void main(String[] args) {
Sub1 s = new Sub1();
s.f();
}
}
class Super1 {
public void f() {
System.out.println("父类的f()方法");
}
}
class Sub1 extends Super1 {
public Sub1() {
//调用父类的构造器
super();
//调用当前类的方法
this.f();
//调用父类的f方法。
super.f();
}
public void f() {
super.f();
}
}