【Java SE】继承(2)

【Java SE】继承:代码复用与扩展的艺术-CSDN博客文章浏览阅读389次,点赞16次,收藏12次。摘要:继承是面向对象编程的核心特性,允许子类复用父类的属性和方法并扩展新功能。子类通过extends继承父类,可访问父类成员(同名时遵循就近原则),使用super关键字可调用父类同名成员。继承体现了代码复用和层次化设计,子类必须添加特有功能以区别于父类。语法上需注意成员访问优先顺序(子类优先)和super的使用限制(仅非静态方法)。通过继承关系可构建更复杂的类层次结构。https://blog.csdn.net/Boop_wu/article/details/148700233


 1.5子类构造方法

子类构造对象时,需要先调用父类构造方法,然后执行子类的构造方法

实例:

public class Test {
    public static void main(String[] args) {
        Derived d = new Derived();
    }
}
public class Base {
    public Base(){
        System.out.println("Base()");
    }
}
public class Derived extends Base {
    public Derived(){
        //super();
        System.out.println("Derived()");
    }
}

【Java SE】继承(2)_第1张图片

在子类构造方法中,并没有写任何关于父类构造的代码,但是在构造子类对象是,先执行父类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,父类继承下来的以及新增的部分。在构造对象时,要先调用父类的构造方法,将从父类继承下来的成员构造完整,然后再调用子类的构造方法,将子类自己新增的成员初始化完整。

注意

  • 若父类显示定义无参或者默认的构造方法,再子类构造方法第一行默认隐含super()调用,即调用积累构造方法。
  • 若父类构造方法时带有参数的,此时需要用户为子类显示定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
  • 在子类构造方法中,super()调用父类构造时,必须时子类构造函数中的第一条语句。
  • super()只能在子类构造方法中出现一次,并且不能和this同时出现


1.6 super和this 

相同点

①都是java中的关键字

②只能在类的非静态方法中使用,用来访问非静态成员方法和字段

③在构造方法中调用,必须是构造方法中的第一条语句,并且不能同时存在

不同点

①this 是当前对象的引用,当前对象即调用实例方法;super 相当于是子类对象中从父类继承下来部分成员的引用

②在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性

③在构造方法中:this(....)用于调用本类构造方法,super(...)用于调用父类的构造方法,两种调用不能同时在构造方法中出现

④构造方法中一定会存在super(..)调用,用户没有写编译器也会增加,但是this(..)用户不写就没有。


1.7.1 在没有继承关系的执行顺序:

①静态代码块先执行,并且在类加载阶段只执行一次

②当有对象创建时,才会执行实例代码块,再执行构造代码块

1.7.2 有继承关系的执行顺序

①父类静态代码块优先与子类静态代码块执行,并且是最早的

②父类实例代码块和父类构造方法紧接着执行

③子类的实例代码块和子类构造方法紧接着再执行

④第二次实例化对象时,父类和子类的静态代码块都不会再执行


1.8 protected关键字

作用:protected成员可以被同一包内的其他类访问,也可以被不同包中的子类访问。

实例如下:

【Java SE】继承(2)_第2张图片

package d1;

public class B {
    private int a;
    protected int b;
    int c;
    public int d;

}
package d1;

public class D extends B{
    public void method(){
        //super.a = 10;
        super.b = 20;
        super.c = 30;
        super.d = 40;
    }
}
package d2;

import d1.B;

public class C extends B {
    public void method(){
        //super.a = 10;
        super.b = 20;
        //super.c = 30;
        super.d = 40;
    }
}

【Java SE】继承(2)_第3张图片

【Java SE】继承(2)_第4张图片


1.9 .1Java继承的基本概念

Java通过extends关键字实现单继承,即一个子类只能直接继承一个父类。继承允许子类复用父类的属性和方法,并可以扩展或修改父类的行为。

  • 语法示例
    class ParentClass {
        // 父类成员
    }
    class ChildClass extends ParentClass {
        // 子类成员
    }
    

