继承

  1. 继承是是什么?

android 14 修改状态栏网络信号格和wifi图标_java


  1. 生物学中的界门纲目科属种就是继承关系,也是包含的关系,继承就是被包含,例如,草食动物继承了所有动物的特性例如:吃喝拉撒。
    在代码中的体现就是,学生类和老师类都属于人类,所以我们可以讲学生类和老师类继承人这个大类,java中只有单继承没有多个类,不能继承多个类,但是可以连着继承,例如学生类继承人类,人类继承生物类
    继承的好处是:提升代码的复用性,继承是多态的前提(使类与类之间产生了关系)

编写生物类:变量:姓名和年龄,方法:吃饭睡觉

//生物类
public class LivingThings {
    String name;
    int age;
    public void eat() {
        System.out.println("吃饭");
    }
    public void sleep() {
        System.out.println("睡觉");
    }
}

人类:继承生物,但是比生物多的方法:会说话

public class Human extends LivingThings {
    public void speak() {
        System.out.println("说人话");
    }
}

老师类:除了会说话,变量多了个工资,方法多了会讲课

public class Teacher extends Human {
    int salary;
    public void teach() {
        System.out.println("讲java");
    }
}

学生类:继承人类,除了人类有的属性还有独特的方法:写作业

public class Student extends Human {
    public void writeHomework(){
        System.out.println("写作业");
    }
}

使用main函数调用学生类,可以访问到生物类,人类,还有本类所有的方法

android 14 修改状态栏网络信号格和wifi图标_java-ee_02

  1. 了解完继承的含义接下来来了解其中的奥秘吧
    从一个简单的继承来看,就是父与子两个类,

父类代码:定义了私有的变量(get&set方法)和普通变量,还有父类专属的方法,以及无参构造方法中加入了输出语句。

