Java基础十三:Java中的继承、重写(Override)与重载(Overload)详解

Java继承

继承是面向对象编程的三大特性之一(封装,继承,多态),它允许子类继承父类的属性和方法,实现代码复用

1. 继承的基本概念

java 复制代码
/**
 * 父类(基类、超类)
 */
class Animal {
    protected String name;
    protected int age;
    
    public Animal() {
        System.out.println("Animal无参构造");
    }
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal有参构造");
    }
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
    
    public void display() {
        System.out.println("名字: " + name + ", 年龄: " + age);
    }
}

/**
 * 子类(派生类)- 单继承
 */
class Dog extends Animal {
    private String breed;  // 品种
    
    public Dog() {
        super();  // 调用父类无参构造(默认存在)
        System.out.println("Dog无参构造");
    }
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类有参构造
        this.breed = breed;
        System.out.println("Dog有参构造");
    }
    
    // 子类特有的方法
    public void bark() {
        System.out.println(name + "正在汪汪叫");
    }
    
    // 重写父类方法
    @Override
    public void eat() {
        System.out.println(name + "正在吃狗粮");
    }
}

public class InheritanceBasic {
    public static void main(String[] args) {
        // 创建子类对象
        Dog dog = new Dog("旺财", 3, "金毛");
        dog.eat();      // 调用重写的方法
        dog.sleep();    // 调用继承的方法
        dog.bark();     // 调用子类特有方法
        dog.display();  // 调用继承的方法
    }
}

2. 继承的特性

java 复制代码
/**
 * 演示继承的各种特性
 */
class Parent {
    // 1. 访问修饰符对继承的影响
    public String publicField = "public字段";
    protected String protectedField = "protected字段";
    String defaultField = "default字段";
    private String privateField = "private字段";
    
    public void publicMethod() {
        System.out.println("public方法");
    }
    
    protected void protectedMethod() {
        System.out.println("protected方法");
    }
    
    void defaultMethod() {
        System.out.println("default方法");
    }
    
    private void privateMethod() {
        System.out.println("private方法");
    }
    
    // 2. 静态方法
    public static void staticMethod() {
        System.out.println("父类静态方法");
    }
    
    // 3. final方法(不能被重写)
    public final void finalMethod() {
        System.out.println("final方法,不能被重写");
    }
    
    // 4. 普通方法示例
    public void show() {
        System.out.println("父类show方法");
    }
}

class Child extends Parent {
    // 可以访问父类的public、protected、default成员
    public void testAccess() {
        System.out.println(publicField);      // ✅ 可以访问
        System.out.println(protectedField);   // ✅ 可以访问
        System.out.println(defaultField);     // ✅ 可以访问(同包)
        // System.out.println(privateField);   // ❌ 不能访问
    }
    
    // 重写父类方法
    @Override
    public void show() {
        System.out.println("子类重写的show方法");
    }
    
    // 静态方法不能重写,只能隐藏
    public static void staticMethod() {
        System.out.println("子类静态方法(隐藏父类方法)");
    }
    
    // ❌ 不能重写final方法
    // public void finalMethod() { }  // 编译错误
}

public class InheritanceFeatures {
    public static void main(String[] args) {
        Child child = new Child();
        child.testAccess();
        child.show();                    // 调用子类重写的方法
        child.publicMethod();            // 继承的方法
        child.protectedMethod();         // 继承的方法
        
        // 静态方法调用(推荐使用类名调用)
        Parent.staticMethod();
        Child.staticMethod();
    }
}

3. 多层继承

java 复制代码
/**
 * 多层继承:GrandFather -> Father -> Son
 */
class GrandFather {
    protected String familyName = "王";
    protected String bloodType = "A型";
    
    public GrandFather() {
        System.out.println("GrandFather构造");
    }
    
    public void work() {
        System.out.println("祖父在工作");
    }
    
    public void showGene() {
        System.out.println("家族姓氏: " + familyName + ", 血型: " + bloodType);
    }
}

class Father extends GrandFather {
    protected String car = "大众";
    
    public Father() {
        System.out.println("Father构造");
    }
    
    @Override
    public void work() {
        System.out.println("父亲在工作");
    }
    
    public void drive() {
        System.out.println("父亲开车: " + car);
    }
}

class Son extends Father {
    private String hobby = "编程";
    
    public Son() {
        System.out.println("Son构造");
    }
    
    @Override
    public void work() {
        System.out.println("儿子在工作");
    }
    
    public void code() {
        System.out.println("儿子爱好: " + hobby);
    }
    
