JAVA面向对象之final关键字与多态详解

news/2024/6/29 12:01:57 标签: java, 面向对象, 多态, final关键字

java面向对象">JAVA面向对象

final关键字绝育的">final关键字(绝育的)

特点

java">1.修饰方法  作用 这个被修饰的方法不能被重写
2.修饰变量  作用 修饰的基本数据类型的变量 不能被重新赋值
            被final修饰的 对象的地址不能 改变(不能重新指向)
3.修饰类    作用  被修饰的类不能被继承

代码示例

public class Demo01{
    public static void main(String[] args){
        Class A = new ClassA();
        a.fun();

        //final修饰引用数据类型时
        //对象中数据变量的值是可以被修改的
        final ClassA a1 = new ClassA();
        //修改成员变量
        a1.num = 20;
        a1.num = 30;
        System.out.println(a1.num);  //输出结果30
    }
}

class ClassA{
    //num  创建对象的时候 有默认的初始值为0
    //但是这个初始值是无效的
    int nun;
    public void fun(){
        System.out.println("我是 ClassA 的 fun方法");
    }
    public void fun1(){
        System.out.println("打开 手机 银行 取钱");
    }

}

class ClassB extends ClassA{
    @Override
    public void fun1(){
        super.fun1();
    }
}
java">final修饰成员变量的时候 该成员变量必须有有效的初值
被final修饰的变量 程序中不能被修改 相当于常量
使用场景:
一般会与public static 连用
常量命名规范: 纯大写 多个用下划线分开

代码示例

public class Demo02{

}
class ClassC{
    public static final int MAX_VALUE = 10;
    //参数也可以被final修饰 相当于修饰的是局部变量
    public void fun(final int i){
        System.out.println(MAX_VALUE);
    }
}

多态一种事物的多种形态">多态:一种事物的多种形态

前提

1.类与类之间要产生联系 继承关系
2.要有方法的重写(没有方法的重写 多态的意义不大)
3.核心:父类的引用指向子类的对象

举例

人(姓名 年龄 性别)的多种形态
婴儿(多30块骨头) 少年(早恋) 成年(智齿) 中年(更年期) 老年(痴呆症)
暮年(最后一口气) 死人

动物(出声) 名字 种类 介绍自己(方法)
狗(汪汪汪) 猫(喵喵喵) 牛(萌萌萌) 羊(咩咩咩)

水果 香蕉 苹果 橘子 菠萝

代码举例

public class Demo03{
    public static void main(String[] args){
        //本类的引用指向本类对象的空间
        Cat cat = new Cat();
        //父类的引用执行子类的空间
        Animal animal = new Cat();
        animal.Speak();  //调用的是猫类的方法

        Animal animal2 = new Dog();
        animal2.Speak;  //调用的是狗类的方法
    }
}
class Animal{
    private String name;
    private int kind;

    public Animal(){

    }
    public Animal(String name, String kind){
        this.name = name;
        this.kind = king;
    }

    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getKind(){
        return kind;
    }
    public void setKind(String kind){
        this.kind = kind;
    }

    public void speak(){
        System.out.println("动物会发出叫声");
    }
    public String toString(){
        return "姓名" + name + "种类:" + kind;
    }
}

//猫类
class Cat extends Animal{
    public Cat(){

    }
    public Cat(String name, String kind){
        this.name = name;
        this.kind = name;
    }
    //重写父类speak方法
    public void speak(){
        System.out.println("猫会喵喵叫");
    }
    //重写toString()方法
    public String toString(){
        return super.toString();
    }
}
//狗类
class Dog extends Animal{
    public Dog(){

    }
    public Dog(String name, String kind){
        this.name = name;
        this.kind = kind;
    }
    //重写speak方法
    public void speak(){
        System.out.println("狗会汪汪汪地叫");
    }
    //重写toString()方法
    public String toString(){
        return super.toString();
    }
}

多态内存分析">多态内存分析

多态">测试多态

调用成员变量 和 成员方法   在内存中的表现

多态调用成员变量时   简单记 编译和运行 都看等号左边(父类引用)
解释:当子类继承父类之后,new一个子类对象的时候,由于子类对象继承了父类的对象,
所有子类内存中会有一部分的内存区域(称为A区域)保存的是父类的成员变量,当父类
引用指向子类对象时,父类的引用会指向A区域,寻找A区域的内存变量,如果A区域没有
这个变量,编译将会报错,所有运行时候看的是左边父类,打印的是父类中得变量;

多态调用成员方法时,会动态绑定 简单记编译看左边(父类)运行看右边(子类)
解释:编译时Animal animal = new Cat(),这句编译时,只要子类继承了父类,
这句话就可以编译通过,但当调用子类的方法时,比如调用子类的toString()方法或者
调用子类自身特有的方法时,编译器会坚持父类中有没有该方法,如果父类中没有在调
用的子类的方法时,编译将报错,如果父类中有子类的该方法时,编译将通过,所有称之
为编译看左边;运行看右边是因为,运行时,虽然父类中也有该方法,不过运行时候调用
的却是子类中的重写方法,而不是父类中同名的方法,所有运行看右边,即子类,输出的
是子类方法中得内容

