首页 > 代码库 > Java笔记(07):面向对象--多态

Java笔记(07):面向对象--多态

1、final关键字

 1 /*
 2     final可以修饰类,方法,变量
 3     
 4     特点:
 5         final可以修饰类,该类不能被继承。
 6         final可以修饰方法,该方法不能被重写。(覆盖,复写)
 7         final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。
 8         
 9     常量:
10         A:字面值常量
11             "hello",10,true
12         B:自定义常量
13             final int x = 10;
14 */
15 
16 //final class Fu //无法从最终Fu进行继承
17 
18 class Fu {
19     public int num = 10;
20     public final int num2 = 20;
21 
22     /*
23     public final void show() {
24     
25     }
26     */
27 }
28 
29 class Zi extends Fu {
30     // Zi中的show()无法覆盖Fu中的show()
31     public void show() {
32         num = 100;
33         System.out.println(num);
34         
35         //无法为最终变量num2分配值
36         //num2 = 200;
37         System.out.println(num2);
38     }
39 }
40 
41 class FinalDemo {
42     public static void main(String[] args) {
43         Zi z = new Zi();
44         z.show();//100 20
45     }
46 }

2、final修饰局部变量

 1 /*
 2     面试题:final修饰局部变量的问题
 3         基本类型:基本类型的值不能发生改变。
 4         引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
 5 */
 6 class Student {
 7     int age = 10;
 8 }
 9 
10 class FinalTest {
11     public static void main(String[] args) {
12         //局部变量是基本数据类型
13         int x = 10;
14         x = 100;
15         System.out.println(x);
16         final int y = 10;
17         //无法为最终变量y分配值
18         //y = 100;
19         System.out.println(y);
20         System.out.println("--------------");
21         
22         //局部变量是引用数据类型
23         Student s = new Student();
24         System.out.println(s.age);
25         s.age = 100;
26         System.out.println(s.age);
27         System.out.println("--------------");
28         
29         final Student ss = new Student();
30         System.out.println(ss.age);
31         ss.age = 100;
32         System.out.println(ss.age);
33         
34         //重新分配内存空间
35         //无法为最终变量ss分配值
36         ss = new Student();
37     }
38 }

3、final修饰变量的时机

 1 /*
 2     final修饰变量的初始化时机
 3         A:被final修饰的变量只能赋值一次。
 4         B:在构造方法完毕前。(非静态的常量)
 5 */
 6 class Demo {
 7     //int num = 10;
 8     //final int num2 = 20;
 9     
10     int num;
11     final int num2;
12     
13     {
14         //num2 = 10;
15     }
16     
17     public Demo() {
18         num = 100;
19         //无法为最终变量num2分配值
20         num2 = 200;
21     }
22 }
23 
24 class FinalTest2 {
25     public static void main(String[] args) {
26         Demo d = new Demo();
27         System.out.println(d.num);
28         System.out.println(d.num2);
29     }
30 }

4、继承的代码体现

 1 /*
 2     继承的代码体现
 3     
 4     由于继承中方法有一个现象:方法重写。
 5     所以,父类的功能,就会被子类给覆盖调。
 6     有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
 7     这个时候,针对这种情况,Java就提供了一个关键字:final
 8     
 9     final:最终的意思。常见的是它可以修饰类,方法,变量。
10 */
11 class Fu {
12     public final void show() {
13         System.out.println("这里是绝密资源,任何人都不能修改");
14     }
15 }
16 
17 class Zi extends Fu {
18     // Zi中的show()无法覆盖Fu中的show()
19     public void show() {
20         System.out.println("这是一堆垃圾");
21     }
22 }
23 
24 class ZiDemo {
25     public static void main(String[] args) {
26         Zi z = new Zi();
27         z.show();
28     }
29 }

 5、多态

 1 /*
 2     多态:同一个对象(事物),在不同时刻体现出来的不同状态。
 3     举例:
 4         猫是猫,猫是动物。
 5         水(液体,固体,气态)。
 6         
 7     多态的前提:
 8         A:要有继承关系。
 9         B:要有方法重写。
10             其实没有也是可以的,但是如果没有这个就没有意义。
11                 动物 d = new 猫();
12                 d.show();
13                 动物 d = new 狗();
14                 d.show();
15         C:要有父类引用指向子类对象。
16             父 f =  new 子();
17             
18     用代码体现一下多态。
19     
20     多态中的成员访问特点:
21         A:成员变量
22             编译看左边,运行看左边。
23         B:构造方法
24             创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
25         C:成员方法
26             编译看左边,运行看右边。
27         D:静态方法
28             编译看左边,运行看左边。
29             (静态和类相关,算不上重写,所以,访问还是左边的)
30             
31         由于成员方法存在方法重写,所以它运行看右边。
32 */
33 class Fu {
34     public int num = 100;
35 
36     public void show() {
37         System.out.println("show Fu");
38     }
39     
40     public static void function() {
41         System.out.println("function Fu");
42     }
43 }
44 
45 class Zi extends Fu {
46     public int num = 1000;
47     public int num2 = 200;
48 
49     public void show() {
50         System.out.println("show Zi");
51     }
52     
53     public void method() {
54         System.out.println("method zi");
55     }
56     
57     public static void function() {
58         System.out.println("function Zi");
59     }
60 }
61 
62 class DuoTaiDemo {
63     public static void main(String[] args) {
64         //要有父类引用指向子类对象。
65         //父 f =  new 子();
66         Fu f = new Zi();
67         System.out.println(f.num);//100
68         //找不到符号
69         //System.out.println(f.num2);
70         
71         f.show();//show Zi
72         //找不到符号
73         //f.method();
74         f.function();//function Fu
75     }
76 }