public class Fu {
    private int num = 10;
    int numA = 100;
    public Fu() {
        System.out.println("父类的无参构造方法");
    }
    public void show() {
    }
    public void showA() {
        System.out.println("父类中的showA方法");
    }
    public void showB() {
        System.out.println("父类中的showB方法");
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
}

子类代码:继承了父类,与父同名的变量名,无参构造方法中也加入了输出语句,

public class Zi extends Fu{
    int numA = 1000;
    int numC = 6666;
    public Zi1() {
        System.out.println("子类构造方法");
    }
    public void showA() {
        System.out.println("子类中的showA方法");
    }
    public void showC() {
        System.out.println("子类中的showC方法");
    }

那么在main方法中调用子类的时候会输出什么呢?

public static void main(String[] args) {
        Zi1 zi = new Zi1();
        int numA = zi.numA;
        System.out.println(numA);
        int num = zi.getNum();
        System.out.println(num);
    }

解析:继承中有个原则:就近原则,当需要访问变量或者方法时,会先查询子类有无其定义,若有则将其赋值为子类中的定义,若没有则向上查询,父类有则直接使用,如果没有就报编译异常。
当new新的子类时,如果其有父类,会先调用其无参的构造方法,再调用本类的构造方法可以将子类构造方法看成如下代码:

public Zi() {
        super();
        System.out.println("子类的无参构造方法");

输出:

android 14 修改状态栏网络信号格和wifi图标_开发语言_03

  1. this关键字和super关键字用法一样就写一起了
    this关键字最常用的地方就是在get&set方法中,其总共有三种使用方法:

this关键字的使用

  1. 就近原则
    变量在使用的时候,优先使用定义的近的变量,谁离得近就指向哪个变量
  2. this作用
    表示存储“当前对象”的引用
    this指向的内容,可以理解为访问本类中的内容。
  3. 三种格式
    this.成员变量 访问本类成员变量
    this.成员方法名() 访问本类成员方法
    this(…) 访问本类构造方法
    我们定义一个类,里面有无参构造方法和全参构造方法,再提供一个其他方法来讲解this关键字。

super关键字的使用

  1. super作用
    表示“父类”的引用
    super指向的内容,可以理解为访问父类中的内容。
  2. 三种格式
    super.成员变量 访问父类成员变量
    super.成员方法名(…) 访问父类成员方法
    super(…) 访问父类构造方法
public class Zi {
    int num = 666;
    public Zi() {
        this(6666);//要写在首行 其意思就是先访问其全参构造方法,将6666赋值到this.num中
        System.out.println("子类的无参构造方法");
    }
    public Zi(int num) {
        System.out.println("子类的有参构造");
        this.num = num;
    }
    public void method() {
        System.out.println("子类中的method方法");
    }
    public void show() {
        int num = 999;
        System.out.println("访问局部的num:" + num);
        System.out.println("访问本类成员位置的num:" + this.num);
        //访问本类的成员方法
        method();
        this.method();//一般不用加
    }
}

输出:

android 14 修改状态栏网络信号格和wifi图标_System_04

  1. 继承体系的内存图 涉及知识点:jvm

android 14 修改状态栏网络信号格和wifi图标_java_05



  1. 在此之间,我们先了解简单的jvm知识,我们会有问题,栈内存是干嘛的?堆内存又是什么?方法区是啥?
    在我们访问一个对象时,JAVA虚拟机内部是通过栈上的reference数据来操作堆上的具体对象,同时方法区又存储着这个对象的类型数据即对象所属的类的信息。JAVA虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位、去找到对象所在堆中的具体位置,所以对象的方法方法是取决于虚拟机实现而定的。
  1. 栈:每个线程都会有一个栈内存,由栈帧组成栈,一个栈帧等于一次方法的调用,我们用一个很简单的代码来演示栈的压栈和出栈
public class Demo4 {
   public static void main(String[] args) {
      a();//在这里设置断点
   }
   public static void a(){
      b();
   }
   public static void b(){}
}

当我们将断点设在main方法函数中,用debug运行,我们很容易看出压栈和出栈的过程

android 14 修改状态栏网络信号格和wifi图标_java_06


android 14 修改状态栏网络信号格和wifi图标_System_07


下图可以看出来,main方法a方法b方法都已经入栈了,main方法在栈底,栈是先进后出的一种数据结构

android 14 修改状态栏网络信号格和wifi图标_System_08


b方法执行完就进行出栈操作

android 14 修改状态栏网络信号格和wifi图标_开发语言_09


将所有方法出栈后结束程序,另外补充一个知识点:垃圾回收不涉及栈内存,因为栈内的是一次性的方法调用,每次调用后,都会被弹出栈,会自动回收,垃圾回收是回收堆内存中的无用对象

堆和方法区后续补充。。。

  1. 抽象方法的使用
    当我们写动物类之后,在写猫类和狗类的时候,我们我们可以将其继承动物类,在猫类和狗类中补充他们的叫声,但是他们还是有很多不同的,我们有时候怕忘记在具体类中写在这里插入代码片他们的不同时会采用抽象方法先定义出他们会叫,至于怎么叫在子类中实现,不实现就会报编译错误,所以不怕忘记写
    我们先编写动物类(为了简化代码,就写了他们的不同)他们吃的东西不同
public abstract class Animal {
  public abstract void eat();
}

猫类(猫吃鱼)

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

编写狗类

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

我们的main方法如下:

public static void main(String[] args) {
        Cat c = new Cat();
        c.eat();
        Dog d = new Dog();
        d.eat();
    }

注意事项:
1.抽象类只能通过子类创建对象。
2.抽象类可以有构造器,供子类初始化父类成员。
3.抽象类中,不一定包含抽象方法。
4.抽象类的子类,必须重写抽象父类中"所有的"抽象方法,否则子类也必须定义成抽象类
5.抽象类存在的意义是为了被子类继承,体现的是模板思想。

  1. 最后来介绍final类
    概述
    1.作用
    Java提供了final 关键字,用于修饰不可改变内容。
    2.应用
    修饰类:被修饰的类,不能被继承(例如:String类、Math类、Scanner类…)。
    修饰方法:被修饰的方法,不能被重写。
    修饰变量:被修饰的变量,一旦赋值,不能被重新赋值。
    final的使用
    1.修饰类:
    格式:public final public class 类名 { //类中成员 }
    2.修饰方法:
    格式:public final 返回值类型 方法名(){}
    3.修饰变量
    格式:final 数据类型 变量名=值; 或 final 数据类型 变量名; 变量名=值;
    注意事项:
    被final修饰的常量,被称为自定义常量(所有字母都大写)。
    修饰的如果是成员变量,可以不直接赋值,但需要保证所有构造方法有赋值操作