9299.net
大学生考试网 让学习变简单
当前位置:首页 >> 工学 >>

[Core.Java基础教程]_杨帆_06.Java面向对象编程-类设计_图文

[Core.Java基础教程]_杨帆_06.Java面向对象编程-类设计_图文

http://gzyangfan.spaces.live.com/blog/

学习目标
? ? ? ? ?

正确使用属性、方法完成类设计 定义继承、多态、重载、覆盖 和虚拟方法调用 使用访问修饰符 protected 和缺省(友元包) 描述构造器和方法重载的概念 描述完整的对象结构和初始化操作

gzyangfan@gmail.com

面向对象
面向对象使软件的开发超越了过程序编程,而进入了简化程序开发的可重用编程世界。

gzyangfan@gmail.com

面向对象概述(wiki)
面向对象程序设计的雏形,早在1960年的Simula语言中即可发现,当时的程序设计领域 正面临着一种危机:在软硬件环境逐渐复杂的情况下,软件如何得到良好的维护?面向对象 程序设计在某种程度上通过强调可重复性解决了这一问题。20世纪70年代的Smalltalk语言在 面向对象方面堪称经典——以至于30年后的今天依然将这一语言视为面向对象语言的基础。 面向对象程序设计可以被视作一种在程序中包含各种独立而又互相调用的单位和对象的 思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者 直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、 处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,或者说是 负各自责任的不同角色。 目前已经被证实的是,面向对象程序设计推广了程序的灵活性和可维护性,并且在大型 项目设计中广为应用。 此外,支持者声称面向对象程序设计要比以往的做法更加便于学习, 因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。反对者 在某 些领域对此予以否认。

gzyangfan@gmail.com

面向对象和面向过程的区别
?

?

面向过程就是分析出解决问题所需要的步骤,然后用 函数把这些步骤一步一步实现,使用的时候一个一个 依次调用就可以了。 面向对象是把构成问题事务分解成各个对象,建立对 象的目的不是为了完成一个步骤,而是为了描叙某个 事物在整个解决问题的步骤中的行为。

gzyangfan@gmail.com

面向对象和面向过程的区别示例
?

面向过程
? 我要去某个地方,我要自己来开车,决定走哪条路,决定该 向左还是向右,遇到交通灯又要停下来……整个到目的地过 程中的所有细节我都要关心。

?

面向对象
? 我要去某个地发,我请一个司机,告诉他我的目的地。好了, 我可以睡觉了,到了目的地司机会叫醒我,我不再需要关心 过程中的细节问题,那是司机的事了。

gzyangfan@gmail.com

对象的两重含义
?

在数据级别

对象可以集成许多不同数据类型的信息,是一种数据的载体, 使系统可定义符合自身业务含义的数据类型。
?

在程序开发级别

对象提供模块化程序构造方式。这时,程序员在现有对象的 基础之上进行开发。对象可以被其他对象再使用,以利用它 们的过程,从而消除了当再次需要它们的时候,必须每次都 重写这些代码。

gzyangfan@gmail.com

基本理论(wiki)
?

类(Class)
? 类定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它 可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切 基础特征,例如,它的孕育、毛皮颜色和吠叫的能力。类可以为程序 提供模版和结构。一个类的方法和属性被称为“成员”。

?

对象(Object)
? 对象是类的实例。例如,“狗”这个类列举狗的特点,从而使这个类 定义了世界上所有的狗。而莱丝这个对象则是一条具体的狗,它的属 性也是具体的。狗有皮毛颜色,而莱丝的皮毛颜色是棕白色的。因此, 莱丝就是狗这个类的一个实例。一个具体对象属性的值被称作它的 “状态”。(系统给对象分配内存空间,而不会给类分配内存空间, 这很好理解,类是抽 象的系统不可能给抽象的东西分配空间,对象 是具体的)

gzyangfan@gmail.com

基本理论(wiki)
?

方法(Method)
? 方法是一个类能做的事情,但方法并没有去做这件事。作为 一条狗,莱丝是会吠叫的,因此“吠叫()”就是它的一个方 法。与此同时,它可能还会有其它方法,例如,“坐下()”, 或者“吃()”。 对一个具体对象的方法进行调用并不影响其 它对象,正如所有的狗都会叫,但是你让一条狗叫不代表所 有的狗都叫。

gzyangfan@gmail.com

面向对象的三个关键特征
数据(属性) 封装 Encapsulation 行为(方法) 继承 Inheritance 覆盖 多态 Polymorphism 重载 组合(聚合) 泛化(继承)

Java由于不支持多继承,但 可通过实现多接口,结合方法 委托(Delegate)来代替。
gzyangfan@gmail.com

面向对象的三个关键特征
?

封装性 Encapsulation
? 具备封装性的面向对象程序设计隐藏了某一方法的具体执行 步骤,取而代之的是通过消息传递机制传送消息给它。

?

继承性 Inheritance
? 继承是指这样一种能力:它可以使用现有类的所有功能,并 在无需重新编写原来的类的情况下对这些功能进行扩展。通 过继承创建的新类称为“子类”或“派生类”。被继承的类 称为“基类”、“父类”或“超类”。继承的过程,就是从 一般到特殊的过程。

?

多态性 Polymorphism
? 多态性是指由继承而产生的相关的不同的类,其对象对同一 消息会做出不同的响应。
gzyangfan@gmail.com

封装
?

封装的内容可分为
? 对象的属性/内部状态 ? 行为的具体实现 ? 系统/模块的具体实现

?

封装的特点
? 使具体实现不可视; ? 对所有的用户统一接口; ? 增强可维护性。

从系统/模块的角度来说,接口是一种对系统/模块内部的 封装。

gzyangfan@gmail.com

继承
? ? ?

当类只从一个类继承时,称为单继承 。 接口具备多继承的优点,并避免其缺点。 Java 类的继承语法如下所示:
< 修饰符> class < 名称> [extends < 超类>] { < 声明>* }

接口也可以继承接口,不过和类继承不同的是,接口可以 同时继承多个接口。

gzyangfan@gmail.com

继承示例
?

父类

