Java学习笔记——Java语言基础(八)(继承、super关键字与多态)

一、继承

1.1 继承的概述

1.多个类中存在相同的属性和行为是,将这些相同的内容抽取到单独的一个类中,这样多个类中就不用去定义这些相同的属性和行为,只要去继承抽取出来的那个类即可。
2.继承的格式:使用关键字extends可以实现继承的关系
class 子类 extends 父类{ }
父类也可以称为基类或者超类。
3.代码实现继承的关系

//定义一个父类
public class FU {
    String name;
    int age;
    public void eat(){
        System.out.println(name+"的年龄为"+age);
    }
}
//子类实现继承
class Zi extends FU{
     
}

//测试类
public class Test {
    public static void main(String[] args) {
    //定义子类的一个对象zi,通过对象调用继承父类的成员变量和成员方法,可以看到正常运行
        Zi zi = new Zi();
        zi.name="张三";
        zi.age=23;
        zi.eat();//张三的年龄为23
    }
}

4.继承的利与弊:

好处:a.提高了代码的复用性
           b.提高了代码的维护性
           c.让类与类之间的发生了关系,是多态的前提
弊端:a.增加了类的耦合性
在开发的过程中:讲究的就是高内聚,低耦合。
内聚:就是自己完成某件事的能力
耦合:就是类与类之间的关系  

5.继承的特点:
继承只支持单继承,不支持多继承。但是Java支持多层继承,也就是继承体系,继承父类的子类同样也可以拥有子类。
6.注意事项:

  1. 子类只能继承父类所有的非私有的成员方法和成员变量
  2. 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法
  3. 不能为了部分功能而且继承
    7.继承是成员变量的关系
    子类的成员变量和父类的成员变量不一样,通过子类中去调取不同的变量名即可。
    子类的成员变量和父类的成员变量一样,代码查看运行结果:
//父类与子类的成员变量名相同,在子类方法中进行调用。
class Fu {
    //父类的成员变量
    int num = 22;
}

class Zi extends Fu {
    //子类的成员变量
    int num = 23;
    //子类的成员方法
    public void show() {
        System.out.println("父类: " + num);//23
        System.out.println("子类:" + num);//23
    }
}
class Test{
    public static void main(String[] args) {
        // 创建子类对象
        Zi z = new Zi();
        // 调用子类中的show()方法
        z.show();
    }
}

可以看出运行结果两个都是子类的成员变量,并没有调取父类的成员方法。这是因为在子类中的变量的访问的一个查找顺序(就近原则)

  1. 子类的方法局部内进行查找,有就使用
  2. 子类的成员范围内进行查找,有就使用
  3. 父类的成员范围内进行查找,有就使用
  4. 如果都没有找到,则报错

1.2 super关键字

1.super关键字可以在子类的局部范围内访问父类的成员变量
2.this和super的区别
   this       代表的是本类对象的引用
   super    代表的是父类存储空间的标识(父类的引用,操作父类的成员)
3.this和super的使用
    (1)调用成员变量
            this.成员变量        调用本类的成员变量
            super.成员变量     调用父类的成员变量
    (2)调用构造方法
            this()       调用本类的构造方法
            super()   调用父类的构造方法
    (3)调用成员方法
            this.成员方法       调用本类的成员方法
            super.成员方法    调用父类的成员方法

对上述代码使用super关键字:

//父类与子类的成员变量名相同,在子类方法中使用super关键字进行调用。
class Fu {
    //父类的成员变量
    int num = 22;
}

class Zi extends Fu {
    //子类的成员变量
    int num = 23;
    //子类的成员方法
    public void show() {
        System.out.println("父类: " + super.num);//22
        System.out.println("子类:" + num);//23
    }
}
class Test{
    public static void main(String[] args) {
        // 创建子类对象
        Zi z = new Zi();
        // 调用子类中的show()方法
        z.show();
    }
}

可以看出,使用super关键字之后的num访问的是父类的成员变量

1.3 继承中的构造方法

1.子类中所有的构造方法默认都会访问父类中空参数的构造方法
2.子类继承父类中的数据,可能还会使用父类中的数据,这时候子类在进行初始化之前,一定要先完成父类数据的初始化
3.每一个子类的构造方法的第一条语句默认都是super()
4.构造方法中的注意事项:
当父类没有无参构造方法时,子类怎么办?(父类中定义了有参构造,系统将不会默认给出无参构造)

  • 在父类中添加一个无参的构造方法
  • 子类通过super去显示调用父类其他的带参的构造方法
  • 子类通过this去调用本类的其他构造方法(本类其他构造也必须首先访问父类构造)
    super(…)和this(…)必须出现在第一条语句上
public class Test02 {
    public static void main(String[] args) {
        Zi1 zi1 = new Zi1();//子类的无参构造将name传递给子类的有参构造,将name返回父类的有参构造,输出 name
        Zi1 zi2 = new Zi1("张三");//将张三传递给子类的有参构造,将张三返回父类的有参构造,输出  张三
        System.out.println(zi1);//打印地址值
        System.out.println(zi2);//打印地址值
    }
}
class Fu1{
    String name;
    public Fu1(String name){
        System.out.println(name);
    }

}
class Zi1 extends Fu1{
    String name1;
    //父类没有无参构造,默认报错
//    public Zi1(){
//
//    }
    //父类只存在有参构造,所有子类的有参构造必须第一行使用super(参数)
    public Zi1(String name){
        super(name);
    }
    //无参构造,必须第一行使用this调用本类的其他构造方法
    public Zi1(){
       this("name");
    }
}

1.4 继承中的成员方法关系

