Java核心技术卷感悟:第四章 对 象 与 类


面向 对象程序设计与面向过程程序设计在思维方式上存在着很大的差别,面向对象程序设计(简称 OOP) 是当今主流的程序设计范型,Java 是完全面向对象的.

面向对象程序设计概述:

面向对象的程序是由对象组成的, 每个对象包含对用户公开的特定功能部分和隐藏的实现部分。面向对象更加适用于解决规模较大的问题.

  1. 类( class) 是构造对象的模板或蓝图。由类构造(construct) 对象的过程称为创建类的实例 (instance )
  2. 封装 是与对象有关的一个重要概念。从形式上看, 封装是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式,封装给对象赋予了“ 黑盒” 特征, 这是提高重用性和可靠性 的关键。对象 中的数据称为成员变量( instance field ), 操纵数据的过程称为方法( method 。) 对于每个特定的 类实例(对象)都有一组特定的成员变量值。这些值的集合就是这个对象的当前状态( state )。
  3. 通过扩展一个类来建立另外一个 类的过程称为继承(inheritance),在扩展一个已有的类时, 这个扩展后的新类具有所扩展的类的全部属性和方法。在新类 中,只需提供适用于这个新类的新方法和数据域就可以了。
  4. 对象的三个主要特性:
  5. 对象的行为(behavior) —可以对对象施加哪些操作,或可以对对象施加哪些方法?
  6. 对象的状态(state ) —当施加那些方法时,对象如何响应?
  7. 对象标识(identity ) —如何辨别具有相同行为与状态的不同对象?
  8. 识别类的简单规则是在分析问题的过程中寻找名词,而方法对应着动词。
  9. 在类之间, 最常见的关系有:依赖、聚合、继承。依赖( dependence ), 即“ uses-a” 关系, 是一种最明显的、 最常见的关系。例如,Order 类使用 Account 类是因为 Order 对象需要访问 Account 对象查看信用状态。应该尽可能地将相互依赖的类减至最少,用软件工程的术语来说,就是 让类之间的耦合度最小。聚合(aggregation ), 即“ has-a ” 关系, 是一种具体且易于理解的关系。例如, 一个 Order 对象包含一些 Item 对象。聚合关系意味着类 A 的对象包含类 B 的对象。继承( inheritance ), 即“ is-a” 关系, 是一种用于表示特殊与一般关系的。例如,Rush Order类由 Order 类继承而来,Rush Order类具有Order类的一些属性和方法。

类:

  1. 在 Java 中, 没有类就无法做任何事情,然而,并不是所有 的类都具有面向对象特征。例如:Math 类只封装了功能,它不需要也不 必隐藏数据。由于没有数据,因此也不必担心生成对象以及初始化成员变量。
  2. 要想使用对象,就必须首先构造对象, 并指定其初始状态,构造器是一种特殊的方法, 用来构造并初始化对象。构造器的名字应该与类名相同,要想构造一个 Date 对 象, 需要在构造器前面加上 new 操作符。new Date()构造器与类同名 、每个类可以有一个以上的构造器 、构造器可以有 0 个、1 个或多个参数 、构造器没有返回值 、构造器总是伴随着 new 操作一起调用
  3. 对象与对象变量之间存在着一个重要的区别,定义了一个对象变量 deadline, 它 可 以 引 用 Date 类型的对象。但是,一定要认识到: 变量 deadline 不是一个对象, 实际上也没有引用对象。此时,不能将任何 Date 方法应用于这个变 量上。Date deadline;s = deadline.toString(); // not yet必须首先初始化变量 deadline,deadline = new Date();一定要认识到,一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。
  4. raiseSalary 方法有两个参数。 第一个参数称为隐式 参数, 是出现在方法名前的 Employee 类对象。第二个参数位于方法名后面括号中的数值,这是一个显式 参 数 number007. raiseSalary(5);
  5. 私有方法,在实现一个类时,由于公有数据非常危险, 所以应该将所有的数据域都设置为私有的。然 而,方法又应该如何设计呢?尽管绝大多数方法都被设计为公有的,但在某些特殊情况下,也 可能将它们设计为私有的。然而,只要方法是 私有的,类的设计者就可以确信:它不会被外部的其他类操作调用,可以将其删去。如果方 法是公有的, 就不能将其删去,因为其他的代码很可能依赖它
  6. final 成员变量,可以将成员变量定义为 final。 构建对象时必须初始化这样的域。也就是说, 必须确保在每 一个构造器执行之后,这个域的值被设置, 并且在后面的操作中, 不能够再对它进行修改。
  7. 静态变量,如果将域定义为 static, 每个类中只有一个这样的域。而每一个对象对于所有的实例域 却都有自己的一份拷贝。静态变量使用得比较少,但静态常量却使用得比较多。在 Math 类中定义了一个 静态常量:Math.Pi。静态方法是一种不能向对象施加操作的方法,例如, Math 类的 pow 方法就是一个静态 方法。静态方法不能访问实例域, 因为它不能操作实例对象。但是,静态方法可 以操作自身类中的静态域。当然,也可以使用对象调用静态方法,不过,这种方式很容易造成混淆,其原因 是静态 方法计算的结果与 实例对象 毫无关系。
  8. main 方法不对任何对象进行操作。事实上,在启动程序时还没有任何一个对象。静态的 main 方法将执行并创建程序所需要的对象。

