抽象类、接口和内部类(下)
来源:互联网 发布:2016网络暴力案例 编辑:程序博客网 时间:2024/05/24 00:31
- 抽象类、接口和内部类(下)
- 面向对象汇总
1. 抽象类、接口和内部类(下)
1.1. 多态
1.1.1. 多态的意义
前面所讲解的现象就是多态,多态即多种形态,主要有两个方面的表现。
首先,一个类型的引用在指向不同的对象时会有不同的实现,看如下的代码:
- 达内职员 emp1 = new 达内讲师();
- 达内职员 emp2 = new 达内项目经理();
- emp1.完成工作();
- emp2.完成工作();
达内职员 emp1 = new 达内讲师(); 达内职员 emp2 = new 达内项目经理();emp1.完成工作();emp2.完成工作();
同样是达内职员类型,当指向不同的对象时,可以有不同的表现。
其次,同样一个对象,造型成不同的类型时,会有不同的功能,看如下代码所示:
- 达内讲师 teacher = new 达内讲师();
- 企业技术顾问 consultant = teacher;
- 技术图书作者 author = teacher;
- consultant.培训员工();
- author.编辑稿件();
达内讲师 teacher = new 达内讲师();企业技术顾问 consultant = teacher;技术图书作者 author = teacher;consultant.培训员工();author.编辑稿件();
通过上面的代码,可以看出,同样的达内讲师对象,当将其造型为企业技术顾问及技术图书作者时,可以实现不同的功能。
1.1.2. 向上造型
在前面的课程中,介绍了一个现象,父类的引用指向子类的对象。这个现象就是下面要给大家介绍的现象,叫做向上造型。
一个类的对象可以向上造型的类型有:父类的类型及其实现的接口类型。当发生向上造型时,Java编译器会根据类型检查调用方法是否匹配。看如下的图 -1:
图 -1
实际应用中,可以使用如下的代码进行操作:
- 达内讲师 teacher = new 达内讲师();
- 达内职员 emp = teacher;
- 企业技术顾问 consultant = teacher;
- 技术图书作者 author = teacher;
- emp.上班打卡();
- emp.完成工作();
- consultant.培训员工();
- author.编辑稿件();
达内讲师 teacher = new 达内讲师();达内职员 emp = teacher;企业技术顾问 consultant = teacher;技术图书作者 author = teacher;emp.上班打卡();emp.完成工作();consultant.培训员工();author.编辑稿件();
1.1.3. 强制转型
在实际应用中,还可以通过强制转换将父类型变量转换为子类型变量,前提是该变量指向的对象确实是该子类类型。也可通过强制转换将变量转换为某种接口类型,前提是该变量指向的对象确实实现了该接口。如果在强制转换过程中出现违背上述两个前提,将会抛出ClassCastException。看如下代码所示:
- 达内职员 emp1 = new 达内讲师();
- 达内讲师 teacher = (达内讲师) emp1;
- 技术图书作者 author = (技术图书作者) emp1;
- 达内项目经理 pm = (达内项目经理) emp1;
达内职员 emp1 = new 达内讲师();达内讲师 teacher = (达内讲师) emp1;技术图书作者 author = (技术图书作者) emp1;达内项目经理 pm = (达内项目经理) emp1;
分析如下代码,声明达内职员类型emp1指向子类达内讲师对象,而后将emp1强制转换为达内讲师类,完全没有问题,而后将emp1再转换为技术图书作者类型,因为emp1实现了技术图书作者接口,所以转换也没有问题。但是最后一句,将emp1强制转换为达内项目经理,则会出现错误,抛出ClassCastException异常,意为,类型转换异常。因为emp1与达内项目经理没有父子关系及实现关系。
1.1.4. instanceof关键字
在强制转型中,为了避免出现ClassCastException,可以通过instanceof关键字判断某个引用指向的对象是否为指定类型。看如下代码所示:
- 达内职员 emp1 = new 达内讲师();
- System.out.println(emp1 instanceof 达内讲师); // true
- System.out.println(emp1 instanceof 技术图书作者); // true
- System.out.println(emp1 instanceof 达内项目经理); // false
- 达内项目经理 pm = null;
- if (emp1 instanceof 达内项目经理) {
- pm = (达内项目经理) emp1;
- }
达内职员 emp1 = new 达内讲师();System.out.println(emp1 instanceof 达内讲师); // trueSystem.out.println(emp1 instanceof 技术图书作者); // trueSystem.out.println(emp1 instanceof 达内项目经理); // false达内项目经理 pm = null;if (emp1 instanceof 达内项目经理) { pm = (达内项目经理) emp1;}
分析如上代码,可以看出,因为emp1指向的为达内讲师,所以判断emp1是否是达内讲师类,返回结果为true,而达内讲师类又实现了技术图书作者接口,所以判断emp1是否为技术图书作者,返回结果也为御前。当想将emp1转换为达内项目经理时,先通过instanceof关键字判断,而后再转型。这样则可以避免发生ClassCastException,因为只要instanceof为true,则强制转换一定成功。
1.2. 内部类
1.2.1. 定义成员内部类
一个类可以定义在另外一个类的内部,定义在类内部的类称之为Inner,其所在的类称之为Outer;Inter定义在Outer的内部,通常只服务于Outer,对外不具备可见性,Inter可以直接调用Outer的成员及方法(包括私有的)。看如下代码:
- class Outer{
- private int time;
- class Inner{
- public void timeInc(){
- time++;
- }
- }
- }
class Outer{private int time; class Inner{ public void timeInc(){ time++;}}}
从上面的代码可以看出,在Outer类之中声明了Inner类,在Inner类中直接操作了Outer类的私有成员变量time。
1.2.2. 创建内部类对象
一般情况下,Inner对象会在Outer对象中创建(构造方法或其他方法);Inner对象中会有一个隐式的引用指向创建它的Outer类对象。看如下代码所示:
- class Outer {
- private int time;
- private Inner inner;
- Outer(int time) {
- this.time = time;
- inner = new Inner();
- inner.timeInc();
- }
- public void printTime() {
- System.out.println(time);
- }
- class Inner {
- public void timeInc() {
- time++;
- }
- }
- }
class Outer { private int time; private Inner inner; Outer(int time) { this.time = time; inner = new Inner(); inner.timeInc(); } public void printTime() { System.out.println(time); } class Inner { public void timeInc() { time++; } }}
在main方法中,声明如下代码:
- Outer outer = new Outer(100);
- outer.printTime();
Outer outer = new Outer(100);outer.printTime();
上面代码的输出结果为:101。在Outer构造方法中创建的Inner对象会有一个隐式的引用指向创建它的Outer对象,调用Inner对象的timeInc方法,即会对Outer的time属性进行操作。
1.2.3. 定义匿名内部类
如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类),而且对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。看下面的代码:
- SuperType obj = new SuperType (…) {
- … … …
- };
SuperType obj = new SuperType (…) { … … …};
其中,第一个SuperType为用匿名类所实现的接口或所继承的父类类型声明的引用;第二个SuperType为匿名类所要实现的接口或继承的父类;小括号()中为构造方法参数;大括号中为匿名中定义的成员变量或方法。
请参见下面的代码:
- public interface Action { public void execute();
- }
- public class Main {
- public static void main(String[] args) {
- Action action = new Action(){
- public void execute() {
- System.out.println("Hello, World");
- }
- };
- action.execute();
- }
- }
public interface Action { public void execute();} public class Main { public static void main(String[] args) { Action action = new Action(){ public void execute() { System.out.println("Hello, World"); } }; action.execute(); }}
如上的代码中,创建了实现了Action接口的内部匿名类对象,并调用其execute方法。
2. 面向对象汇总
2.1. 面向对象汇总
2.1.1. 面向对象汇总
面向对象三大特征:封装、继承、多态
- 抽象类、接口和内部类(下)
- Java类和接口(常规内部类、静态内部类、局部内部类、匿名内部类、抽象类、接口)
- java接口,抽象类和内部类
- 内部类,抽象类和接口
- 抽象类、接口和内部类
- 抽象类、接口和内部类
- OOP Unit06 抽象类、接口和内部类(下) 、 面向对象汇总
- OOP Unit05 抽象类、接口和内部类(上)
- 抽象类、接口和内部类(上)
- Java--类和接口--常规内部类,静态内部类,局部内部类,匿名内部类,抽象类,接口
- 接口、抽象类、内部类
- 抽象类,接口,内部类
- 接口、抽象类、内部类
- 抽象类、接口、内部类
- 接口,抽象类,内部类
- 接口和内部类、抽象类的特性
- java接口、抽象类和内部类的区别
- 转:接口、抽象类和内部类的区别
- 抽象类、接口和内部类(上)
- ThinkPhp学习笔记-如何定义Template模板路径
- ACM Contest and Blackout
- C#相对路径转绝对路径,绝对路径转相对路径
- Codeforces Round #422 (Div. 2) C. Hacker, pack your bags!
- 抽象类、接口和内部类(下)
- POJ 3984 迷宫问题
- Java-Java反射
- HDU 2553 N皇后问题
- 51nod 1238 最小公倍数之和 V3
- MFC exe替换大、中、小图标方法
- 《深入探索Android热修复技术原理》安卓热修复原理宝典出炉,阿里技术大牛联袂推荐
- Fix TypeError: Cannot read property 'emit' of undefined after upgrade to 2.0.0 @ionic/cli-plugin-ion
- Eclipse搭建SSH(Struts2+Spring3+Hibernate3)框架项目教程