Java——继承详解、super 关键字、super和this的异同、protected关键字、final关键字、继承与组合

1、继承的概念:

继承主要解决的问题:共性的抽取,实现代码复用

可以让我们在保持原有类(父类、超类、基类)特性的基础上进行扩展,增加新功能,这样产生新的类,称为派生类(子类)

2、继承的语法:

  • Java中表示类之间的继承关系,要用到 extends 关键字
  • 子类会将父类中的成员变量或成员方法继承到子类中
  • 子类继承父类后,必须要新添加自己特有的成员

3、父类成员访问

3.1 子类访问父类中的成员变量

1、子类和父类中不存在同名成员变量

public class Base {
    int a;
    int b;
}

public class Derived extends Base{
    int c;
    public void method(){
        a = 10;//访问从父类中继承下来的a
        b = 20;//访问从父类中继承下来的b
        c = 30;//访问子类自己的c
    }
}

2、子类和父类中存在同名成员变量

public class Base {
    int a;
    int b;
}


public class Derived extends Base{
    int a;//与父类中成员a同名,且类型相同
    char b;//与父类中成员b同名,但类型不同
    int c;
    public void method(){
        a = 55;
        b = 66;
        c = 77;
        //d = 40;error

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
    public static void main(String[] args) {
        Derived d = new Derived();
        d.method();
    }
}

结果:

分析:

  • 如果访问的成员变量子类中有,优先访问自己的成员变量,遵循就近原则
  • 如果访问的成员变量子类中没有,则访问父类继承下来的,若父类中也没有定义,则编译报错
  • 若个访问的成员变量与父类中成员变量同名,则优先访问自己的

3.2 子类访问父类的成员方法

  • 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找不到就在父类中找,都找不到则编译报错
  • 通过子类对象访问父类与子类中同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法所传递的参数选择合适的方法访问,没有则报错
  • 想要通过子类对象访问父类与子类中同名的方法,且参数列表也相同时,需用到关键字 super

 4、super 关键字

作用:在子类方法中访问父类的成员

示例:

public class Base {
    int a;
    int b;

    public void methodA(){
        System.out.println("methodA()::Base");
    }
    public void methodB(){
        System.out.println("methodB()::Base");
    }
}


public class Derived extends Base{
    int a;//与父类中成员a同名,且类型相同
    char b;//与父类中成员b同名,但类型不同
    int c;

    //与父类methodA()构成重载
    public void methodA(int x){
        System.out.println("methodA()::Derived");
    }

    //与父类methodB()构成重写
    public void methodB(){
        System.out.println("methodB()::Derived");
    }

    public void method(){
        a = 55;
        super.b = 66;//访问父类与子类同名成员变量用super
        c = 77;
    //父类与子类中构成重载的方法,通过参数列表区分访问
        methodA();
        methodA(c);

    //父类与子类中构成重写的方法,需借助super访问父类方法
        methodB();
        super.methodB();

        System.out.println(a);
        //访问父类与子类同名成员变量用super
        System.out.println(super.b);
        System.out.println(c);
    }
    public static void main(String[] args) {
        Derived d = new Derived();
        d.method();
    }
}

结果:

tips:

  • super关键字只能在非静态方法中使用
  • 使用 super() 必须在第一行,与 this() 不共存
  • super只能指代当前类的父类,不能指代父类的父类

 5、子类构造方法

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

示例:

public class Animal {

    static{
        System.out.println("static::Animal{ }");
    }

    {
        System.out.println("实例代码块::Animal{ }");
    }

    public Animal() {
        System.out.println("构造方法::Animal()...");
    }
}

//==================================

public class Dog extends Animal{
    static{
        System.out.println("static::Dog{ }");
    }

    {
        System.out.println("实例代码块::Dog{ }");
    }

    public Dog() {
        System.out.println("构造方法::Dog()...");
    }
}

//==================================

public class Cat extends Animal{
    static{
        System.out.println("static::Cat{ }");
    }

    {
        System.out.println("实例代码块::Cat{ }");
    }

    public Cat() {
        System.out.println("构造方法::Cat()...");
    }
}

//==================================

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

结果:

原理:子类对象中成员是由两部分组成的,父类继承的部分以及子类新增的部分,先有父再有子,所以在构造子类对象时,先调用父类构造,将继承下来的成员构造完整,再调用子类的构造,将新增成员初始化完整。

tips:

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

结论

  • 父类静态代码块优先于子类静态代码块执行,且最早执行
  • 父类实例代码块和父类构造方法紧接着执行
  • 子类实例代码块和子类构造方法紧接着执行
  • 第二次实例化子类对象时,父类和子类的静态代码块都不会再执行

6、super和this的异同

相同点:

  • 都是Java关键字
  • 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  • 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

不同点:

  • this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
  • 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  • 在构造方法中,this(...) 用于调用本类构造方法,super(...) 用于调用父类构造方法,两种调用不能同时在构造方法中出现
  • 构造方法中一定会存在super(...) 的调用,用户没有写编译器也会加,但是this(...) 不写则没有

 7、protected关键字

用protected修饰的成员变量不能在 不同包中的非子类 访问

虽然不能直接访问,但是也继承到子类了

8、Java中的继承方式

如图:

tips:

Java中不支持多继承

在应用场景中,尽量不要出现超过三层的继承关系

想要在语法上进行限制,可以使用final关键字,用final修饰的类无法被继承

9、final关键字

final关键字可以用来修饰变量、成员方法以及类

  • 1.修饰变量或字段,表示常量,即不能修改
  • 2.修饰类,表示此类不能被继承
  • 3.修饰方法,表示该方法不能被重写

10、继承与组合

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物

组合表示对象之间是has-a的关系,比如:汽车的零件有轮胎、发动机、方向盘等等

//轮胎类
class Tire {
    //...
}


//发动机类
class Engine {
    //...
}


//组合:轮胎、发动机都是汽车的组成部分
class Car {
    private Tire tire;//可以复用轮胎类中的属性和方法
    public Engine engine;//可以复用发动机类中的属性和方法
}


//继承:奔驰属于汽车中的一类
class Benz extends Car{
    //将汽车中包含的轮胎、发动机全部继承下来
}

优缺点对比:

tips:

  • 组合比继承更符合 高内聚低耦合 的状态 
  • 所以在面向对象中有『多用组合、少用继承』或者说『组合优于继承』的观点
  • 在同样可行的情况下,建议使用组合
  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值