方法参数:

按 值调用 (call by value) 表示方法接收的是调用者提供的值。而按引用调用 ( call by reference) 表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而 不能修改传递值调用所对应的变量值

方法参数共有两种类型:基本数据类型(数字、布尔值)、对象引用。一个方法不可能修改一个基本数据类型的参数,而对象引用作为参数就不同了,对象引用及其他的拷贝是同时引用同一个对象。

对 象 构 造:

  1. 重载,有些类有多个构造器,这种特征叫做重载( overloading)。 如果多个方法(比如, StringBuilder 构造器方法)有 相同的名字、 不同的参数,便产生了重载。Java 允许重载任何方法, 而不只是构造器方法。重载解析:这个过程是如 果编译器找不到匹配的参数, 就会产生编译时错误,因为根本不存在匹配, 或者没有一个比 其他的更好。
  2. 默认初始化,如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值: 数值为 0、 布尔值为 false、 对象引用为 null。同数组。
  3. 无参数的构造器,很多类都包含一个无参数的构造函数,对象由无参数构造函数创建时, 其状态会设置为 适当的默认值。如果在编写一个类时没有编写构造器, 那么系统就会提供一个默认的无参数构造器。这个构造 器将所有的实例域设置为默认值。如果类中提供了至少一个构造器, 那么就会重载默认的无参构造器。仅当类没有提供任何构造器的时候, 系统才会提供一个默认的构造器
  4. 显式初始化,可以在类定义中, 直接将一个值赋给任何属性,在执行构造器之前,先执行赋值操作。
  5. 如果构造器的第一个语句形如 this(...), 这个构造器将调用同一个类的另一个构造器。
  6. 初始化块,在一个类的声明中, 可以包含多个代码块,只要构造类的对象,这些块就会被执行。无论使用哪个构造器构造对象,首 先运行初始化块,然后才运行构造器的主体部分。这种机制不是必需的,也不常见。通常会直接将初始化代码放在构造器中
  7. 静态的初始化块,将代码放在一个块中,并标记关键字 static。在类第一次加载的时候, 将会进行静态域的初始化。
  8. 调 用构造器的具体处理步骤:
  9. 所有属性被默认初始化为默认值(0、false 或 null)。
  10. 按照在类声明中出现的次序, 依次执行初始化块。
  11. 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体
  12. 执行这个构造器的主体

包:

Java 允许使用包( package ) 将类组织起来。借助于包可以方便地组织自己的代码,并将 自己的代码与别人提供的代码库分开管理。使用包的主要原因是确保类名的唯一性。

  1. 一个类可以使用所属包中的所有类, 以及其他包中的公有类( public class)。
  2. 要想将一个类放人包中, 就必须将包的名字放在源文件的开头,包中定义类的代码之 前。package com.horstiann.corejava; public class Employee { }
  3. 标记为 public 的部分可以被任意的类使 用;标记为 private 的部分只能被定义它们的类使用。如果没有指定 public 或 private , 这 个 部 分(类、方法或变量)可以被同一个包中的所有方法访问。

文档注释:

JDK 包含一个很有用的工具,叫做javadoc, 它可以由源文件生成一个 HTML 文档。

类设计技巧:

  1. 一定要保证数据私有。这是最重要的,绝对不要破坏封装性。
  2. 一定要对数据初始化。Java 不对局部变量进行初始化, 但是会对对象的实例域进行初始化。最好不要依赖于系 统的默认值, 而是应该显式地初始化所有的数据
  3. 不要在类中使用过多的基本类型。就是说,用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且易于 修改。
  4. 不是所有的域都需要独立的域访问器和域更改器
  5. 将职责过多的类进行分解。如果明 显地可以将一个复杂的类分解成两个更为简单的类,就应该将其分解
  6. 类名和方法名要能够体现它们的职责。
  7. 优先使用不可变的类。更改对象的问题在于, 如果多个线程试图同时更新一个对象,就会发生并发更改。


0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP