java学习-继承和final方法

1. 继承

  1.1 继承的概述

  1. 继承面向对象中的一大特征
  2. 继承 : 让类与类之间发生关系(关联), 子父类关系 ; 使用extends关键字,让类与类之间具有子父类继承关系
  3. 举例 :

     class A{}

     class B extends A{}

  上述代码:

     A类被继承的类 : 称为父类, 超类, 基类

     B类用于继承 : 称为子类, 派生类

  1.2继承发生场景

     如果同一个类别的多个事物之间, 具有共性, 将共性内容向上抽取, 抽取到一个父类中,剩下的类作为这个父类的子类 ; 父类中实现共性内容, 每一个子类只需要实现其特有的内容即可, 子类可以通过继承关系使用父类中的共性内容

   注意 : 不要为了节省几个方法的设计,贸然使用继承关系; 继承关系通常都是属于关系(is a), 举例 : 猫和狗都属于动物, 因此猫和狗可以作为动物的子类

代码

public class Animal {
      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 Dog extends Animal {
    public void lookHome() {
        System.out.println("狗可以看家");
    }
}
public class TestAnimal {
    public static void main(String[] args) {
          // 1. 创建出一个Cat对象
          Cat c = new Cat();
          c.eat();// eat方法从父类Animal类中继承使用
          c.sleep();// sleep方法从父类Animal类中继承使用
          c.catchMouse();// catchMouse方法是Cat类型特有方法
          
          // 2. 创建出一个Dog对象
          Dog d = new Dog();
          d.eat();
          d.sleep();
          d.lookHome();
    }
}

  1.3 继承使用的注意事项

  1. 父类中的私有成员变量和方法, 无法被子类继承使用

   私有都是使用private关键字修饰的, 私有只能在当前类型中使用, 子类不是父类类型本身, 私有因为权限使用范围,所以子类无法继承使用父类中的私有成员

  1. 父类的构造方法无法被子类继承, 但是子类可以调用父类构造

   父类构造是父类类名; 子类构造是子类类名, 如果可以继承父类构造,就会发生构造名称与子类类名不一致的情况,矛盾, 因此子类不能继承父类构造

  1.4 继承的特点

  1. java中, 继承关系都是单继承, 不支持多继承,可以多层继承
  2. 单继承 : 一个子类只能有一个直接父类
  3. 不支持多继承 : 不支持一个子类同时继承多个父类

     

     

  4.  多层继承:

       C类继承B: CB的子类

       B类继承A: BA的子类

       C类可以继承到B,A类中的所有的可继承内容

     

     

     

     

 代码

public class A {
    public void eat() {
        System.out.println("Aeat");
    }

    public void fun() {
        System.out.println("A玩");
    }
}
public class B extends A {
    public void sleep() {
        System.out.println("Bsleep");
    }

    public void fun() {
        System.out.println("B玩");
    }
}
public class C extends B{

}
public class TestABC {
    public static void main(String[] args) {
        C c = new C();
        c.fun();// fun使用从父类B继承来的方法
        c.eat();// eat使用从爷爷A继承来的方法
        c.sleep();// fun使用从父类B继承来的方法
    }
}

  1.5 继承中的成员变量

    子类可以继承使用父类中的非私有成员变量

  1 子父类成员变量不重名

   如果子类中定义了与父类不重名的成员变量, 子类可以使用从父类继承来的成员变量,也可以使用子类特有的变量

  2 super关键字区分子父类成员变量重名

  如果子类中定义了与父类中同名的成员变量

    1) 变量的使用需要符合就近原则:

     a : 方法中使用变量,如果方法中已经定义出了局部变量, 优先使用局部

     b : 没有定义局部变量,使用当前类型中成员变量

     c : 如果类型中没有定义出成员变量,到父类中寻找可继承的成员...一直找最顶层的父类处(Object)

 

    2) 区分子父类变量的重名问题 : 可以在子类中使用super关键字

     super : 关键字, 表示当前类型对应的父类对象的引用

     在子类代码中 : super.调用变量, 带有super关键字的变量,表示父类成员变量的调用

 代码

public class Father {
    // 1. 继承中的成员变量使用
    int i = 10;
    int w = 20;
}
public class Son extends Father {
    // 1. 继承中成员变量
    // Son从父类中继承到变量i = 10; w = 20;
    int j = 99;
    
    // 子类定义出了与父类同名的成员变量w
    int w = 88;
    
    public void useVariable() {
        int w = 999;
        System.out.println(w);// 999
        System.out.println(this.w);// 88
        // 使用父类中的w变量
        System.out.println(super.w);// 20
    }
}
public class TestFatherAndSon {