1.9.2继承的类型

①单继承
Java不支持多继承(一个子类继承多个父类),但可以通过接口(implements)实现多重继承的效果。

②多层继承
子类可以进一步被其他类继承,形成继承链。

class Grandparent {}
class Parent extends Grandparent {}
class Child extends Parent {}

③方法重写(Override)
子类可以重写父类的方法,使用@Override注解确保逻辑正确。

class Parent {
    void display() {
        System.out.println("Parent method");
    }
}
class Child extends Parent {
    @Override
    void display() {
        System.out.println("Child method");
    }
}

1.9.3继承中的访问控制

  • protected成员:子类可以访问父类的protected成员。
  • private成员:子类无法直接访问父类的private成员,需通过公有方法间接访问。


1.10.1final关键字的基本概念

在Java中,final关键字用于修饰变量、方法或类,表示不可更改的语义。具体作用取决于修饰的目标:

  • 变量:一旦赋值后不能重新赋值。
  • 方法:不能被子类重写。
  • :不能被继承。

1.10.2final修饰变量

①基本类型变量:值不可修改。

final int x = 10;  
// x = 20; // 编译错误,无法重新赋值  

②引用类型变量:引用地址不可变,但对象内部状态可能可变。

final List list = new ArrayList<>();  
list.add("A"); // 允许修改对象内容  
// list = new ArrayList<>(); // 编译错误,引用不可变  

类成员变量:必须在声明时或构造方法中初始化。

1.10.3 final修饰方法

子类不能重写final方法,但可以继承调用。

class Parent {  
    final void display() { System.out.println("Parent"); }  
}  
class Child extends Parent {  
    // void display() { } // 编译错误,无法重写  
}  

1.10.4 final修饰类

final类不能被继承,例如String类。

final class MyClass { }  
// class SubClass extends MyClass { } // 编译错误  

1.10.5final与不变性

final仅保证引用或基本值不变,但若对象内部状态可变(如final List),需结合其他机制(如防御性拷贝)实现完整不可变性。

通过合理使用final,可以增强代码的安全性、清晰性和可维护性。


1.11.1继承与组合的概念

继承(Inheritance)是面向对象编程中的一种机制,允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以复用父类的代码,同时扩展或修改父类的行为。

组合(Composition)是一种设计模式,通过将一个类的对象作为另一个类的成员变量来实现代码复用。组合强调“拥有”关系,而非“是”关系。

1.11.2继承的特点

  • 优点
    代码复用性强,子类可以直接使用父类的属性和方法。
    支持多态,父类引用可以指向子类对象。
    适合表示“is-a”关系(如“Dog is an Animal”)。

  • 缺点
    破坏封装性,子类依赖父类的实现细节。
    父类变更可能影响所有子类。
    Java不支持多继承,可能限制灵活性。

// 继承示例
class Animal {
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog is barking");
    }
}

1.11.3组合的特点

  • 优点
    灵活性高,可以动态替换成员对象。
    降低耦合,类之间通过接口交互。
    适合表示“has-a”关系(如“Car has an Engine”)。

  • 缺点
    需要手动实现部分功能,代码量可能增加。
    无法直接利用多态特性。

// 组合示例
class Engine {
    void start() {
        System.out.println("Engine started");
    }
}

class Car {
    private Engine engine;

    Car(Engine engine) {
        this.engine = engine;
    }

    void start() {
        engine.start();
    }
}

1.11.4选择继承还是组合?

①优先使用组合
符合“组合优于继承”的设计原则,尤其是当关系为“has-a”时。
需要动态改变行为时(如通过setter方法替换成员对象)。

②使用继承的场景
关系明确为“is-a”且逻辑高度一致。
需要利用多态或重写父类方法。

总结:继承和组合各有适用场景。组合通常更灵活且易于维护,适合模块化设计;继承适合建立清晰的层级关系和多态需求。实际开发中应结合具体需求选择。


你可能感兴趣的:(java,开发语言)