Java中final以及多态的概述和使用

这一块的内容主要是有关final以及多态的概述和使用。

1.final

  • final关键字是最终的意思,可以修饰 类、成员变量、成员方法

    • 修饰类,类不能被继承
    • 修饰变量,变量就变成了常量,只能被赋值一次
    • 修饰方法,方法不能被重写
    • 在构造方法初始化完成之前赋值完毕(修饰的是非静态的常量)
  • 常量

    • 字面值常量:
      “java”、100、false
    • 自定义常量:
      修饰变量,变量就变成了常量
      final int x = 100;//此刻的x就是一个常量
  • final变量的引入
    由于继承中有一个现象,子类的方法和父类的方法声明一样,出现重写现象,所以,父类的功能就会被子类覆盖。但有时候,我们不想让子类覆盖父类的方法或者功能,只能让子类使用,这个时候,针对这种情况,Java就提供了一个关键字:final

举例1:子类无法重写父类中被final修饰的方法

class Fu1{
    public final void show(){
        System.out.println("这是父类的方法");
    }
}

class Zi extends Fu1{
//    public void show(){
//        System.out.println("子类无法重写父类的方法");
//    }
}

public class ZiDemo {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();
    }
}
//这是父类的方法

举例2:final修饰的变量不能被修改

class Fu2{
    int num = 10;
    final int num2 = 20;
    public final void fun(){
        System.out.println("这是父类的方法");
    }
}

class Zi2 extends Fu2{

    int num1 = 100;
    public void show(){
        num = 100;
//        num2 = 20;//这也是一个不能被重写的变量
        System.out.println(num);
        System.out.println(num2);
    }

//    public void fun(){
//        System.out.println("这是一个不能被重写的方法");
//    }
}

public class FinalDemo1 {
    public static void main(String[] args) {
        Zi2 zi2 = new Zi2();
        zi2.show();
        zi2.fun();//这里打印的是父类的方法

        final int x = 20;
//        x = 30;//这是一个不能被该的变量
        System.out.println(x);
    }
}
//100
//20
//这是父类的方法
//20
  • 面试题:final修饰局部变量
    1、在方法内部,该变量不能被改变
    2、final修饰引用数据类型的时候,引用的地址值不能发生改变,但是,该对象的堆内存里面的值是可以改变的
class Student1{
    int age = 10;
}

public class FinalTest1 {
    public static void main(String[] args) {
        int x = 10;
        x = 100;
        System.out.println(x);
        System.out.println("------------------");
        final int y = 20;
//        y = 200;//Java无法为最终变量y分配值
        System.out.println(y);
        System.out.println("------------------");

        Student1 student1 = new Student1();
        System.out.println(student1.age);
        System.out.println("------------------");
        final Student1 student2 = new Student1();
        System.out.println(student2.age);
        student2.age = 20;
        System.out.println(student2.age);
        System.out.println("------------------");
//        student2 = new Student1();//Java无法为最终变量s2分配值
    }
}
//100
//------------------
//20
//------------------
//10
//------------------
//10
//20
//------------------

2.多态

  • 多态概述:某一个事物,在不同时刻表现出来的不同状态
  • 举例
    水:
    固态、液态、气态
    固态的水是水、液态的水是水、气态的水是水
    水果:
    苹果、香蕉、西瓜
    苹果是水果、香蕉是水果、西瓜是水果
    但不能说水果是苹果、水果是香蕉
  • 我们通过观察这些例子发现,要想有多态,必须要有继承,继承是多态的前提
  • 多态的条件:
    • 要有继承的关系
    • 要有方法的重写
      其实没有也可以,但是没有重写就没有意义
    • 要有父类引用指向子类对象
      父 f = new 子();
  • 多态中成员访问特点
    • 成员变量
      编译看左边,运行看左边
    • 构造方法
      创建子类对象的时候,先访问父类的构造方法,对父类的数据先进行初始化
    • 成员方法
      编译看左边,运行看右边
      因为成员方法存在重写,所以访问看右边
    • 静态成员方法
      编译看左边,运行看左边
      由于被static修饰的都是与类相关的,算不上重写,所以,运行的时候,访问的还是左边的

多态中访问成员变量、成员方法、静态成员方法举例:

class Fu3{
    int num = 100;
    int num2 = 20;

    public void show(){
        System.out.println("这是父类中的成员方法");
    }

    public static void show2(){
        System.out.println("这是父类中的静态成员方法");
    }
}

class Zi3 extends Fu3{

    int num = 1000;
    int num2 = 40;

    public void show(){
        System.out.println("这是子类中的成员方法");
    }

    public void fun(){
        System.out.println("这是子类中的另一个成员方法");
    }

