面向对象——继承

代码块

概述

代码块是指由一对大括号 {} 包围的代码段。根据代码块所在的位置和用途不同,它们在程序中的执行时机和作用也有所不同。常见的代码块类型包括:

  1. 局部代码块
  2. 构造代码块
  3. 静态代码块
  4. 同步代码块(多线程)
局部代码块
  • 格式:由一对大括号 {} 包围的代码段。

  • 位置:位于方法内部。

  • 作用

    • 限定变量的生命周期,其作用域仅限于代码块内部。
    • 在局部代码块中声明的变量,只能在该代码块内使用,出了代码块就无法访问。
    • 当变量的作用范围结束后,内存会被释放,节省空间。
  • 注意事项

    • 局部代码块声明的变量,生命周期较短,一旦超出作用范围就无法访问。
    • 局部代码块内可以修改外部变量,修改后的值在代码块结束后依然生效。

代码示例

public static void main(String[] args) {
    int i = 10;
    {
        System.out.println(i); // 输出: 10
        i = 20;
        int j = 100;
        System.out.println(j); // 输出: 100
    }
    System.out.println(i); // 输出: 20
    // System.out.println(j); // 编译错误:无法访问局部代码块中的变量 j
}
构造代码块
  • 格式:由一对大括号 {} 包围的代码段。

  • 位置:位于类中方法之外。

  • 作用:用于初始化成员变量。

  • 执行顺序

    1. 在创建对象时执行,由 JVM 自动调用。
    2. 在构造方法执行之前执行。
    3. 每次调用构造方法前都会执行一次。
    4. 如果多个构造方法中有公共的初始化逻辑,可以提取到构造代码块中。
静态代码块【常用】
  • 格式

    static {
        // 静态代码块的内容
    }
    
  • 位置:位于类中方法之外。

  • 作用

    • 用于初始化静态成员变量。
    • 适合执行只需要执行一次的代码,如驱动加载。
  • 执行特点

    1. 随着类的加载而执行。
    2. 类只加载一次,静态代码块只执行一次。
    3. 执行时机早于对象实例化和 main 方法的执行。

继承

继承的概述
  • 概念:继承是面向对象编程中子类继承父类属性和方法的机制,使得类与类之间产生继承关系。
  • 关键字extends,表示扩展和继承。
  • 父类和子类
    • 父类:被继承的类,称为超类或基类。
    • 子类:继承父类的类,称为派生类。

代码示例

  • 未使用继承

    // 示例代码省略
    
  • 使用继承

    // 示例代码省略
    
继承的优缺点
  • 优点

    1. 提高代码的复用性。
    2. 提高代码的可维护性。
    3. 是实现多态的基础。
  • 缺点

    1. 提高了代码的耦合性。
  • 开发原则

    • 高内聚:一个对象应尽可能完成自身的所有任务。
    • 低耦合:减少与其他代码的依赖,提高代码的独立性。
继承的注意事项
  1. 私有成员不能被继承。
    • 父类中的私有成员在子类中无法直接访问。
  2. 构造方法不能被继承。
    • 因为构造方法与类名绑定,不同类名的构造方法不兼容。
  3. 继承设计时应避免仅为部分功能定义继承关系。
继承中成员变量的关系
  1. 子类和父类中定义不同名称的成员变量时,子类可以访问两者。
  2. 子类和父类中定义同名成员变量时,访问遵循就近原则。

代码示例

public class Test01 {
    public static void main(String[] args) {
        Fu f = new Fu();
        System.out.println(f.a); // 输出: 10

        Zi z = new Zi();
        System.out.println(z.a); // 输出: 100
        System.out.println(z.b); // 输出: 20
        z.test();
    }
}

class Fu {
    int a = 10;
    int c = 10;
}

class Zi extends Fu {
    int b = 20;
    int a = 100;

    public void test() {
        System.out.println(a); // 输出: 100
    }

    public void test2() {
        System.out.println(c); // 输出: 10
    }
}

关键字 thissuper 的详细解释

  • this:表示当前对象的引用。
  • super:表示当前对象父类的引用。
thissuper 的使用总结
  1. this 表示当前对象的引用。哪个对象调用了方法,this 就指向哪个对象。
  2. super 表示当前对象的父类引用。哪个对象调用了方法,super 就指向该对象的父类部分。

继承中构造方法的关系

  1. 在初始化子类数据之前,必须先完成父类数据的初始化。
  2. 如果子类构造方法中没有显式调用父类或本类的其他构造方法,系统会默认调用父类的无参构造方法。
  3. 如果手动调用父类或本类构造方法,系统不会再自动添加构造方法调用。
  4. 构造方法不能递归调用。
总结
  1. 子类构造方法必须首先调用父类构造方法。
  2. thissuper 语句必须在构造方法的第一行,不能同时存在。
  3. thissuper 不能在非构造方法的非静态成员方法中使用。

