天天看点

JavaSE——继承、super关键字、方法重写、final关键字、多态

继承

  • 概述

    多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

  • 格式

    通过extends关键字可以实现类与类的继承

    class 子类名 extends 父类名 { }

    单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类

    eg:父类:

public class Animal {
    public String name;
    public String age;

    public void eat() {
        System.out.println("吃饭饭");
    }

    public void sleep() {
        System.out.println("睡觉觉");
    }


}
           

子类:(猫是动物的一种,有基础共同点)

public class Cat extends Animal{

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}
           

测试类:

public class MyTest {
    public static void main(String[] args) {
      Cat cat = new Cat();
        cat.name="小白";
        cat.age="2";
        cat.eat();  //继承了父类Animal的eat方法
        cat.sleep(); //继承了父类Animal的sleep方法
        cat.catchMouse();//cat自身的catchMouse方法
        System.out.println(cat.name);
        System.out.println(cat.age);

    }
}

           
  • 继承的好处
    1. 提高了代码的复用性
    2. 提高了代码的维护性
    3. 让类与类之间产生了关系,是多态的前提
  • 继承的弊端

    类的耦合性增强了。

  • 继承的特点
    1. Java只支持单继承,不支持多继承。(只有一个父亲)
    2. Java支持多层继承(继承体系,即一个父亲也可以有一个父亲就是爷爷,儿子继承父亲,父亲继承爷爷,就相当于孙子也会继承爷爷的成员)
  • 继承的注意事项
    1. 子类只能继承父类所有非私有的成员(成员方法和成员变量)
    2. 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
    3. 不要为了部分功能而去继承
  • 子类中的成员变量和父类中的成员变量名称一样

    在子类中访问一个变量的查找顺序(“就近原则”)

    1. 在子类方法的局部范围找,有就使用
    2. 在子类成员范围找,有就使用
    3. 在父类成员范围找,有就使用
    4. 如果还找不到,就报错
  • 继承中成员方法关系

    I:当子类的方法名和父类的方法名不一样的时候

    II:当子类的方法名和父类的方法名一样的时候

    通过子类调用方法:

    1. 先查找子类中有没有该方法,如果有就使用

    2. 再看父类中有没有该方法,有就使用

    3. 如果没有就报错

super关键字

  • this和super的区别

    this 代表的是本类对象的引用

    super 代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)

  • this和super的使用
    1. 调用成员变量

      this.成员变量 调用本类的成员变量

      super.成员变量 调用父类的成员变量

    2. 调用构造方法

      this(…) 调用本类的构造方法

      super(…) 调用父类的构造方法

    3. 调用成员方法

      this.成员方法 调用本类的成员方法

      super.成员方法 调用父类的成员方法

其实每一个构造方法的第一条语句默认都是:super(),即先访问初始化父类

因为,子类会继承父类中的数据,可能还会使用父类的数据。

所以,子类初始化之前,一定要先完成父类数据的初始化。

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); //30
			System.out.println(this.num); //20
			System.out.println(super.num); //10
		}
	}
class Test {
		public static void main(String[] args) {
			Zi z = new Zi();
			z.show();
		}
	}
           

输出:30(就近本方法中的num=30)、20(this.num即本类中的num=20)、10(super.num即父类中的num=10).

方法重写

  • 概念:

    子类中出现了和父类中一模一样的方法声明(方法名,参数列表,返回值类型),也被称为方法覆盖,方法复写。

  • 应用:

    当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。

    这样,即沿袭( super.call();重写方法中保留)了父类的功能,又定义了子类特有的内容。

//父类代码
public class Phone {
    public Phone() {
        System.out.println("构造方法执行了");
    }

    public void call() {
        System.out.println("打电话 1000行代码");
    }

    public void send() {
        System.out.println("发短信");
    }
}
//子类代码
public class Iphone extends Phone{
    public void palyGame(){
        System.out.println("玩游戏");
    }