    public void showAll() {
        System.out.println("家族姓氏: " + familyName);  // 来自祖父
        System.out.println("血型: " + bloodType);      // 来自祖父
        System.out.println("汽车: " + car);            // 来自父亲
        System.out.println("爱好: " + hobby);          // 自己的
    }
}

public class MultiLevelInheritance {
    public static void main(String[] args) {
        Son son = new Son();
        
        System.out.println("=== 调用各层方法 ===");
        son.work();           // 儿子重写的方法
        son.drive();          // 父亲的方法
        son.code();           // 自己的方法
        son.showGene();       // 祖父的方法
        son.showAll();        // 综合显示
        
        System.out.println("\n=== 构造顺序 ===");
        // 输出顺序:GrandFather构造 -> Father构造 -> Son构造
        // 构造时先调用父类构造器
    }
}

4. super关键字

java 复制代码
/**
 * super关键字的用法
 */
class Person {
    protected String name;
    protected int age;
    
    public Person() {
        this("未知", 0);
        System.out.println("Person无参构造");
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person有参构造: " + name + ", " + age);
    }
    
    public void display() {
        System.out.println("Person: " + name + ", " + age);
    }
    
    public void sayHello() {
        System.out.println("Person打招呼");
    }
}

class Student extends Person {
    private String school;
    private int grade;
    
    public Student() {
        // super();  // 隐含调用父类无参构造
        this("未知", 0, "未知学校", 0);
        System.out.println("Student无参构造");
    }
    
    public Student(String name, int age, String school, int grade) {
        super(name, age);  // 调用父类有参构造,必须在第一行
        this.school = school;
        this.grade = grade;
        System.out.println("Student有参构造");
    }
    
    @Override
    public void display() {
        super.display();  // 调用父类的display方法
        System.out.println("Student: " + school + ", " + grade + "年级");
    }
    
    @Override
    public void sayHello() {
        super.sayHello();  // 调用父类方法
        System.out.println("Student打招呼: 我是" + name);
    }
    
    public void testSuper() {
        // super可以访问父类的成员
        System.out.println(super.name);      // 访问父类字段
        super.display();                     // 调用父类方法
        // super()  // ❌ 只能在构造方法的第一行使用
    }
}

public class SuperKeyword {
    public static void main(String[] args) {
        System.out.println("=== 创建Student对象 ===");
        Student stu = new Student("张三", 18, "清华大学", 1);
        
        System.out.println("\n=== 调用display ===");
        stu.display();
        
        System.out.println("\n=== 调用sayHello ===");
        stu.sayHello();
    }
}

Java重写

重写是子类重新定义父类的方法,实现运行时多态

1. 重写的基本规则

java 复制代码
class ParentClass {
    // 1. 方法签名必须相同(方法名和参数列表)
    public void method1() {
        System.out.println("Parent method1");
    }
    
    // 2. 返回值类型:可以是父类返回类型的子类型(协变返回类型)
    public Object method2() {
        System.out.println("Parent method2");
        return new Object();
    }
    
    // 3. 访问修饰符:不能比父类更严格
    protected void method3() {
        System.out.println("Parent method3");
    }
    
    // 4. 异常声明:不能抛出比父类更宽泛的异常
    public void method4() throws Exception {
        System.out.println("Parent method4");
    }
}

class ChildClass extends ParentClass {
    @Override
    public void method1() {
        System.out.println("Child method1");
    }
    
    @Override
    public String method2() {  // String是Object的子类,协变返回类型
        System.out.println("Child method2");
        return "String返回值";
    }
    
    @Override
    public void method3() {  // 可以扩大访问权限(public > protected)
        System.out.println("Child method3");
    }
    
    @Override
    public void method4() throws IOException {  // IOException是Exception的子类
        System.out.println("Child method4");
    }
}

public class OverrideRules {
    public static void main(String[] args) {
        ParentClass pc = new ChildClass();
        pc.method1();  // 调用子类方法
        pc.method2();  // 调用子类方法
        pc.method3();  // 调用子类方法
    }
}

2. @Override注解

java 复制代码
class Base {
    public void show() {
        System.out.println("Base show");
    }
}

class Derived extends Base {
    @Override  // 可选但推荐,可以帮助编译器检查
    public void show() {
        System.out.println("Derived show");
    }
    
    // @Override  // ❌ 编译错误,这不是重写
    public void display() {
        System.out.println("Derived display");
    }
}

3.动态绑定(运行时多态)