    public static void show2(){
        System.out.println("这是子类中的静态成员方法");
    }
}

public class Polymorphic {
    public static void main(String[] args) {
        Fu3 f = new Zi3();
        System.out.println(f.num2);//成员变量,编译看左边,运行看左边

        f.show();//成员方法,编译看左边,运行看右边
        f.show2();//静态成员方法,编译看左边,运行还是看左边
    }
}
//20
//这是子类中的成员方法
//这是父类中的静态成员方法
  • 多态的好处
    1、提高了代码的维护性(这是继承保证的)
    2、提高了程序的扩展性(这是多态决定的)
  • 多态的弊端
    不能访问子类的特有功能

多态的弊端举例:
在这个例子中,我们就无法访问子类的特有方法function

class Fu4{
    public void show(){
        System.out.println("这是父类的方法");
    }
}

class Zi4 extends Fu4{
    public void show(){
        System.out.println("这是子类的方法");
    }

    public void function(){
        System.out.println("这是子类特有的方法");
    }
}

public class PolymorphicDemo3 {
    public static void main(String[] args) {
        Fu4 f = new Zi4();
        f.show();
//        f.function();//Error:(23, 10) java: 找不到符号
    }
}
  • 多态中的转型
    我们刚刚发现了,子类不能调用自己特有的方法

    如果我就想使用多态来调用自己子类的特有方法,怎么办呢

    这时我们就要使用到多态中的转型
    Zi5 z = (Zi5) f2;

    多态中转型的使用:
    向上转型:Fu5 f = new Zi5();
    向下转型:Zi5 z = (Zi5) f2;
    注意:这样的转型,必须要求f2必须是能够转换成z的,也就是说,他俩必须要是继承关系

    子类转换为父类,向上转型:自动转换
    父类转换为子类,向下转型:强制转换

class Fu5{
    public void show(){
        System.out.println("这是父类的方法");
    }
}

class Zi5 extends Fu5{
    public void show(){
        System.out.println("这是子类重写父类的方法");
    }

    public void function(){
        System.out.println("这是子类特有的方法");
    }
}

public class PolymorphicDemo4 {
    public static void main(String[] args) {
        Fu5 f = new Zi5();
        f.show();

        //多态中的转型,我们既然可以将子类的对象赋值给父,为什么不能把父的引用赋值给子引用
        //将子的对象赋值给父
        Fu5 f2 = new Zi5();
        //将父的引用赋值给子的引用
        Zi5 z = (Zi5)f2;
        z.show();
        z.function();
    }
}
//这是子类重写父类的方法
//这是子类重写父类的方法
//这是子类特有的方法
  • 多态的内存图
    在这里插入图片描述
  • 多态向下转型的一种异常
class Animal5{
    public void eat(){}
}

class Dog5 extends Animal5{
    public void eat(){}
    public void lookDoor(){}
}

class Cat5 extends Animal5{
    public void eat(){}
    public void paShu(){}
}

public class PolymorphicDemo5 {
    public static void main(String[] args) {
        Animal5 a = new Dog5();
        a.eat();
//        a.lookDoor();

        Dog5 d = (Dog5) a;  //在我自己看来,这地方就直接相当于是:Dog5 d = new Dog5() ,就可以直接使用Dog5里面所有的东西了

        a = new Cat5();
        a.eat();
//        ((Cat5) a).paShu();

        Cat5 cat5 = (Cat5)a;
        cat5.eat();
        cat5.paShu();

        a = new Animal5();
//        Dog5 dd = (Dog5)a;//因为这个a现在是赋给了cat,而这句话dog和cat,两个没有继承关系,所以报错
    }
}

在这里插入图片描述

  • 附上一道很有意思的题目,结果在代码最后
package com.bigdata.shujia12;
/*
	看程序写结果:先判断有没有问题,如果没有,写出结果

	多态访问成员方法的特点:
		编译看左边,运行看右边

	存在继承的时候:
		1、子类中有父类一样的方法,叫重写
		2、子类中没有出现父类的方法(没有 明确重写),方法直接继承自父类
*/
class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}

class B extends A {
	public void show() {
		show2();
	}

    public void show2() {
        System.out.println("爱");
    }
}
class C extends B {
    public void show() {
        super.show();
    }

    public void show2() {
        System.out.println("你");
    }
}
public class DuoTaiTest4 {
    public static void main(String[] args) {
        A a = new B();
        a.show(); // 爱

        B b = new C();
        b.show(); //你  //方法的重写
    }
}

//爱
//你

感谢阅读,我是啊帅和和,一位大数据专业即将大四学生,祝你快乐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊帅和和。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值