面向对象(五)
来源:互联网 发布:做网络兼职是真的吗 编辑:程序博客网 时间: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
- 面向对象(五)
- 面向对象(五)
- JAVA面向对象(五)
- 面向对象计算器(五)
- 面向对象PHP(五)
- 第七课 面向对象编程(五)
- GIS面向对象模型设计(五)
- javascript面向对象编程(五)
- Java基础之面向对象(五)
- Java基础—面向对象(五)
- java面向对象基础知识(五)
- 理解面向对象编程(五)-GUI
- C++面向对象实验(五)
- Python学习 (五 面向对象编程)
- JAVA之面向对象(五)
- C#面向对象(五)委托
- java学习记录----面向对象(五)
- Java面向对象(五)封装
- UE4 中 为StaticMesh添加贴合物体的碰撞
- 那既然如此,就再水一篇吧
- sublime3配置Python编译器快速编译python程序
- 分享一个网站,代码交流平台的,免的费神向ide复制粘贴又粘贴到论坛!
- 【Cyril的二级C++笔记】运算符
- 面向对象(五)
- android代码16进制公钥进行RSA加密
- JMX 介绍
- elasticsearch的一些优化汇集
- python基础篇--Dict(字典)
- 练手文章
- iOS应用程序实现内部多语言国际化,不跟随系统语言改变的步骤
- OpenStack-Nova组件理解
- 完美洗牌算法