1.当子类的方法名和父类的方法名不一样的时候,使用对象.方法名调用即可
2.当子类的方法名与父类的方法名一样的时候:通过子类调用方法
(1).先查看子类中有没有此方法,有就使用
(2).再看父类有没有此方法,有就使用
(3).如果都没有就报错

public class Test03 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        //父类与子类的方法名不一样,直接调用
        dog.sleep1();//狗在睡觉
        dog.sleep();//动物睡觉
        //父类与子类的方法名一样,子类中有这个方法,则使用的是子类的方法
        dog.eat();//狗在吃饭
    }
}
class Animals{
    String name;
    public void eat(){
        System.out.println("动物吃饭");
    }
    public void sleep(){
        System.out.println("动物睡觉");
    }

}
class Dog extends Animals{
    public void eat() {
        System.out.println("狗在吃饭");
    }

    public void sleep1() {
        System.out.println("狗在睡觉");
    }
}

1.5 方法重写

1.注意事项:

  • 父类中私有的方法不能被重写(父类的私有方法不会被子类所继承)
  • 子类重写父类方法时,访问权限不能更低(最后一致)
  • 静态方法属于类,不参与重写。(静态方法优先于对象的创建)
  • 子类重写父类方法的时候,最好声明一模一样
public class Test01 {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();//show方法
        Zi.test();//通过类名调用静态方法
        Fu.test();//通过类名调用静态方法
    }
}
class Fu{
    public void show(){
        System.out.println("show方法");
    }
    public static void test(){
        System.out.println("父类的静态方法");
    }

}
class Zi extends Fu{
    //重写父类方法的快捷键 ctrl+o

    @Override
    public void show() {
        super.show();
    }
    public static void test(){
        System.out.println("子类的静态方法");
    }
}

1.6 final关键字

1.由于继承中会有方法重写,而有时候不让子类去重写父类的方法,这种情况下要使用final关键字
2.final关键字:可以修饰类,变量和成员方法
3.final的修饰特点:(1)修饰类:  被修饰的类不能	
               	(2)修饰成员变量:  被修饰的变量不能被重新赋值,因为这个量是一个常量
		 (3)修饰方法:  被修饰的方法不能够被重写
4.final修饰成员变量是,成员变量名使用大写
5.final修饰局部变量的时候:(1)基本类型:   值不能改变
			 (2)引用类型:  地址值不能改变

public class Test {
    //final修饰的值不能被该改变
    private final int MENU_01=23;
    public static void main(String[] args) {
        final int NUM=200;
        System.out.println(NUM);//200
        new C().test();//子类Test方法
        new C().show();//show方法
        //final修饰的引用类型地址值不能改变
        final B b=new B();
        System.out.println(b);//B@1540e19d
    }
}
class A{
    //final修饰的方法不能够重写
    public final void show(){
        System.out.println("show方法");
    }
    public void test(){
        System.out.println("父类test方法");
    }
}
final class B{

}
class C extends A{
    //重写test方法
    @Override
    public void test() {
        System.out.println("子类Test方法");
    }
}

二、多态

2.1 多态的概述

1.多态:某一种事物,在不同时刻表现出来的不同状态
Cat cat=new Cat()
Animal cat=new Cat()
上述两行表示一个对象可以表示两种类型:猫可以是猫,也可以是动物
2.多态的前提:

  • 要有继承关系
    -要有方法的重写
    要有父类引用指向子类对象
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();//猫吃饭
        //父类对象指向子类引用
        Animal cat1=new Cat();
        cat1.eat();//猫吃饭
    }
}
class Animal{
    public void eat(){
        System.out.println("动物吃饭");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃饭");
    }
}

2.2 多态中的成员访问特点

1.成员访问特点:
  a.成员变量:编译看左,运行看左
  b.构造犯法:创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化
  c.成员方法:编译看左,运行看右
  d.静态方法:编译看左,运行看左(静态方法与类相关,访问还是左边的)
public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        System.out.println(zi.name);//李四
        zi.show();//子类的show方法
        //采用多态的形式,去访问成员变量 访问的是父类 编译看左边,运行也看左边
        Fu zi1=new Zi();
        System.out.println(zi1.name);//张三
        //采用多态的形式,去调用成员方法,如果有重写。编译看左边,运行看右边
        zi1.show();//子类的show方法
        Fu.test();//父类的静态方法
        Zi.test();//子类的静态方法
    }
}
class Fu{
    String name="张三";
    public void show(){
        System.out.println("父类的show方法");
    }
    public static void test(){
        System.out.println("父类的静态方法");
    }

}
class Zi extends Fu{
    String name="李四";

    @Override
    public void show() {
        System.out.println("子类的show方法");
    }
    public static void test(){
        System.out.println("子类的静态方法");
    }
}

2.3 多态的好处与弊端

1.提高了代码的维护性(继承保证)
2.提高了代码的扩展性(多态保证)
3.弊端:不能使用子类特有的功能

2.4 多态中的向上转型和向下转型

把父类的引用强制转换为子类的引用

public class Test {
    public static void main(String[] args) {
        //向上转型
        Fu fu=new Zi();
        fu.show();//子类的show方法
        //fu.test(); 由于父类中不存在test方法,编译看左,所以不能够直接调用test方法
        //这也是一种向下转型的方式,调用子类特有的方法
        ((Zi) fu).test();
        //向下转型
        Zi zi= (Zi) fu;
        zi.test();//子类特有的test方法
    }
}
class Fu{
    public void show(){
        System.out.println("父类的show方法");
    }
}
class Zi extends Fu{
    @Override
    public void show() {
        System.out.println("子类的show方法");
    }
    public void test(){
        System.out.println("子类特有的test方法");
    }
}

2.5 多态的内存图

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值