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 }
时间: 2024-10-05 01:00:53