方法重写

  1. 子类可以直接调用父类的方法,也可以重写父类的方法。
  2. 重写发生在子类和父类中有同名方法的情况下,子类可以改变父类方法的实现。
  3. 方法重载与重写的区别:
    • 重载:同一个类中方法名相同,参数列表不同。
    • 重写:子类与父类中方法名相同,参数列表相同。
重写的注意事项
  1. 私有方法不能被重写。
  2. 方法在重写时,访问权限不能变得更小。

Java 中继承的特点

  1. 单继承:Java 支持单继承,不支持多继承,但支持多层继承。
  2. 多层继承:通过逐层继承,子类可以继承多个祖先类的属性和方法。

final 关键字

  1. final 表示不可更改的含义。
  2. final 可修饰类、方法、变量。
  3. 修饰类:表示该类不能被继承。
  4. 修饰方法:表示该方法不能被重写。
  5. 修饰变量:表示变量为常量,只能赋值一次。

final 关键字的详细解析

final 关键字在 Java 中有多种应用场景,通过修饰类、方法、或变量,final 能够限制继承、重写或重新赋值,从而增强代码的稳定性和安全性。

1. final 修饰类

当一个类被 final 修饰时,表示该类不能被继承。也就是说,没有其他类能够从这个类派生出子类。

特点

  • 这种设计通常用于保证类的实现不会被改变,常用于工具类或关键的业务类。

代码示例

public final class UtilityClass {
    public static void doSomething() {
        System.out.println("Doing something...");
    }
}
  • 上述代码中,UtilityClass 类被 final 修饰,因此无法被继承。
2. final 修饰方法

当一个方法被 final 修饰时,表示该方法不能被子类重写。

特点

  • 这种设计用于保护方法的实现,防止子类改变方法的行为,确保父类的逻辑一致性。

代码示例

class Parent {
    public final void show() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // 下面的代码将会报错,因为父类的 show() 方法是 final 类型,无法被重写
    // public void show() {
    //     System.out.println("Trying to override the final method.");
    // }
}
  • 上述代码中,show 方法在父类 Parent 中被 final 修饰,因此子类 Child 无法重写它。
3. final 修饰变量

final 关键字也可以用来修饰变量。修饰后的变量称为常量,只能被赋值一次,且在赋值之后不可再更改。

特点

  • 常用于定义常量值,以确保变量的值在程序运行过程中不会被改变。

代码示例

public class Constants {
    public static final double PI = 3.14159;

    public static void main(String[] args) {
        // PI = 3.15; // 编译错误,final 变量不能被重新赋值
        System.out.println("The value of PI is: " + PI);
    }
}
  • 上述代码中,PI 是一个 final 变量,因此在赋值后不能被修改。
4. final 修饰引用类型

final 修饰的是一个引用类型(例如对象、数组等),表示引用本身不可更改,也就是该引用变量在被赋值之后不能再指向其他对象。但引用所指向的对象的内部状态是可以改变的。

代码示例

public class FinalReferenceExample {
    public static void main(String[] args) {
        final int[] numbers = {1, 2, 3};
        numbers[0] = 10; // 允许:可以修改数组的内容
        // numbers = new int[]{4, 5, 6}; // 编译错误:不能更改 final 引用的指向
        for (int num : numbers) {
            System.out.println(num);
        }
    }
}
  • 上述代码中,numbers 数组引用是 final 类型,因此无法指向其他数组,但可以修改其内容。

final 关键字的使用场景

  1. 定义常量

    • final 常用于定义不可修改的常量,通常与 static 一起使用。

    代码示例

    public static final String COMPANY_NAME = "OpenAI";
    
  2. 防止类被继承

    • 当一个类不希望被其他类继承时,可以将其声明为 final
  3. 确保方法不被重写

    • 在一些重要或核心的方法上使用 final,防止子类破坏父类的逻辑。
  4. 确保变量只赋值一次

    • 在某些情况下,为确保变量不会被意外修改,可以使用 final 来限制其只能被赋值一次。

final 和不变性

通过结合 final 关键字和适当的设计模式,可以创建不可变类,即一旦创建,其状态就无法改变的对象。不可变类在多线程环境中尤其有用,因为它们本质上是线程安全的。

代码示例

public final class ImmutableClass {
    private final String name;
    private final int age;

    public ImmutableClass(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
  • 上述代码中,ImmutableClass 类是不可变的,因为它的状态在对象创建后无法改变。所有成员变量都是 final,并且没有提供修改它们的方法。

结论

final 关键字在 Java 编程中非常重要,通过合理使用 final,可以有效地控制类的继承、方法的重写以及变量的赋值,从而增强代码的稳定性、可读性和安全性。在开发过程中,理解并适当地应用 final,是编写高质量代码的关键步骤之一。

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值