Java面向对象继承、代码块、final关键字详讲

一、代码块

1. 代码块概述

  • 什么是代码块
    在Java中,用一对{}括起来的代码就是代码块
  • 分类
    • 局部代码块
      在方法中出现,前面没有修饰符,用于限定变量的生命周期,提早释放变量,以提高内存的使用效率,变量的生命周期就是他所在的最近的外层{}中
    • 构造代码块
      在类中方法外,前面没有修饰符,作用是将多个构造方法中相同代码取出来放在一起,为多个构造方法所共有,每次执行构造方法的时候都会先执行构造代码块。简单来说,构造代码块就是用来修饰构造方法的,为每一个构造方法所共享,每一次调用构造方法时会先加载构造代码块,来对构造方法加以修饰
    • 静态代码块
      在类中方法外,前面必须加static修饰符,表示静态的。用来修饰类,在类加载的时候随着类的加载而加载,给类初始化

2. 看程序写结果

  1. 看下列程序,写出运行结果
    class Student {//学生类
        static {
            System.out.println("Student 静态代码块");
        }
    
        public Student() {
            System.out.println("Student 构造方法");
        }
    
        {
            System.out.println("Student 构造代码块");
        }
    }
    class StudentTest {//学生类的测试类
        static {
            System.out.println("StudentDemo 静态代码块");
        }
    
        public static void main(String[] args) {
            System.out.println("我是main方法");
    
            Student s1 = new Student();
            Student s2 = new Student();
        }
    }
    
  • 执行结果

    StudentDemo 静态代码块 //先加载测试类,执行测试类的静态代码块
    我是main方法       //然后进程序主入口main方法
    Student 静态代码块 //加载学生类,执行学生类的静态代码块
    Student 构造代码块 //当创建类对象s1时,先执行构造代码块
    Student 构造方法   //再执行构造方法
    Student 构造代码块 //当创建类对象s2时,先执行构造代码块
    Student 构造方法   //再执行构造方法
    

二、继承

1. 继承概述

  • 为什么要有继承
    当我们开发好一个类时,比如说我们已经开发了一个汽车类,里面有属性:大小、颜色等,功能有前进、后退等;这个时候又需要开发一个卡车和一个推土机,如果全部重新写一遍太过麻烦,这个时候我们只需要给汽车类添加一个大车厢或者添加一个大推兜就行了,大卡车或者推土机都有汽车类所具有的属性和功能,这时候就叫做卡车或者推土机继承了汽车类的成员
  • 继承概念
    继承是面向对象最显著的一个特征,是从已有的类中派生出新的类,新的类可以吸收父类的属性和方法,并且可以扩展出自己新的属性和方法
  • 格式
    通过extends关键字来实现继承
    class 子类名 extends 父类名 {}

2. 继承的利弊

  • 优点
    • 提高代码的复用性,降低开发的复杂性
    • 提高代码的维护性,改变父类成员,所有引用该父类的子类成员都将改变
    • 让类与类之间产生了联系,是多态的前提
  • 缺点
    • 让类的耦合度增强了(类与类之间的联系)
    • 开发的原则:高内聚、低耦合

3. Java中继承的特点

  • 只支持单继承
    即一个类最多只能有一个父类,不能有多个父类,单继承使得继承关系变得很简单,易于管理程序,同时一个类中可以实现多个接口,从而克服单继承的缺点
  • 支持多层继承
    即父类可以拥有自己的父类,子类也可以拥有自己的子类,但 object 类是所有类的源头

4. 继承的注意事项

  • 子类只能继承父类非私有的成员(不被private修饰的)
  • 子类不能继承父类的构造方法,但是可以通过super关键字来访问父类的构造方法
    super();
  • 不要为了部分功能而去继承,因为Java中是单继承,一个类只能有一个父类,所以非必须情况下,不要为了部分功能而去继承
  • 什么时候使用继承
    假设有两个类A、B,如果A、B满足A是B的一种,或B是A的一种的情况,就可以使用继承

5. 继承中成员变量的关系

  • 子类成员变量与父类成员变量名称不一致
    不影响,根据名称进行调用
  • 子类成员变量与父类成员变量名称一致时
    采用就近原则
    • 先在子类方法的局部变量里找,有就使用
    • 再在子类的局部变量里面找,有就使用
    • 最后在父类的局部变量里面找,有就使用
    • 如果都没有,提示错误