6、多态的好处

  1 /*
  2     多态的好处:
  3         A:提高了代码的维护性(继承保证)
  4         B:提高了代码的扩展性(由多态保证)
  5         
  6     猫狗案例代码
  7 */
  8 class Animal {
  9     public void eat(){
 10         System.out.println("eat");
 11     }
 12     
 13     public void sleep(){
 14         System.out.println("sleep");
 15     }
 16 }
 17 
 18 class Dog extends Animal {
 19     public void eat(){
 20         System.out.println("狗吃肉");
 21     }
 22     
 23     public void sleep(){
 24         System.out.println("狗站着睡觉");
 25     }
 26 }
 27 
 28 class Cat extends Animal {
 29     public void eat() {
 30         System.out.println("猫吃鱼");
 31     }
 32     
 33     public void sleep() {
 34         System.out.println("猫趴着睡觉");
 35     }
 36 }
 37 
 38 class Pig extends Animal {
 39     public void eat() {
 40         System.out.println("猪吃白菜");
 41     }
 42     
 43     public void sleep() {
 44         System.out.println("猪侧着睡");
 45     }
 46 }
 47 
 48 //针对动物操作的工具类
 49 class AnimalTool {
 50     private AnimalTool(){}
 51 
 52     /*
 53     //调用猫的功能
 54     public static void useCat(Cat c) {
 55         c.eat();
 56         c.sleep();
 57     }
 58     
 59     //调用狗的功能
 60     public static void useDog(Dog d) {
 61         d.eat();
 62         d.sleep();
 63     }
 64     
 65     //调用猪的功能
 66     public static void usePig(Pig p) {
 67         p.eat();
 68         p.sleep();
 69     }
 70     */
 71     public static void useAnimal(Animal a) {
 72         a.eat();
 73         a.sleep();
 74     }
 75     
 76 }
 77 
 78 class DuoTaiDemo2 {
 79     public static void main(String[] args) {
 80         //我喜欢猫,就养了一只
 81         Cat c = new Cat();
 82         c.eat();
 83         c.sleep();
 84         
 85         //我很喜欢猫,所以,又养了一只
 86         Cat c2 = new Cat();
 87         c2.eat();
 88         c2.sleep();
 89         
 90         //我特别喜欢猫,又养了一只
 91         Cat c3 = new Cat();
 92         c3.eat();
 93         c3.sleep();
 94         //...
 95         System.out.println("--------------");
 96         //问题来了,我养了很多只猫,每次创建对象是可以接受的
 97         //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
 98         //我们准备用方法改进
 99         //调用方式改进版本
100         //useCat(c);
101         //useCat(c2);
102         //useCat(c3);
103         
104         //AnimalTool.useCat(c);
105         //AnimalTool.useCat(c2);
106         //AnimalTool.useCat(c3);
107         
108         AnimalTool.useAnimal(c);
109         AnimalTool.useAnimal(c2);
110         AnimalTool.useAnimal(c3);
111         System.out.println("--------------");
112         
113         //我喜欢狗
114         Dog d = new Dog();
115         Dog d2 = new Dog();
116         Dog d3 = new Dog();
117         //AnimalTool.useDog(d);
118         //AnimalTool.useDog(d2);
119         //AnimalTool.useDog(d3);
120         AnimalTool.useAnimal(d);
121         AnimalTool.useAnimal(d2);
122         AnimalTool.useAnimal(d3);
123         System.out.println("--------------");
124         
125         //我喜欢宠物猪
126         //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
127         Pig p = new Pig();
128         Pig p2 = new Pig();
129         Pig p3 = new Pig();
130         //AnimalTool.usePig(p);
131         //AnimalTool.usePig(p2);
132         //AnimalTool.usePig(p3);
133         AnimalTool.useAnimal(p);
134         AnimalTool.useAnimal(p2);
135         AnimalTool.useAnimal(p3);
136         System.out.println("--------------");
137         
138         //我喜欢宠物狼,老虎,豹子...
139         //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
140         //前面几个必须写,我是没有意见的
141         //但是,工具类每次都改,麻烦不
142         //我就想,你能不能不改了
143         //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
144         //改用另一种解决方案。
145         
146     }
147     
148     /*
149     //调用猫的功能
150     public static void useCat(Cat c) {
151         c.eat();
152         c.sleep();
153     }
154     
155     //调用狗的功能
156     public static void useDog(Dog d) {
157         d.eat();
158         d.sleep();
159     }
160     */
161 }