java 复制代码
class Vehicle {
    public void start() {
        System.out.println("交通工具启动");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("汽车启动:点火、踩离合、挂挡");
    }
}

class Bicycle extends Vehicle {
    @Override
    public void start() {
        System.out.println("自行车启动:踩脚踏板");
    }
}

class Motorcycle extends Vehicle {
    @Override
    public void start() {
        System.out.println("摩托车启动:打火、加油门");
    }
}

public class DynamicBinding {
    public static void main(String[] args) {
        Vehicle v1 = new Car();
        Vehicle v2 = new Bicycle();
        Vehicle v3 = new Motorcycle();
        
        v1.start();  // 运行时调用Car的start
        v2.start();  // 运行时调用Bicycle的start
        v3.start();  // 运行时调用Motorcycle的start
        
        // 多态数组
        Vehicle[] vehicles = {new Car(), new Bicycle(), new Motorcycle()};
        for (Vehicle v : vehicles) {
            v.start();  // 动态绑定
        }
    }
}

Java重载

1. 重载的基本规则

重载是同一个类中定义多个同名但参数列表不同的方法;

java 复制代码
/**
 * 方法重载示例
 */
class Calculator {
    // 1. 参数个数不同
    public int add(int a, int b) {
        System.out.println("调用add(int, int)");
        return a + b;
    }
    
    public int add(int a, int b, int c) {
        System.out.println("调用add(int, int, int)");
        return a + b + c;
    }
    
    // 2. 参数类型不同
    public double add(double a, double b) {
        System.out.println("调用add(double, double)");
        return a + b;
    }
    
    // 3. 参数顺序不同
    public String add(String str, int num) {
        System.out.println("调用add(String, int)");
        return str + num;
    }
    
    public String add(int num, String str) {
        System.out.println("调用add(int, String)");
        return num + str;
    }
    
    // ❌ 以下不是重载(只有返回值类型不同)
    // public int add(int a, int b) { return a + b; }
    // public long add(int a, int b) { return (long)a + b; }
}

public class OverloadDemo {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        
        System.out.println(calc.add(5, 10));           // add(int, int)
        System.out.println(calc.add(5, 10, 15));       // add(int, int, int)
        System.out.println(calc.add(3.14, 2.86));      // add(double, double)
        System.out.println(calc.add("数字: ", 100));    // add(String, int)
        System.out.println(calc.add(200, " 是数字"));   // add(int, String)
    }
}

2. 重载的常见应用

java 复制代码
/**
 * 构造函数重载
 */
class StudentInfo {
    private String name;
    private int age;
    private String major;
    private double score;
    
    // 构造方法重载
    public StudentInfo() {
        this("未知", 0, "未定", 0.0);
    }
    
    public StudentInfo(String name) {
        this(name, 0, "未定", 0.0);
    }
    
    public StudentInfo(String name, int age) {
        this(name, age, "未定", 0.0);
    }
    
    public StudentInfo(String name, int age, String major) {
        this(name, age, major, 0.0);
    }
    
    public StudentInfo(String name, int age, String major, double score) {
        this.name = name;
        this.age = age;
        this.major = major;
        this.score = score;
    }
    
    public void display() {
        System.out.printf("姓名: %s, 年龄: %d, 专业: %s, 分数: %.1f\n", 
                         name, age, major, score);
    }
}

/**
 * 方法重载的实际应用
 */
class StringUtil {
    // 重载的反转方法
    public String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }
    
    public String reverse(String str, int start, int end) {
        char[] chars = str.toCharArray();
        for (int i = start, j = end; i < j; i++, j--) {
            char temp = chars[i];
            chars[i] = chars[j];
            chars[j] = temp;
        }
        return new String(chars);
    }
    
    // 重载的查找方法
    public int find(String str, char target) {
        return str.indexOf(target);
    }
    
    public int find(String str, String target) {
        return str.indexOf(target);
    }
    
    public int find(String str, char target, int fromIndex) {
        return str.indexOf(target, fromIndex);
    }
    
    // 重载的格式化方法
    public String format(String template, String... args) {
        String result = template;
        for (int i = 0; i < args.length; i++) {
            result = result.replace("{" + i + "}", args[i]);
        }
        return result;
    }
    
    public String format(String template, Object... args) {
        return String.format(template, args);
    }
}