内存图:

这里写图片描述

代码示例

public class Demo04{
    public static void main(String[] args){
        Father father = new Son();
        System.out.println(father.num);   //输出结果为10
        father.print();  //输出:我是子类中得print方法

    }
}
class Father{
    int num = 10;

    System.out.println("我是父类中的print方法");
}

class Son extends Father{
    int num = 20;

    System.out.println("我是子类中得print方法");
}

多态的好处与弊端">多态的好处与弊端

多态的好处:
1.代码维护性强(这条建立在继承的基础上)
2.代码的扩展性强(核心好处)

多态的弊端:
使用多态声明的时候 无法直接调用子类的特有方法 只能通过向下转型后才可以
使用子类特有的方法


int num = 97;
char c = (char)num;
System.out.println(c);

代码举例

public class Demo05{
    public static void main(String[] args){
        //使用多态的形式创建对象
        //骗子把自己的逼格提高 伪装了一个人
        //向上转型
        Person person = new PZ();
        //打印的是子类的方法 而非父类的方法
        person.speak(); //输出:洗脑 掏钱

        //调用子类特有的方法 这时多态下 创建出来的对象
        //是不能直接调用子类的特有方法 person.hit();
        //需要把这个对象 进行向下转型(相当于强制类型转换)
        //注意:必须是这个类型的,才可以进行强制转换,不是这个类型的 不能
        //进行强制转换
        PZ pz = (PZ)person;
        pz.hit();
    }
}

//建立人 类
class person{
    public void speak(){
        System.out.println("人类会说话");
    }
}

//建立骗子类
class PZ extends person{
    //重写父类speak方法
    @override
    public void speak(){
        System.out.println("洗脑  掏钱");
    }
    //自己特有的方法
    public void hit(){
        System.out.println("打到死为止, 不能轻易放弃");
    }
}

多态举例1">多态举例1

 * 需求:
 * 武器类  打 挥舞武器
 * 刀类    打  挥舞刀 —  砍人
 *        练功  练刀
 * 棍类    打  挥棍 —— 敲人
 *        练棍  耍棍
 * 封装一个创建刀的方法  在方法中调用挥舞刀方法
public class Demo06{
    public void fun(WuQi wuqi){
        wuqi.play();  //当传入刀的对象实例时,输出:挥舞刀 - 砍人
                      //当传入棍的对象实例时,输出:挥棍 - 敲人
    }
    public static void main(String[] args){
        fun(new Dao());  //调用重写方法
        fun(new Gun());  //调用重写方法

        //下面调用私有方法 展示向下转换方法
        Wuqi wq = new Dao();
        if(wq instanceof Dao){ 
            Dao dao = (Dao) wq;
            wq.practise();  //输出:练刀
        }

    }
}
class WuQi{
    public void play(){
        System.out.println("挥舞武器");
    }
}
class Dao extends WuQi(){
    //重写武器类的打方法
    public void play(){
        System.out.println("挥舞刀 - 砍人");
    }
    public void practise(){
        System.out.println("练刀");
    }
}
class Gun extends WuQi(){
    //重写武器类方法
    public void play(){
        System.out.println("挥棍 -- 敲人");
    }
    public void parct(){
        System.out.println("刷棍");
    }
}

多态举例2">多态举例2

 需求
 * 铁桶僵尸(zombie) 血量 方法:被打一次掉2血 直到被打死
 * 帽子僵尸 血量 方法:被打一次掉5血 直到被打死
 * 封装一个 打僵尸的方法
 */
public class Demo07{

    public void practise(Zombie z){
        z.play();
    }
    public static void main(String[] args){
        practise(new TtZombie(40));
        practise(new mZZombie(60));
    }
}
class Zombie{
    private int blood;
    public int getBlood(){
        return blood;
    }
    public void setBlood(int blood){
        this.blood = blood;
    }
    public void play(){
        System.out.println("打僵尸,被打一次要掉血,直到被打死");
    }
}

Class TtZombie extends Zombie{
    public TtZombie(){

    }
    public TtZombie(int blood){
        super(blood);
    }
    //重写父类play()方法
    public void play(){
        while(true){
            if(this.getBlood() <= 0){
                System.out.println("铁通僵尸被打死了");
                break;
            }
            this.setBlood(this.getBlood() - 2);
            System.out.println("铁通僵尸剩余血量为:" + this.getBlood);
        }
    }
}

class MzZombie extends Zombie{
    public MzZombie(){

    }
    public MzZombie(int blood){
        this.blood = blood;
    }

