当前位置:   article > 正文

JavaSE(继承、super用法、protected、final)_protected final

protected final

1.继承

继承概念

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。
在这里插入图片描述
上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。

继承语法

修饰符 class 子类 extends 父类 { //..... }

遵循原则

  1. 子类会将父类中的成员变量或者成员方法继承到子类中了
  2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
// Animal.java
class Animal{
    String name;
    int age;
    float wight;
    public void eat(){
        System.out.println(name + "正在吃饭");
    }
    
    public void sleep(){
        System.out.println(name + "正在睡觉");
    }
}
 
// Dog.java
class Dog extends Animal{    
    void bark(){
        System.out.println(name + "汪汪汪~~~");
    }
}
// Cat.Java
class Cat extends Animal{   
    void mew(){
        System.out.println(name + "喵喵喵~~~");
    }
}
 
// TestExtend.java
public class TestExtend {
    public static void main(String[] args) {
        Dog dog = new Dog();
        // dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
        System.out.println(dog.name);
        System.out.println(dog.age);
 
        // dog访问的eat()和sleep()方法也是从Animal中继承下来的
        dog.eat();
        dog.sleep();
        dog.bark();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

子类中访问父类的成员变量或成员方法

不管是成员变量还是成员方法,都有两种情况:
(1)子类和父类不存在同名
(2)子类和父类同名

在子类方法中 或者 通过子类对象访问成员或方法时:
1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。

1.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
2.通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;

子类构造方法(重要)

父子父子,先有父再有子,即:子类对象构造时,需要先调用父类构造方法,然后执行子类的构造方法。
原因:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子
肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

class Animal {
    public  String name = "123";//姓名
    public int age;
    
    public Animal() {
        System.out.println("Animal()");
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("带有2个参数的构造方法!");
    }
    public void eat() {
        System.out.println(name+" 正在吃饭!");
    }
}
class Dog extends Animal {
    public Dog() {
        //super();//编译器会帮你默认加上的
        System.out.println("DOG()");
    }

    public Dog(String name,int age) {
        //super();
        super(name,age);  
        //super("七月",10);//显示的调用父类的构造方法,帮助父类的成员进行初始化
    }

    public void wangwang() {
        System.out.println(name +" 旺旺叫!");
    }
}
class Cat extends Animal {
    public Cat() {
        super();
    }

    public int size;
    public Cat(String name,int age,int size) {
        super(name,age);
        this.size = size;
    }
    public Cat(String name,int age) {
        super(name,age);
        //this("1",2,3);
    }

    public void mew() {
        System.out.println(name +" 正在喵喵叫!");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println("=====");
        Dog dog2 = new Dog();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
    在这里插入图片描述
  2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
    在这里插入图片描述

2.super关键字

子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?

  • super关键字,该关键字主要作用:在子类方法中访问父类的成员。
    在这里插入图片描述

super和this

super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语句,那他们之间有什么区别呢?

【相同点】

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

【不同点】

  1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
  2. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
    在这里插入图片描述

3.protected 关键字

刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 “封装” 的初衷.
两全其美的办法就是 protected 关键字.
对于类的调用者来说, protected 修饰的字段和方法是不能访问的
对于类的 子类 和 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的

在这里插入图片描述

// 为了掩饰基类中不同访问权限在子类中的可见性,为了简单类B中就不设置成员方法了
// extend01包中
public class B {
    private int a;
    protected int b;
    public int c;
    int d;
}
 
// extend01包中
// 同一个包中的子类
public class D extends B{
    public void method(){
        // super.a = 10;      // 编译报错,父类private成员在相同包子类中不可见
        super.b = 20;         // 父类中protected成员在相同包子类中可以直接访问
        super.c = 30;         // 父类中public成员在相同包子类中可以直接访问
        super.d = 40;         // 父类中默认访问权限修饰的成员在相同包子类中可以直接访问
    }
}
 
// extend02包中
// 不同包中的子类
public class C extends B {
    public void method(){
        // super.a = 10;     // 编译报错,父类中private成员在不同包子类中不可见
        super.b = 20;        // 父类中protected修饰的成员在不同包子类中可以直接访问
        super.c = 30;        // 父类中public修饰的成员在不同包子类中可以直接访问
        //super.d = 40;      // 父类中默认访问权限修饰的成员在不同包子类中不能直接访问
    }
}
 
// extend02包中
// 不同包中的类
public class TestC {
    public static void main(String[] args) {
        C c = new C();
        c.method();
        // System.out.println(c.a);   // 编译报错,父类中private成员在不同包其他类中不可见
        // System.out.println(c.b);   // 父类中protected成员在不同包其他类中不能直接访问
        System.out.println(c.c);      // 父类中public成员在不同包其他类中可以直接访问
        // System.out.println(c.d);   // 父类中默认访问权限修饰的成员在不同包其他类中不能直接访问
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

4.final 关键字

final关键可以用来修饰变量、成员方法以及类,一定要初始化(相当于c语言的const)
final 关键字的功能是 限制 类被继承“限制” 这件事情意味着 “不灵活”. 在编程中, 灵活往往不见得是一件好事. 灵活可能意味着更容易出错.是用 final 修饰的类被继承的时候, 就会编译报错, 此时就可以提示我们这样的继承是有悖这个类设计的初衷的.

  1. 修饰变量或字段,表示常量(即不能修改)

  2. 修饰类:表示此类不能被继承 , 我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承.

  3. 修饰方法:表示该方法不能被重写

1.修饰变量或字段
final int a = 10;//使用final 一定要初始化
a = 20;  // 编译出错

2.修饰类
final public class Animal {
    ...
}
public class Bird extends Animal {
    ...
}
// 编译出错
Error:(3, 27) java: 无法从最终com.bit.Animal进行继比特就业课

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/641915
推荐阅读
相关标签
  

闽ICP备14008679号