7、多态的弊端

 1 /*
 2     多态的弊端:
 3         不能使用子类的特有功能。
 4 */
 5 class Fu {
 6     public void show() {
 7         System.out.println("show fu");
 8     }
 9 }
10 
11 class Zi extends Fu {
12     public void show() {
13         System.out.println("show zi");
14     }
15     
16     public void method() {
17         System.out.println("method zi");
18     }
19 
20 }
21 
22 class DuoTaiDemo3 {
23     public static void main(String[] args) {
24         //测试
25         Fu f = new Zi();
26         f.show();
27         f.method();
28     }
29 }

8、多态的向上向下转型

 1 /*
 2     多态的弊端:
 3         不能使用子类的特有功能。
 4         
 5     我就想使用子类的特有功能?行不行?
 6         行。
 7         
 8     怎么用呢?
 9         A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
10         B:把父类的引用强制转换为子类的引用。(向下转型)
11         
12     对象间的转型问题:
13         向上转型:
14             Fu f = new Zi();
15         向下转型:
16             Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
17 */
18 class Fu {
19     public void show() {
20         System.out.println("show fu");
21     }
22 }
23 
24 class Zi extends Fu {
25     public void show() {
26         System.out.println("show zi");
27     }
28     
29     public void method() {
30         System.out.println("method zi");
31     }
32 
33 }
34 
35 class DuoTaiDemo4 {
36     public static void main(String[] args) {
37         //测试
38         Fu f = new Zi();
39         f.show();
40         //f.method();
41         
42         //创建子类对象
43         //Zi z = new Zi();
44         //z.show();
45         //z.method();
46         
47         //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
48         //如果可以,但是如下
49         Zi z = (Zi)f;
50         z.show();
51         z.method();
52     }
53 }

多态的内存图解:

技术分享

多态的对象变化内存图解:

技术分享

9、ClassCastException:类型转换异常

 1 /*
 2     ClassCastException:类型转换异常
 3     一般在多态的向下转型中容易出现
 4 */
 5 class Animal {
 6     public void eat(){}
 7 }
 8 
 9 class Dog extends Animal {
10     public void eat() {}
11     
12     public void lookDoor() {
13     
14     }
15 }
16 
17 class Cat extends Animal {
18     public void eat() {
19     
20     }
21     
22     public void playGame() {
23         
24     }
25 }
26 
27 class DuoTaiDemo5 {
28     public static void main(String[] args) {
29         //内存中的是狗
30         Animal a = new Dog();
31         Dog d = (Dog)a;
32         
33         //内存中是猫
34         a = new Cat();
35         Cat c = (Cat)a;
36         
37         //内存中是猫
38         Dog dd = (Dog)a; //ClassCastException
39     }
40 }

练习:猫狗案例

 1 /*
 2     多态练习:猫狗案例
 3 */
 4 class Animal {
 5     public void eat(){
 6         System.out.println("吃饭");
 7     }
 8 }
 9 
10 class Dog extends Animal {
11     public void eat() {
12         System.out.println("狗吃肉");
13     }
14     
15     public void lookDoor() {
16         System.out.println("狗看门");
17     }
18 }
19 
20 class Cat extends Animal {
21     public void eat() {
22         System.out.println("猫吃鱼");
23     }
24     
25     public void playGame() {
26         System.out.println("猫捉迷藏");
27     }
28 }
29 
30 class DuoTaiTest {
31     public static void main(String[] args) {
32         //定义为狗
33         Animal a = new Dog();
34         a.eat();
35         System.out.println("--------------");
36         //还原成狗
37         Dog d = (Dog)a;
38         d.eat();
39         d.lookDoor();
40         System.out.println("--------------");
41         //变成猫
42         a = new Cat();
43         a.eat();
44         System.out.println("--------------");
45         //还原成猫
46         Cat c = (Cat)a;
47         c.eat();
48         c.playGame();
49         System.out.println("--------------");
50         
51         //演示错误的内容
52         //Dog dd = new Animal();
53         //Dog ddd = new Cat();
54         //ClassCastException
55         //Dog dd = (Dog)a;
56     }
57 }    

练习:爱你

 1 /*
 2     看程序写结果:先判断有没有问题,如果没有,写出结果
 3     
 4     多态的成员访问特点:
 5         方法:编译看左边,运行看右边。
 6         
 7     继承的时候:
 8         子类中有和父类中一样的方法,叫重写。
 9         子类中没有父亲中出现过的方法,方法就被继承过来了。
10 */
11 class A {
12     public void show() {
13         show2();
14     }
15     public void show2() {
16         System.out.println("我");
17     }
18 }
19 class B extends A {
20     /*
21     public void show() {
22         show2();
23     }
24     */
25 
26     public void show2() {
27         System.out.println("爱");
28     }
29 }
30 class C extends B {
31     public void show() {
32         super.show();
33     }
34     public void show2() {
35         System.out.println("你");
36     }
37 }
38 public class DuoTaiTest4 {
39     public static void main(String[] args) {
40         A a = new B();
41         a.show();//
42         
43         B b = new C();
44         b.show();//
45     }
46 }

 

Java笔记(07):面向对象--多态