    //重写父类的play方法
    public void play(){
        if(this.getBlood() <= 0){
            System.out.println("帽子僵尸被打死了");
            return;
        }
        this.setBlood(this.getBlood() - 5);
        System.out.println("帽子僵尸的血量为:" + this.getBlood());
        play();
    }
}

多态举例3">多态举例3

 * 定义主板类 
 * 主板
 * 启动方法
 * 插卡方法(例如声卡 网卡 显卡 内存条)
 * 播放音乐 关闭播放
 * 上网 断网
public class Demo08{
    public static void main(){
        MainBoard mainboard = new MainBoard(); 
        mainboard.run();    //输出电脑已启动
        mainboard.insertCard(new MusicCard());   //输出音乐已播放  音乐已暂停
        mainboard.insertCard(new NetCard());   //输出网络已连接 网络已断开
    }
}
class MainBoard{
    public void run(){
        System.out.println("电脑已经启动");
    }
    public void insertCard(Card card){
        card.start();
        card.stop();
    }
}
class card{
    public void start(){
        System.out.println("卡已经插入");
    }
    public void stop(){
        System.out.println("卡已经拔出");
    }
}
class MusicCard extends Card{
    //重写start()方法
    public void start(){
        System.out.println("音乐已播放");
    }
    //重写stop方法
    public void stop(){
        System.out.println("音乐已暂停");
    }
}
class NetCard{
    //重写start()方法
    public void start(){
        System.out.println("网络已连接");
    }
    //重写stop()方法
    public void stop(){
        System.out.println("网络已断开");
    }
}

http://www.niftyadmin.cn/n/1829296.html

相关文章

做一个小程序需要多少钱

做一个小程序要多少钱&#xff0c;这种分2种类型 定制版 定制版就是按着客户的需求来做了。首先是聊需求&#xff0c;然后画思维导图&#xff0c;做原型图&#xff0c;做完原型图&#xff0c;就是做UI设计&#xff0c;然后做前端&#xff0c;后端。这个费用下来大概几千元到几…

SVG(可缩放矢量图形)

SVG可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff09;是基于可扩展标记语言&#xff08;XML&#xff09;&#xff0c;用于描述二维矢量图形的一种图形格式。SVG是W3C("World Wide Web ConSortium" 即 " 国际互联网标准组织")在2000年8月制定…

bzoj2437

会做jsoi那道game&#xff0c;这题就非常简单了吧 我们考虑空格的移动&#xff0c;显然&#xff0c;初始与空格位置距离为奇数的黑棋和距离为偶数的白棋并没有什么用&#xff0c; 空格不会移到那&#xff0c;我们直接把他们当作障碍&#xff0c;其他点我们当作可移动区域 这不就…

数论随记(二)

HDU1573 /*中国剩余定理*/ 10. 公式 1. ab(mod m) (a mod m) b (mod m) (化简); HDU1395 (2^x 1(mod n) 2^x%n 1(mod n) ) 2. xa(mod m) x*ka*k(mod m); 3. xn-a(mod m) xan(mod m); HDU1788 4. gcd(a,b)k gcd(a/k,b/k)1; 5. a%k (变型&#xff1a; %k ) HDU1852 如果m与k互…

【解决方案】去掉谷歌浏览器获取焦点时默认的input、textarea的边框和背景

1、使用Chrome的都知道&#xff0c;当鼠标焦点在input、textarea这些元素上时&#xff0c;Chrome默认的会给它们加上黄色的边框&#xff0c;我以前一直以为这是chrome的特性&#xff0c;没法去掉&#xff0c;原来是css的效果&#xff0c;outline这个属性。 你可以用下面的css代…

JAVA面向对象之抽象类

JAVA面向对象之抽象类 abstract类 修饰类 --- 抽象类 修饰方法 --- 抽象方法 修饰变量 --- 没有抽象变量 抽象类简介 1.成员变量 变量和常量 2.成员方法可以是抽象方法 抽象方法不可以有实现部分 3.构造方法有构造方法 4.如何创建对象不能创建对象 注意 1.抽象类不能实…

消息中间件-基于metaq-zookeeper

消息中间件消息中间件在消息传输过程中保持消息的容器。消息中间件再讲消息从它的原中继到它的目标时充当中间人的作用。队列的主要目的是提供路由并保证消息的传递&#xff1b;如果发送消息是接受者不可用&#xff0c;消息队列会保留消息&#xff0c;直到可以成功地传递它为止…

python计算文件夹大小(linux du命令 简化版)

C盘又满了&#xff0c;怎么办&#xff1f;用了一些垃圾清理软件&#xff08;或者bat脚本&#xff09;&#xff0c;但是还是不理想&#xff0c;那么具体哪些文件夹下面有巨大的文件呢&#xff1f;windows并不能通过详细信息看到每个文件夹的大小&#xff08;PS&#xff1a;这里所…