Java 面向对象核心:深入理解继承机制与应用
1. 继承的基础语法与特性
在 Java 中,继承是通过 extends 关键字来实现的。它允许一个类(子类)获取另一个类(父类)的成员变量和成员方法,从而提高代码的复用性。
// 定义父类
public class Device {
private String brand;
private double price;
public String getBrand() { return brand; }
public void setBrand(String brand) { this.brand = brand; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}
// 子类继承父类
public class Phone extends Device {
private int storageSize;
public int getStorageSize() { return storageSize; }
public void setStorageSize(int storageSize) { this.storageSize = storageSize; }
}
public class Main {
public static void main(String[] args) {
Phone myPhone = new Phone();
// 子类可以直接使用父类的非私有方法
myPhone.setBrand("小米");
myPhone.setPrice(3999.0);
myPhone.setStorageSize(256);
System.out.println(myPhone.getBrand() + " 价格: " + myPhone.getPrice());
}
}
关键规则:
- 子类只能继承父类的非私有(non-private)成员。
- Java 支持单继承(一个类只能有一个直接父类),但支持多层继承(A 继承 B,B 继承 C)。
Object类是 Java 中所有类的顶级父类。
2. 权限修饰符的访问范围
Java 提供了四种访问权限修饰符,用于控制成员的可见性:
private:仅限当前类访问。缺省 (default):当前类、同包下的其他类。protected:当前类、同包类、以及其他包中的子类。public:任意位置均可访问。
3. 成员访问的就近原则与 super 关键字
当子类中出现与父类同名的变量或方法时,Java 会遵循就近原则进行访问。如果需要明确访问父类的成员,可以使用 super 关键字。
class Parent {
String info = "父类属性";
public void execute() {
System.out.println("父类执行逻辑");
}
}
class Child extends Parent {
String info = "子类属性";
public void execute() {
System.out.println("子类执行逻辑");
}
public void show() {
String info = "局部变量";
System.out.println(info); // 访问局部变量
System.out.println(this.info); // 访问子类成员变量
System.out.println(super.info); // 访问父类成员变量
execute(); // 调用子类方法
super.execute(); // 调用父类方法
}
}
4. 方法重写(Method Overriding)
当父类的方法无法满足子类的特定需求时,子类可以重新编写一个方法签名(方法名、形参列表)与父类完全一致的方法。使用 @Override 注解可以帮助检查重写逻辑的正确性。
注意事项:
- 私有方法和静态方法不能被重写。
- 子类重写方法的访问权限必须大于或等于父类方法的权限。
class Laptop extends Device {
// 重写 Object 类的 toString 方法,用于展示对象内容而非地址
@Override
public String toString() {
return "Laptop{Brand=" + getBrand() + ", Price=" + getPrice() + "}";
}
}
5. 构造器的执行流程
在创建子类对象时,子类的构造器会默认先调用父类的无参构造器,确保父类控制的成员变量能正确初始化。
5.1 使用 super(...) 调用父类构造器
如果父类没有无参构造器,或者需要通过子类构造器初始化父类的私有属性,必须在子类构造器的第一行显式使用 super(...)。
public class Member {
private String id;
public Member(String id) { this.id = id; }
}
public class VIPMember extends Member {
private int level;
public VIPMember(String id, int level) {
super(id); // 调用父类构造器
this.level = level;
}
}
5.2 使用 this(...) 调用本类构造器
在同一个类中,可以使用 this(...) 在一个构造器里调用另一个构造器,常用于设置默认值。
public class Config {
private String host;
private int port;
public Config(String host) {
// 调用本类双参构造器,默认端口 8080
this(host, 8080);
}
public Config(String host, int port) {
this.host = host;
this.port = port;
}
}
注意:this(...) 和 super(...) 都必须位于构造器的首行,因此它们不能在同一个构造器中共存。