    @Override //注解 @Override 这个注解的作用,是用来检测此方法是不是重写父类的方法
    public void call() {                     //同名同参重写
        super.call();                      //沿袭父类的功能
        System.out.println("高清视频通话");  //子类特有功能
    }
}


           
  • 方法重写注意事项
  1. 父类中私有方法不能被重写(父类私有方法子类根本就无法继承)
  2. 子类重写父类方法时,访问权限不能更低(最好就一致)
  3. 父类静态方法,子类也必须通过静态方法进行重写(其实这个算不上方法重写,但是现象确实如此,其实只是执行了子类自己的静态方法而已)

final关键字

  • final修饰特点

    修饰类: 被修饰类不能被继承

    修饰方法: 被修饰的方法不能被重写

    修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量

  • final关键字修饰局部变量

    基本类型,是值不能被改变

    引用类型,是地址值不能被改变

//final修饰类,此类不能被继承
 final class EE{
 }
 //final修饰方法,此方法,不能被子类重写,但是可以让子类继承去用
 class BB{
   public final void show(){
       System.out.println("父类的final修饰的方法,子类不能重写,子类可以继承");
   }
}
//final修饰变量,此变量为一个常量,既然为常量,常量的值就不能再次被改变。
    final int NUM=100;//自定义常量,常量名一般建议大写


           

多态

  • 概述

    某一个事物,在不同时刻表现出来的不同状态。

    例如: Cat c=new Cat();

    Animal a=new Cat();

    猫可以是猫的类型。猫 m = new 猫();

    猫也是动物的一种,也可以把猫称为动物。动物 d = new 猫();

  • 多态前提
    1. 要有继承关系。
    2. 要有方法重写。 (其实没有也是可以的,但是如果没有这个就没有意义。)
    3. 要由父类引用指向子类对象。

      父类 f = new 子类( );

  • 多态中的成员访问特点
    1. 成员变量

      编译看左边,运行看左边。

    2. 构造方法

      创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。

    3. 成员方法

      编译看左边,运行看右边。

      (即父类中没有这个成员方法会报错编译失败,有的话编译成功,但是运行子类重写的方法)

    4. 静态方法

      编译看左边,运行看左边。

      (静态和类相关,算不上重写,所以,访问还是左边的)

public class MyTest {
    public static void main(String[] args) {
        Fu fu = new Zi();
        //1.多态的形式来访问成员变量,编译看左边(父类),运行还是看左边(父类)。
        int num = fu.num;
        System.out.println(num);
        //2.多态的形式来调用成员方法,如果子类有重写,编译看左边,运行看右边,当然子类没有重写该方法,那调用的还是父类的
        fu.show();
        //3.构造方法,多态的形式,还是先去调用父类的构造方法,先完成父类数据的初始化
        //4.多态的形式调用静态方法,调用的还是父类的静态方法。
        fu.hehe();
        Fu.hehe();
        Zi.hehe();
    }
}

class Fu {
    int num = 100;

    public Fu() {
        System.out.println("父类的构造方法执行了");
    }

    public void show() {
        System.out.println("fu show");
    }

    public static void hehe() {
        System.out.println("fu hehe");
    }
}

class Zi extends Fu {
    int num = 50;

    public Zi() {
        System.out.println("子类的构造方法执行了");
    }

    @Override
    public void show() {
        System.out.println("zi Show");
    }


    public static void hehe() {
        System.out.println("zi hehe");
    }
}

           
  • 多态的好处
    1. 提高了代码的维护性(继承保证)
    2. 提高了代码的扩展性(由多态保证)
  • 多态的弊端

    不能使用子类特有的功能

    解决弊端:把父类的引用强制转换为子类的引用。(向下转型)

Fu fu = new Zi();  //继承
        fu.show();        //继承父类方法
        Zi zi= (Zi) fu;   //向下转型
        zi.method();      //子类特有方法