Java继承
继承是Java面向对象编程的三大特性之一,方便实现代码的高效复用和层次化组织,是里氏替换原则的一种体现。
继承的基本概念
通过extends关键字,子类可以继承父类的属性和方法,形成类之间的“is-a”关系。这种机制不仅减少了代码冗余,更建立了清晰的类层次结构。
继承的优势
代码复用:避免重复编写相同功能的代码
扩展性:子类可在继承基础上添加新功能
多态基础:为方法重写和运行时多态提供支持
/**
* 父类
*/
public class Animal {
// 属性
protected String name;
//默认的权限修饰符,age,同一个package可继承
String age;
public Animal() {
System.out.println("Animal无参构造器");
}
// 构造方法
public Animal(String name) {
this.name = name;
System.out.println("Animal有参构造器");
}
// 通用方法
public void eat() {
System.out.println(name + "正在吃东西");
}
//将被重写的方法
public void makeSound() {
System.out.println("动物发出声音");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
/**
* 子类dog
*/
public class Dog extends Animal {
public Dog() {
//如果父类Animal有无参构造函数,子类构造函数不需要显式调用父类构造方法,编译器会默认调用父类的无参构造方法(子类总需要调用父类的构造方法)
}
public Dog(String name) {
//子类构造器必须调用父类构造器
//如果父类Animal没有无参构造函数,子类构造函数必须显式调用父类构造方法
//如果父类Animal有无参构造函数,子类构造函数不需要显式调用父类构造方法,编译器会默认调用父类的无参构造方法(即子类构造器必须调用父类构造器)
super(name);
}
/**
* 方法重写
*/
// Dog特有的方法
public void fetch() {
System.out.println(name + "正在捡球");
}
@Override
public void makeSound() {
System.out.println(name + "汪汪叫!");
}
}
/**
* 子类bird
*/
public class Bird extends Animal {
// Bird特有的属性
private boolean canFly;
public Bird(String name, boolean canFly) {
super(name);
this.canFly = canFly;
}
// Bird特有的方法
public void fly() {
if (canFly) {
System.out.println(name + "正在飞翔");
}
}
/**
* 方法重写
*/
@Override
public void makeSound() {
System.out.println(name + "咕咕叫!");
}
public boolean isCanFly() {
return canFly;
}
public void setCanFly(boolean canFly) {
this.canFly = canFly;
}
}
运行测试:
public class AnimalTest {
public static void main(String[] args) {
// 多态:父类引用指向子类对象
Animal noSuperDog = new Dog();
Animal myDog = new Dog("旺财");
Animal myBird = new Bird("小翠", true);
Animal myPenguin = new Bird("企鹅先生", false);
// 多态调用 - 运行时确定具体方法
System.out.println("=== 多态演示 ===");
myDog.makeSound(); // 输出:旺财汪汪叫!
myBird.makeSound(); // 输出:小翠叽叽咕咕叫
myPenguin.makeSound(); // 输出:企鹅先生咕咕叫
}
}
运行结果:
Animal无参构造器
Animal有参构造器
Animal有参构造器
Animal有参构造器
=== 多态演示 ===
旺财汪汪叫!
小翠咕咕叫!
企鹅先生咕咕叫!
总结:
1.父类不同权限修饰符的影响
public String publicName; // 任何地方都可访问
protected String protectedName; // 同包或子类可访问
String defaultName; // 同包可访问
private String privateName; // 仅本类可访问
简单讲就是说,子类会继承除private修饰之外的属性值。
2.super关键字的使用
super关键字的使用与 Java 的构造器机制有关。
子类构造方法必须调用父类构造方法,如果不调用 super(name),编译会报错。
调用规则:
子类构造器第一行必须是 super(...)。
如果父类没有无参构造器,子类必须显式调用 super(...)。
如果父类有无参构造器,如果子类没有显式调用 super(...),编译器会自动调用父类的无参构造器。
3.必须调用super(...)的原因
父类和子类的继承关系是"is-a",子类需要继承使用父类中属性,必须保证父类是一个正确初始化的父类对象,
所以必须先初始化父类部分,再初始化子类部分,保证对象的完整性,避免部分初始化的对象。
浙公网安备 33010602011771号