    public static void main(String[] args) {
       // 1. 创建出一个Son子类 对象
        Son son = new Son();
        System.out.println(son.i);// 父类变量i
        System.out.println(son.j);// 子类特有变量j
        System.out.println(son.w);// 与父类重名的变量w, 使用子类的w,88 
        
        System.out.println("----------------");
        
        son.useVariable();
    }
}

  1.7继承中的成员方法

  1. 父类中的私有方法无法被子类继承
  2. 如果子类中定义的方法功能与父类中的方法功能不重名,不重复, 子类可以使用自己定义的方法功能,也可以使用从父类继承来的方法
  3. 如果子类对于从父类继承而来的方法功能, 认为不能实现子类的要求, 那么子类可以重写父类中继承而来的方法, 重写的目的是为了让方法越来越好

    1) 方法重写 : 方法声明上与父类一致,方法的实现逻辑上与父类不一致

    2) 方法重写规则:

    要求 :

    a : 方法返回值类型, 方法名, 参数列表, 与父类方法保持一致

    b : 方法体可以做任意逻辑实现

    c : 子类重写的方法在权限修饰上, 大于等于父类的使用权限

    public ---->默认权限(没有任何权限修饰)--->private(私有)

    d : 验证这个方法是否是子类重写方法, @Override  (Override表示重写), 写在方法声明之上

  4.如果子父类具有重名的方法, 如何区分:

    super.父类方法名(实际参数);

    super关键字调用的方法表示父类方法的调用,记得super关键字用于子类中

  1.8 thissuper关键字的使用总结

  1. this 关键字 : 表示本类(当前类型)对象引用

    1) 用于区分局部变量和成员变量重名问题

       带有this.关键字的变量,表示成员变量的使用

    2) 本类的构造方法之间互相调用

       this(构造需要的实际参数); // 必须写在构造方法中有效行第一行

  2.super关键字 : 表示当前类型父类对象的引用

    1) 用于区分子类和父类中的重名的变量和方法问题

       带有super.关键字的变量和方法, 表示父类的变量或方法的使用

    3) 子类的构造方法调用父类的构造

       super(父类构造需要的实际参数); // 必须写在构造方法中有效行第一行  

  3.静态方法中,不能使用this和super关键字, 静态中不能直接使用非静态

     This() 和 super() 作为构造中的调用语句都要放在第一行, 因此两者不能同时出现在同一个构造中, 二选一

2. final关键字

  1. final关键字 : 修饰符, 表示最终的,最后的,不可改变的
  2. final关键字可以修饰 : 类, 方法, 变量

    1) final修饰类 : 这个类就是一个不可改变的类,最终类

      使用final修饰的类,不能当父类; 最终就体现在没有子类重写改变父类中内容; final修饰的类使用一切正常

    2) final修饰方法 : 这个方法就是最终方法,不可改变

    使用final修饰的方法,能被子类继承使用,但是不能被子类重写

    3) final修饰变量 : 这个变量只能手动赋值一次, 变量值再不可修改;

    使用final修饰的变量称为 常量, 命名规则 : 全大写,多个英文单词之间使用_进行分隔

    a : final修饰基本数据类型变量, 这个变量的值不可修改

    b : final修饰的引用数据类型变量, 变量的地址值不能修改, 但是地址中的数据可以改变

    c : final修饰成员变量, 需要在创建对象完成之前给final变量进行赋值

      1) 定义final成员直接赋值

      2) 可以在构造中,以及构造之前进行赋值

final修饰类代码:

// 定义出一个使用final修饰类, 名字FinalClass
public final class FinalClass {
   int i = 10;
   
   public void fun() {
       System.out.println("-------------");
   }
}
//The type FinalClassZi cannot subclass the final class FinalClass
// FinalClassZi 无法成为一个使用final关键字修饰的类的子类
 public class FinalClassZi extends FinalClass {
    
}
public class TestFinal {
    public static void main(String[] args) {
        // 1. 使用final修饰的类不能作为父类,但是可以正常使用
        FinalClass fc = new FinalClass();
        System.out.println(fc.i);// 10
        fc.fun(); // -------------
    }
}

Final修饰方法代码

public class FinalMethod {
     public final int getSum(int x, int y) {
         return x + y;
     }
}
public class FinalMethodZi extends FinalMethod {
    // FinalMethodZi继承了父类中的final方法getSum
    //  Cannot override the final method from FinalMethod
    //  使用final修饰的方法不能重写
    /*@Override
    public final int getSum(int x, int y) {
         return x + y;
    }*/
}
public class TestFinal {
    public static void main(String[] args) {
        // 2. 使用final修饰的方法,不能被子类重写, 但是可以正常继承和使用
        FinalMethodZi fmz = new FinalMethodZi();
        System.out.println(fmz.getSum(3, 5));
    }
}

final修饰变量

public class FinalVariable {

    final static String SCHOOL_NAME = "第一中学";
    
    // The blank final field j may not have been initialized
    final static int j;
    
    static {
        j = 99;
    }
    // 4. final修饰成员变量 : 赋值机制, 创建对象完成之前必须手动赋值完毕
    /*public FinalVariable() {
        j = 25;
    }
    */
    public static void main(String[] args) {
        final int i = 10;
        // 1. 报错 : 使用final修饰的变量i, 值不能修改
        // i = 20;
        
        System.out.println(FinalVariable.SCHOOL_NAME);
        // 2. 报错 : 使用final修饰的变量SCHOOL_NAME, 值不能修改
        // FinalVariable.SCHOOL_NAME = "一中";      
        
        final FinalClass fc = new FinalClass();
        // 3. final修饰引用数据类型: 不可改变的是这个引用对应的内存地址, 这个地址中的数据可以改变
        // fc = new FinalClass();
        fc.i = 99;
        System.out.println(fc.i);// 99 
    }
}

 

posted @ 2020-07-29 21:25  zcb_bai  阅读(525)  评论(0编辑  收藏  举报