public class Person { private String name; private boolean sex; private int age; public void eat() {…} public void sleep() {…}

?

子类
private String code; public void study() {…}

public class Student extends Person {

gzyangfan@gmail.com

访问控制
?

类成员声明的访问修饰符如下所示。
修饰符
private

同一个类中
是 是 是 是

同一个包中
是 是 是

子类中

全局

default
protected public

是 是 是

gzyangfan@gmail.com

覆盖方法 override
? ?

子类可以修改从父类继承的行为。 子类可以创建与父类方法功能不同的方法,但在以下 三方面是相同的:
? 名称 ? 返回类型 (Java5开始,返回类型可以是被覆盖返回类型的子类。) ? 参数列表

?

?

覆盖方法的可访问性可以被增大,但不能被缩小 满足异常规约的运行时多态
(子类方法掷出的异常必须小于等于父类的异常声明,或者不掷出)

注意,您无法重写 static 的方法或属性。
gzyangfan@gmail.com

覆盖方法示例
public class Vehicle { public void run() { System.out.println("交通工具在跑!"); } } public class Truck extends Vehicle { @Override public void run() { System.out.println("货车在地上跑!"); } } public class Airplane extends Vehicle { @Override public void run() { System.out.println("飞机在天上飞!"); } }
gzyangfan@gmail.com

覆盖方法的可访问性不能较弱
public class Employee { private String mobile; /** 雇员的联系方式不希望公开,但公司内的同事都可以拿到 */ protected String getContactInfo() { return "手机:" + mobile; } } public class Salesman extends Employee { private String msn; /** 销售人员的联系方式,则希望越多人知道越好 */ @Override public String getContactInfo() { return super.getContactInfo() + "\nMSN:" + msn; } }

gzyangfan@gmail.com

调用覆盖方法
?

子类方法使用 super 关键字可以调用超类方法:
? ? ? ? 在类中使用关键字 super 来指向它的超类。 使用关键字 super 来指向超类的成员,包括数据属性和方法。 调用的行为不必在超类中;它可以在更深的层次结构中。 在构造器中,可通过 super() 调用父类的构造器。

gzyangfan@gmail.com

多态
?

? ? ?

多态性从另外一个角度将对象从表现形态与具体的实 施细节中分离开来,即实现了“是什么”和“怎样做” 两个模块的分离。 (接口和父类都可是对象的表现形态,实现类和子类 则是具体的实施细节) Java通过覆盖和重载来实现多态性。 一个对象只有一种形式。 一个引用变量可以指向不同形式的对象。

gzyangfan@gmail.com

多态
public class Animal { public void eat() { System.out.println("动物在吃东西!"); } } public class Pet extends Animal { public String name; @Override public void eat() { System.out.println("宠物吃宠物的粮食!"); } }

?

?

?

Animal animal = new Pet(); 这是合法的 animal.name = “baby”; 这是非法的 animal.eat(); 执行的是Pet.eat()方法

gzyangfan@gmail.com

方法调用的绑定(Think in Java)
?

?

?

将一个方法调用同一个方法主体连接到一起就称为 “绑定”(Binding)。若在程序运行以前执行绑定(由 编译器和链接程序,如果有的话),就叫作“早期绑 定”。 “后期绑定”也叫作“动态绑定”或“运行期绑定” 它意味着绑定在运行期间进行,以变量的类型为基础, 在运行期间判断实例的类型,并调用适当的方法。 Java中绑定的所有方法都采用后期绑定技术,除非一 个方法已被声明成 final 。

gzyangfan@gmail.com

异类集合
?

具有相同类类型的对象集合称为同类集合。示例:
Student[] students = new Student[3]; students[0] = new Student("0001", "小明"); students[1] = new Student("0002", "小红"); students[2] = new Student("0003", "小陈");

?

具有不同类类型的对象集合称为异类集合。示例:
Animal[] animals animals[0] = new animals[1] = new animals[2] = new = new Animal[3]; Pet(); Animal(); Pet();

gzyangfan@gmail.com

多态参数
?

因为 Piano 和 Violion 都是 Instrument,所以下面内容 是有效的:
Musician musician = new Musician(); Piano piano = new Piano(); Violin violin = new Violin(); // 音乐家既可以弹奏钢琴,也可以拉小提琴 musician.performance(piano); musician.performance(violin);

gzyangfan@gmail.com

instanceof 运算符
? ?

instanceof 用于判断对象实体是否属于指定类型 示例:
public static void main(String[] args) {
System.out.println("测试父类"); check(new Instrument()); System.out.println("测试子类"); check(new Piano());

} public static void check(Object object) {
if (object instanceof Instrument) System.out.println("这是一个乐器!"); if (object instanceof Piano) System.out.println("这是一台钢琴!");

}
gzyangfan@gmail.com

对象类型转换
?

示例:
// 上溯造型 Instrument instrument = new Piano(); // 下溯造型 Piano piano = (Piano) instrument;

? ? ?

使用 instanceof 来测试对象的类型。 通过类型转换恢复对象的全部功能。 使用下面的指导方针检查正确的类型转换:
? 隐式进行层次结构中的向上转换。 ? 向下转换必须是对子类进行的,并由编译器检查。 ? 在运行时转换失败会抛出 ClassCastException。

gzyangfan@gmail.com

重载 overload
?

如下使用重载:
? public void println(int i) ? public void println(float f) ? public void println(String s)

? ?

参数列表必须不同。 返回类型可以不同。

返回值类型不可用作方法重载的区别依据。

gzyangfan@gmail.com

可变参数
?

?

使用变量参数 的方法允许在方法中使用多个参数的 成员。 示例:
public int sum(int...numbers) { int total = 0; for (int number : numbers) total += number; return total; }

?

调用示例:
demo.sum(); demo.sum(1, 2, 3); demo.sum(new int[]{1, 2, 3});

可变参也是Java5增加的 新特性,其本质是自动 装箱后的数组。

gzyangfan@gmail.com

编译器处理重载方法的顺序
?

? ? ?

寻找在还没有装箱动作前可以符合参数个数与类型的 方法 尝试装箱动作后可以符合参数个数与类型的方法 尝试没有不定长度参数并可以符合的方法 都找不到适合的方法就报告编译错误

gzyangfan@gmail.com

重载构造器
? ?

像其他方法一样,构造器也可以重载。 示例::
? public Student(String code, String name) ? public Student(String code, String name, int age) ? public Student(String code, String name, int age, boolean sex)

? ?

参数列表必须不同。 在构造器的第一行使用 this 引用来调用另一个构造 器。

gzyangfan@gmail.com

重载构造器示例
public Student(String code, String name) { this.code = code; this.name = name; } public Student(String code, String name, int age) { this(code, name); this.age = age; } public Student(String code, String name, int age, boolean sex) { this(code, name); this.age = age; this.sex = sex; }

gzyangfan@gmail.com

构造器不能继承
? ? ?

子类从超类(父类)继承所有的方法和变量。 子类不从超类继承构造器。 获得构造器的两种方法是:
? 使用缺省构造器。 ? 编写一个或多个显式构造器。

gzyangfan@gmail.com

调用父类构造器
?

? ?

要调用父类构造器,必须在构造器的第一行调用 super。 通过调用 super 的参数可以调用特定的父类构造器。 如果构造器中没有使用 this 或 super 调用,那么编 译器会给调用父类无参数的构造器(可以是缺省构造 器)super() 添加一个隐式调用。 如果父类定义了构造器,但没有提供无参数的构造器, 那么将产生一条编译器错误消息。

gzyangfan@gmail.com

调用父类构造器示例
public class Parent { protected String name; public Parent(String name) { this.name = name; } } public class Child extends Parent { private String name; public Child() { this(null, null); } public Child(String name, String nickname) { super(name); this.name = nickname; } }
gzyangfan@gmail.com

构造和初始化对象步骤
? ?

分配内存和进行缺省初始化。 实例变量的初始化按照如下步骤递归进行:
? ? ? ? ? 1. 绑定构造器参数 2. 如果显式使用 this(),递归调用,然后跳至第 5 步。 3. 递归调用隐式或显式的 super 调用, Object 除外。 4. 执行显式的实例变量初始化。 5. 执行当前构造器的构造体。

gzyangfan@gmail.com

Object 类
? ? ?

在 Java 中,Object 类是所有类的根。 没有 extends 子句的类声明含有 extends Object。 示例:
public class Employee {…}

等同于:
public class Employee extends Object {…}
?

两个重要的方法是:
? equals ? toString

gzyangfan@gmail.com

equals 方法
?

?

? ?

== 运算符确定两个引用是否相同(即引用同一对 象)。 equals 方法确定对象逻辑上是否相等,但没必要相 同。 equals 方法的 Object 实现使用 == 运算符。 用户类可以覆盖 equals 方法来实现特定域的相等测 试。

注意:如果覆盖 equals 方法,则应该覆盖 hashCode 方 法。如果不这样做的话,就会违反 Object.hashCode 的 通用约定,从而导致该类无法和基于散列的集合 ( HashMap、HashSet 和 Hashtable )一起工作。
gzyangfan@gmail.com

hashCode 约定内容
?

?

?

只要对象的 equals 方法的比较操作所用到的信息没 有被修改,那么对这个对象不管调用多少次 hashCode 方法必须返回同一个整数。 如果两个对象根据 equals 方法比较是相等的,那么 调用这两个对象的 hashCode 方法都必须产生相同 的整数结果。 如果两个对象根据 equals 方法比较是不相等的,那 么调用这两个对象的 hashCode 方法,不一定非要 产生不同的整数结果。但给不等的对象产生不同的 hashCode 结果,可以提高散列表的性能。

gzyangfan@gmail.com

toString 方法
?

toString 方法具有如下特征:
? ? ? ? 该方法将对象转换成 String。 该方法用于字符串连接。 通过覆盖此方法以提供给用户更为易读的对象信息。 使用 wrapper 类的 toString 静态方法来将基本类型转换为 String。

gzyangfan@gmail.com

finalize 方法
?

?

当垃圾回收器将要释放无用对象的内存时,先调用该 对象的 finalize 方法。如果在程序终止之前垃圾回收 器始终没有 执行垃圾回收操作,那么垃圾回收器将 始终不会调用无用对象的 finalize 方法。 finalize 方法的特点:
? 垃圾回收器是否会执行该方法及何时执行该方法,都是不确 定的。 ? finalize 方法有可能使对象复活,使它恢复到可触及状态。 ? 垃圾回收器在执行 finalize 方法时,如果出现异常,垃圾回 收器不会报告异常,程序继续正常运行。

对 finalize 方法的最佳忠告就是,永远不要使用该方法。
gzyangfan@gmail.com

clone 方法
? ? ?

clone 用于实现对象的克隆/拷贝。 要使用 clone 方法的对象,要实现 Cloneable 接口。 示例:
public class Person implements Cloneable { String name; int age; boolean sex; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
gzyangfan@gmail.com

wrapper 类
将基本数据类型看作对象。
基本数据类型 boolean char byte short int long float double Wrapper 类 Boolean Character Byte Short Integer Long Float Double

gzyangfan@gmail.com

wrapper 类
?

wrapper 类的示例:
int pInt = 420; Integer wInt = new Integer(pInt); // 这叫装箱 int p2 = wInt.intValue(); // 这叫拆箱

?

其他方法是:
int x = Integer.valueOf(string).intValue(); int x = Integer.parseInt(string);

gzyangfan@gmail.com

基本类型的自动装箱
对自动装箱的描述如下: ? 将基本类型转换为等价的对象 ? 不是总需要 Wrapper 类 ? 示例:
int pInt = 420; Integer wInt = pInt; // 自动装箱 int p2 = wInt; // 自动拆箱
? ? ?

处理集合时最常使用的语言特性 打包的基本类型也用于算术表达式中 使用自动装箱时性能丢失

gzyangfan@gmail.com


网站首页 | 网站地图 | 学霸百科 | 新词新语
All rights reserved Powered by 大学生考试网 9299.net
文档资料库内容来自网络,如有侵犯请联系客服。zhit325@qq.com