6. this关键字与super关键字

  • super 关键字
    • 如果在子类成员变量与父类成员变量名称一致,使用子类成员变量用this关键字,那使用父类成员变量呢?
    • 用super关键字
    • super关键字代表的父类的存储空间的标志,可以理解为父类的一个引用(对象),可以对父类的成员进行操作,比如super.成员变量; super.成员方法
  • this关键字与super关键字的区别
    • 调用成员变量
      • this关键字:调用本类成员变量
      • super关键字:调用父类成员变量
    • 调用构造方法
      • this关键字:调用本类的构造方法
      • super关键字:调用父类的构造方法
    • 调用成员方法
      • this关键字:调用本类的成员方法
      • super关键字:调用父类的成员方法

7. 继承中构造方法的关系

  • 父类中有无参构造
    • 子类中的所有的构造方法执行前都会默认访问父类的无参构造
    • 原因:因为子类继承了父类中的成员(成员变量和成员对象),子类在初始化后可能还要使用到父类中的成员,所以在子类初始化前必须先对父类进行初始化,以保证子类初始化时能加载到父类的成员
    • 注:其实子类的构造方法的第一条语句默认是super(); 即分类的无参构造,用来初始化父类的成员
  • 父类中没有无参构造
    • 在父类中手动添加一个无参构造
    • 通过super关键字调用父类其他的有参构造,只要是构造函数,能对父类的成员进行初始化就行
    • 通过this关键字调用子类其他构造方法,前提是这个构造方法已经访问过父类,即有父类初始化的成员数据,也可以

8. 举例

  • 1)读程序分析结果

    class Fu {//父类
        public int num = 10;
    
        public Fu() {
            System.out.println("fu");
        }
    }
    
    class Zi extends Fu {//子类
        public int num = 20;
    
        public Zi() {
            System.out.println("zi");
        }
    
        public void show() {
            int num = 30;
            System.out.println(num);
            System.out.println(this.num);
            System.out.println(super.num);
        }
    }
    
    class Test {//测试类
        public static void main(String[] args) {
            Zi z = new Zi();
            z.show();
        }
    }
    
  • 运行结果

    fu     //先访问父类的构造方法,对父类成员初始化
    zi     //再访问子类的构造方法
    30     //输出子类局部变量
    20     //输出子类成员变量
    10     //输出父类成员变量
    
  • 2)读程序分析结果

    class Fu {//父类
        static {
            System.out.println("静态代码块Fu");
        }
    
        {
            System.out.println("构造代码块Fu");
        }
    
        public Fu() {
            System.out.println("构造方法Fu");
        }
    }
    
    class Zi extends Fu {//子类
        static {
            System.out.println("静态代码块Zi");
        }
    
        {
            System.out.println("构造代码块Zi");
        }
    
        public Zi() {
            System.out.println("构造方法Zi");
        }
    }
    
    class Test {//测试类
        public static void main(String[] args) {
            Zi z = new Zi();
        }
    }
    
  • 运行结果

    静态代码块Fu  //先加载父类进方法区,父类中静态的成员随着父类的加载而加载
    静态代码块Zi  //再加载子类进方法区,子类静态的成员随着子类的加载而加载
    构造代码块Fu  //先访问父类的构造方法,先执行构造代码块
    构造方法Fu    //再执行构造方法
    构造代码块Zi  //后访问子类的构造方法,先执行构造代码块
    构造方法Zi    //再执行构造方法
    

三、final 关键字

1. final 关键字概述

  • 为什么有final关键字
    由于在继承中子类可以重写父类的方法,但有时候我们想将某个方法设置为父类所独有的,不想被子类所重写,这个时候就可以用到final关键字
  • final关键字含义
    final从字面上理解是最终的意思,可以用来修饰类、成员变量、成员方法

2. final 关键字特点

  • 修饰类
    被修饰的类将不能被继承
  • 修饰方法
    被修饰的方法将不能被重写
  • 修饰变量
    这个变量将不能重新赋值,即这个变量其实成了一个常量
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值