面向对象(五)

来源:互联网 发布:做网络兼职是真的吗 编辑:程序博客网 时间:2024/05/01 05:20

一、final
1.继承的代码实现:
由于继承中方法有一个现象:方法重写。
所以,父类的功能,就会被子类给覆盖掉
有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
这个时候,针对这种情况,java就提供了一个关键字:final

final:"最终"的意思,常见的是它可以修饰类,方法,变量。
class Fu{// Zi中的show()无法覆盖Fu中的show()    public final void show(){        System.out.println("绝密文件,任何人都不能修改");    }}class Zi extends Fu{    public void show(){        System.out.println("这是一堆垃圾");    }}class FinalDemo{    public static void main(String[] args){        Zi z = new Zi();        z.show();    }}

2.final修饰类,方法,变量
final可以修饰类,方法,变量

    特点:    final可以修饰类:该类不能被继承。    final可以修饰方法:该方法不能被重写(覆盖,复写)    final可以修饰变量:该变量不能被重新赋值,因为这个变量其实就是常量。    常量:        A、字面值常量            "hello"、10、true        B、自定义常量            final int x = 10
class Fu{        public final int num= 100; }class Zi extends Fu{    public void show(){    //无法为最终变量num分配值         num = 10;        System.out.println(num);    }}class FinalDemo{    public static void main(String[] args){        Zi z = new Zi();        z.show();    }}

3.final修饰局部变量的问题
基本类型:基本类型的值不能发生改变
引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
比如:教室的地址不能变,但是教室里面的学生可以改变。

class Student{    int age = 10;}class FinalDemo{    public static void main(String[] args){        //局部变量是基本数据类型        int x = 10;        x = 100;        System.out.println(x);        final int y = 10;        //错误: 无法为最终变量y分配值        //y = 10;        System.out.println(y);        System.out.println("------------");        //局部变量是引用数据类型        Student s = new Student();        System.out.println(s.age);        s.age = 100;        System.out.println(s.age);        System.out.println("-------------");        final Student ss = new Student();        System.out.println(ss.age);        ss.age = 100;        System.out.println(ss.age);        System.out.println("-----------");        //不能这样写,因为引用变量传递是地址值,        //我们这样做,是在重新开辟一个空间        //而final修饰的引用变量是无法重新开辟空间的。        //重新分配内存空间        //错误: 无法为最终变量ss分配值        ss = new Student();    }}

4.final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次
B:在构造方法完毕前(非静态的常量)

class Demo{    //int num = 10;    //final int num2 = 20;    int num;    final int num2;    public Demo(){        num = 100;        num2 = 200;    }}class FinalDemo{    public static void main(String[] args){        Demo d = new Demo();        System.out.println(d.num);    }}

二、多态
1.概述和前提条件
多态:同一个对象(事物),在不同时刻体现出来的不同状态。
举例:
猫是猫,猫是动物。
水(液态,固态,气态)。

多态的前提:    A:要有继承关系    B:要有方法重写。        其实没有也是可以的,但是如果没有这个就没有意义。    C:要有父类引用指向子类对象。        父   f   =   new  子();用代码体现一下 多态中的成员访问特点:A:成员变量:编译看左边,运行看左边。B:构造方法    创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。C:成员方法        编译看左边,运行看右边。(因为方法存在方法覆盖)    **如果子类中存在方法重写,那么        父类    f =  new  子类        中f调用的就是子类中的方法,如果调用的方法子类中没有,那么就调用父类中的方法D:静态方法    编译看左边,运行看左边(静态和类相关,算不上重写,所以,访问还是左边的)由于成员方法存在方法重写,所以它运行看右边。
class Fu{    public int num = 100;    public void show(){        System.out.println("showFu");    }}class Zi extends Fu{    public int num = 1000;    public int num2 = 200;    public void show(){        System.out.println("showZi");    }    public void method(){        System.out.println("method");    }}class DuoTaiDemo{    public static void main(String[] args){        //要有父类引用指向子类对象。        //父   f = new  子();        Fu f = new Zi();        System.out.println(f.num);        //结果是100        // 错误: 找不到符号        //System.out.println(f.num2);        f.show();        // 错误: 找不到符号        //f.method();    }}

2.多态的好处
A:提高了代码的维护性(继承保证)
B:提高了代码的维护性
猫狗案例代码

class Animal{    public void eat(){        System.out.println("eat");    }    public void sleep(){        System.out.println("sleep");    }}class Dog extends Animal{    public void eat(){        System.out.println("狗吃肉");    }    public void sleep(){        System.out.println("狗站着睡觉");    }}class Cat extends Animal{    public void eat(){        System.out.println("猫吃鱼");    }    public void sleep(){        System.out.println("猫趴着睡觉");    }}class Pig extends Animal{    public void eat(){        System.out.println("猪吃白菜");    }    public void sleep(){        System.out.println("猪侧着睡觉");    }}//针对动物操作的工具类class AnimalTool{    //私有化工具类构造方法,别人无法创建对象    private AnimalTool(){}    /*    //调用猫的功能    public static void useCat(Cat c){        c.eat();        c.sleep();    }    //调用狗的功能    public static void  useDog(Dog d){        d.eat();        d.sleep();    }     //调用猪的功能    public static void  usePig(Pig p){        p.eat();        p.sleep();    }    */    public static void useAnimal(Animal a){        a.eat();        a.sleep();    }}class DuoTaiDemo{    public static void main(String[] args){        //我喜欢猫,就养了一只        Cat c = new Cat();        c.eat();        c.sleep();        //我很喜欢猫,所以,又养了一只        Cat c2 = new Cat();        c2.eat();        c2.sleep();        //我特别喜欢猫,又养了一只        Cat c3 = new Cat();        c3.eat();        c3.sleep();        System.out.println("---------------");        //问题来了,我养了很多只猫,每次创建对象是可以接受的        //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。        //我们准备用方法改进        //调用方式        /*        useCat(c1);        useCat(c2);        useCat(c3);        */        //AnimalTool.useCat(c);        //AnimalTool.useCat(c2);        //AnimalTool.useCat(c3);        AnimalTool.useAnimal(c);        AnimalTool.useAnimal(c2);        AnimalTool.useAnimal(c3);        System.out.println("---------------");        //我喜欢狗        Dog d = new Dog();        Dog d2 = new Dog();        Dog d3 = new Dog();        //AnimalTool.useDog(d);        //AnimalTool.useDog(d2);        //AnimalTool.useDog(d3);        AnimalTool.useAnimal(d);        AnimalTool.useAnimal(d2);        AnimalTool.useAnimal(d3);        System.out.println("---------------");        //我喜欢宠物猪        //定义一个猪类,她要继承自动物,提供两个方法,并且还要在工具类中添加该类的调用        Pig p = new Pig();        Pig p2 = new Pig();        Pig p3 = new Pig();        //AnimalTool.usePig(p);        //AnimalTool.usePig(p2);        //AnimalTool.usePig(p3);        AnimalTool.useAnimal(p);        AnimalTool.useAnimal(p2);        AnimalTool.useAnimal(p3);        System.out.println("---------------");        //我喜欢宠物狼,老虎,豹子...        //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用        //前面几个必须写,但是,工具类每次都改,我就想,能不能不改了?        //所以改用另一种解决方案。        //    }    /*    //调用猫的功能    public static void useCat(Cat c){        c.eat();        c.sleep();    }    //调用狗的功能    public static void  useDog(Dog d){        d.eat();        d.sleep();    }    */}

3.多态的弊端
不能使用子类的特有功能

class Fu{    public void show(){        System.out.println("show Fu");    }}class Zi extends Fu{    public void show(){        System.out.println("show Zi");    }    public void method(){        System.out.println("method");    }}class DuoTaiDemo{    public static void main(String[] args){        Fu fu = new Zi();        fu.show();        //错误: 找不到符号        fu.method();    }}

4.多态中向上转型和向下转型
多态的弊端:
不能使用子类的特有功能

我就想使用子类的特有功能?行不行?行。怎么用呢?A:创建子类对象调用方法即可。(可以,但是很多时候不合理,而且,太占内存了)B:把父类的引用强制转换为子类的引用。(向下转型)对象间的转换问题:    向上转型:            Fu  f = new zi();    向下转型:            Zi z = (Zi)f;//要求这里的f必须是能够转换为子的。
class Fu{    public void show(){        System.out.println("show Fu");    }}class Zi extends Fu{    public void show(){        System.out.println("show Zi");    }    public void method(){        System.out.println("method");    }}class DuoTaiDemo{    public static void main(String[] args){        Fu fu = new Zi();        fu.show();        //错误: 找不到符号        //fu.method();        //创建子类对象        //方式1:使用这种方法,内存是两个对象        //Zi z = new Zi();        //z.show();        //z.method();        //方式2:使用这种方法,内存中是一个对象。        //你能够把子的对象赋值给父亲,那么我能不能        //把父的引用赋值给子的引用呢?        Zi z = (Zi)fu;        z.show();        z.method();    }}

4.多态问题理解——孔子装爹案例

class 孔子爹  {    public int age = 40;    public void teach(){        System.out.println("讲解javase");    }}class 孔子 extends 孔子爹 {    public int age = 20;    public void teach(){        System.out.println("讲解javase");    }    public void playGame(){        System.out.println("英雄联盟");    }}//java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了,//但是还有人来请,就剩孔子在家,价格还挺高,孔子一想,我是不是可以考虑去呢?//然互就穿上爹的衣服,带上爹的眼镜,粘上爹的胡子。就开始装爹。//向上转型孔子爹   k爹  =  new  孔子();//到人家那里去了System.out.println(k爹.age);k爹.teach();k爹.playGame();//这是儿子才能做的//讲完了,下班回家了//脱下爹的装备,换上自己的装备孔子  K = (孔子)k爹;System.out.println(k.age);//20k.teach();//讲解论语k.playGame();//英雄联盟

5.多态的内存图解
这里写图片描述

6.多态中的对象变化内存图解
这里写图片描述

/*    ClassCastException:类型转换异常    一般在多态的向下转型中容易出现*/class Animal{    public void eat(){}}class  Dog extends Animal{    public void eat(){}    public void lookDoor(){}}class Cat extends Animal{    public void eat(){}    public void playGame(){}}class DuoTaiDemo{    public static void main(String[] args){        //内存中的是狗        Animal a = new Dog();        Dog d = (Dog)a;        //内存中的是猫        a = new Cat();        Cat c = (Cat)a;        //内存中的是猫        Dog  dd = (Dog)a;//.ClassCastException        //java中类型转换不匹配的错误    }}

7.面试题

/*    看程序写结果:先判断有没有问题,如果没有,写出结果    多态的成员访问特点:        方法:编译看左边,运行看 右边    继承的时候:        子类中有和父类中一样的方法,叫重写。        子类中没有和父亲中出现过的方法,方法就被继承*/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 DuoTaiTest2{    public static void main(String[] args){        A a = new B();        a.show();        B b = new C();        b.show();    }}/*    结果:爱你*/
0 0
原创粉丝点击