public class OverloadApplications {
    public static void main(String[] args) {
        // 构造方法重载
        StudentInfo s1 = new StudentInfo();
        StudentInfo s2 = new StudentInfo("张三");
        StudentInfo s3 = new StudentInfo("李四", 20);
        StudentInfo s4 = new StudentInfo("王五", 21, "计算机");
        StudentInfo s5 = new StudentInfo("赵六", 22, "数学", 95.5);
        
        s1.display();
        s2.display();
        s3.display();
        s4.display();
        s5.display();
        
        // 方法重载
        StringUtil util = new StringUtil();
        System.out.println(util.reverse("Hello"));
        System.out.println(util.reverse("Hello World", 0, 4));
        System.out.println(util.find("Hello World", 'o'));
        System.out.println(util.find("Hello World", "World"));
        System.out.println(util.format("Hello {0}, welcome to {1}", "张三", "Java"));
    }
}

3. 重载的自动类型转换

java 复制代码
class TypeConversion {
    public void method(int a) {
        System.out.println("int: " + a);
    }
    
    public void method(long a) {
        System.out.println("long: " + a);
    }
    
    public void method(double a) {
        System.out.println("double: " + a);
    }
    
    public void method(Integer a) {
        System.out.println("Integer: " + a);
    }
    
    public void method(int... a) {
        System.out.println("可变参数: " + a.length);
    }
}

/**
 * 重载方法的匹配顺序
 * 1. 精确匹配
 * 2. 自动类型转换(向上转型)
 * 3. 装箱/拆箱
 * 4. 可变参数
 */
public class OverloadPriority {
    public static void main(String[] args) {
        TypeConversion tc = new TypeConversion();
        
        tc.method(10);           // 精确匹配 int
        tc.method((byte)10);     // 自动类型转换 byte -> int
        tc.method((short)10);    // 自动类型转换 short -> int
        tc.method(10L);          // 精确匹配 long(不是int转long)
        tc.method(10.0f);        // float -> double
        tc.method(10.0);         // 精确匹配 double
        tc.method(10);           // 装箱成Integer(如果没有int匹配)
        tc.method(10, 20);       // 可变参数
    }
}

四、重写 vs 重载对比

java 复制代码
/**
 * 重写 vs 重载对比示例
 */
class Parent {
    // 父类方法
    public void method(int a) {
        System.out.println("Parent method(int): " + a);
    }
    
    public void method(String s) {
        System.out.println("Parent method(String): " + s);
    }
    
    // 将被重写的方法
    public void show() {
        System.out.println("Parent show");
    }
    
    // 将被重写的方法(有返回值)
    public Object getValue() {
        return new Object();
    }
}

class Child extends Parent {
    // 重载:在子类中增加新方法
    public void method(String s, int a) {
        System.out.println("Child method(String, int): " + s + ", " + a);
    }
    
    // 重写:重新定义父类方法
    @Override
    public void show() {
        System.out.println("Child show");
    }
    
    // 重写:协变返回类型
    @Override
    public String getValue() {
        return "Child value";
    }
}

public class OverrideVsOverload {
    public static void main(String[] args) {
        Parent p = new Parent();
        Child c = new Child();
        Parent pc = new Child();  // 多态
        
        System.out.println("=== 重载 ===");
        p.method(10);           // 调用父类method(int)
        p.method("Hello");      // 调用父类method(String)
        c.method(20);           // 继承的method(int)
        c.method("World");      // 继承的method(String)
        c.method("Hi", 30);     // 子类新增的重载方法
        
        System.out.println("\n=== 重写 ===");
        p.show();               // 调用父类show
        c.show();               // 调用子类show
        pc.show();              // 多态调用子类show
        
        System.out.println("\n=== 协变返回类型 ===");
        System.out.println(p.getValue().getClass());  // Object
        System.out.println(c.getValue().getClass());  // String
        System.out.println(pc.getValue().getClass()); // String
    }
}
相关推荐
Java面试题总结1 小时前
使用 Python 设置 Excel 数据验证
开发语言·python·excel
【 】4231 小时前
C++&STL(Standard Template Library,标准模板库)
java·开发语言·c++
茉莉玫瑰花茶1 小时前
LangChain 核心组件 [ 2 ]
java·数据库·langchain
eastyuxiao1 小时前
OpenClaw 自动处理核心逻辑
开发语言·人工智能
小郑加油1 小时前
python学习Day10天:列表进阶 + 内置函数 + 代码简化
开发语言·python·学习
信徒_1 小时前
ID 生成技术选型
java
eastyuxiao1 小时前
影响 OpenClaw 自动处理效率的核心因素
开发语言·人工智能
a8a3022 小时前
Laravel8.x新特性全解析
java·spring boot·后端
啧不应该啊2 小时前
Day1 python与c宏观区别
c语言·开发语言