[JAVA语言入门] 第五章 Java的类

发布时间:2010年04月28日      浏览次数:284 次
类 是Java语 言 面 向 对 象 编 程 的 基 本 元 素, 它 定 义 了 一 个 对 象 的 结 构 和 行 为。 在Java程 序 里, 你 要 表 达 的 概 念 封 装 在 某 个 类 里。 一 个 类 定 义 了 一 个 对 象 的 结 构 和 它 的 功 能 接 口, 功 能 接 口 称 为 成 员 函 数。 当Java程 序 运 行 时, 系 统 用 类 的 定 义 创 建 类 的 实 例, 类 的 实 例 是 真 正 的 对 象。 类 定 义 的 一 般 形 式 如 下:
class classname extends superclassname { type instance-variable1; type instance-variable2; ................................. type instance-variableN; type methodname1(parameter-list) { method-body; } type methodname2(parameter-list) { method-body; } ....................................................type methodnameN(parameter-list) {method-body; } }
这 里,classname和superclassname是 合 法 的 标 识 符。 关 键 词extends用 来 表 明classname是 superclassname派 生 的 子 类。 有 一 个 类 叫 做Object, 它 是 所 有Java类 的 根。 如 果 你 想 定 义Object 的 直 接 子 类, 你 可 以 省 略extends子 句, 编 译 器 会 自 动 包 含 它。 下 面 是 一 个 简 单 的 类 的 定 义。 class University { }
5.1 对 象 实 例
类 名 可 以 作 为 变 量 的 类 型 来 使 用, 如 果 一 个 变 量 的 类 型 是 某 个 类, 那 么 它 将 指 向 这 个 类 的 实 例, 称 为 对 象 实 例。 所 有 对 象 实 例 和 它 们 的 类 型(某 个 类?copy; 的 子 类 的 实 例 都 是 相 容 的。 就 象 可 以 把byte型 的 值 赋 给int型 的 变 量 一 样, 你 可 以 把Object的 子 类 的 任 何 实 例 赋 给 一 个Object型 的 变 量。 一 个 实 例 是 类 模 板 的 单 独 的 拷 贝, 带 有 自 己 的 称 为 实 例 变 量 的 数 据 集。 每 个 实 例 也 可 以 作 为 一 个 对 象。 当 你 定 义 一 个 变 量 的 类 型 是 某 个 类 时, 它 的 缺 省 值 是null,null是Object的 一 个 实 例。 对 象null没 有 值, 它 和 整 数0不 同。 下 面 这 个 例 子 中, 声 明 变 量u的 类 型 是 类University。 University u; 这 里, 变 量u的 值 是null。
5.2 实 例 变 量
Java通 过 在 类 定 义 的 大 括 号 里 声 明 变 量 来 把 数 据 封 装 在 一 个 类 里。 这 里 的 变 量 称 为 实 例 变 量。 下 面 的 例 子 定 义 了 一 个 叫 做University的 类, 它 有 两 个 实 例 变 量:name和city。 class University{ String name, city; }
5.3 new操 作 符
操 作 符new用 来 生 成 一 个 类 的 实 例, 下 面 这 个 例 子 生 成 了 类University的 一 个 实 例, 存 放 在 变 量u中。
University u = new University( ); 在 此 例 中, 变 量u指 向 这 个 对 象, 但 并 不 真 正 包 含 这 个 对 象。 你 可 以 用 多 个 变 量 指 向 同 一 个 对 象。 下 面 的 例 子 中, 创 建 了 一 个University的 对 象, 但 创 建 了 两 个 指 向 它 的 变 量。
University u = new University(); University u2 = u;
对u2所 指 向 的 对 象 的 任 何 改 动 都 会 对u所 指 向 的 对 象 起 作 用, 因 为 它 们 是 同 一 个 对 象。 对u和u2的 赋 值 只 是 把 它 们 指 向 这 个 对 象, 既 没 有 分 配 内 存, 也 没 有 复 制 这 个 对 象 的 任 何 部 分。 对u的 再 赋 值 只 是 简 单 地 去 掉 了u和 原 来 对 象 的 联 系, 并 不 影 响 对 象 本 身, 下 面 的 例 子 说 明 了 这 种 情 况。
University u = new University( ); University u2 = u; u = null;
尽管u被 赋 值 为null,u2仍 指 向 原 来 由 操 作 符new创 建 的 对 象。 在 前 面 的 例 子 里, 我 们 生 成 了 一 个 对 象 并 且 指 向 了 它 两 次。 这 就 允 许 两 个 变 量 改 变 同 一 个 对 象。 创 建 一 个 新 的 对 象 时, 可 直 接 对 它 的 实 例 变 量 赋 值。 每 个 对 象 都 有 它 所 属 类 的 实 例 变 量 的 拷 贝, 每 个 对 象 的 实 例 变 量 都 是 和 其 他 对 象 的 实 例 变 量 分 离 的, 所 以 改 变 一 个 对 象 的 实 例 变 量 不 会 影 响 其 他 对 象 的 实 例 变 量。 下 面 的 例 子 创 建 了 两 个University的 对 象, 并 对 它 们 分 别 赋 值: class TwoUniversity { public static void main(String args[]) { University u1 = new University( ); University u2 = new University( ); u1.name = \"北 ?copy; 大 学\"; u1.city = \"北 ?copy;\"; u2.name = \"清 华 大 学\"; u2.city = \"北 ?copy;\"; System.out.println(\"大 学:\" + u1.name + \" 城 市:\" + u1.city); System.out.println(\"大 学:\" + u2.name + \" 城 市:\" + u2.city); } } 这 个 例 子 创 建 了 两 个University的 对 象, 并 且 对 它 们 的name、city分 别 赋 了 不 同 的 值, 这 说 明 这 两 个 对 象 是 真 正 分 离 的。 下 面 是 该 程 序 运 行 后 的 输 出 结 果。 C:\\>java TwoUniversity 大 学: 北 ?copy; 大 学 城 市: 北 ?copy; 大 学: 清 华 大 学 城 市: 北 ?copy;
5.4 点(.?copy; 操 作 符点(.?copy; 操 作 符 用 来 接 收 一 个 对 象 的 实 例 变 量 和 成 员 函 数。 下 面 是 用 点 操 作 符 来 接 收 实 例 变 量 的 一 般 形 式。 objectreference.variablename
这 里objectreference是 一 个 对 象 实 例,variablename是 这 个 对 象里 你 想 接 收 的 实 例 变 量。 下 面 的 程 序 段 说 明 了 怎 样 用 点 操 作 符 来 给 实 例 变 量 赋 值。
u.name = \"北 ?copy; 大 学\"; u.city = \"北 ?copy;\"; 下 面 说 明 怎 样 用 点 操 作 符 来 得 到 实 例 变 量 的 值。 System.out.println(\"大 学:\" + u.name + \" 城 市:\" + u.city); 通 过 向 类University里 加 入 一 个 成 员 函 数main, 我 们 创 建 了 一 个 完 整 的 例 子, 它 使 用 了new 操 作 符 来 创 建 一 个University, 用 点 操 作 符 来 赋 值, 然 后 打 印 结 果。 class University { String name, city; public static void main(String args[]) { University u = new University( ); u.name = \"北 ?copy; 大 学\"; u.city = \"北 ?copy;\"; System.out.println(\"大 学:\" + u.name + \" 城 市:\" + u.city); } }
运 行 这 个 程 序 后, 就 会 得 到 下 面 的 结 果。 C:\\>java University 大 学: 北 ?copy; 大 学 城 市: 北 ?copy;
5.5 成 员 函 数 定 义
成 员 函 数, 是 类 的 功 能 接 口, 是 类 定 义 里 的 一 个 子 程 序, 在 类 的 定 义 里 和 实 例 变 量 处 于 同 一 级 别。 你 必 须 通 过 一 个 类 的 实 例 来 调 用 成 员 函 数。 成 员 函 数 可 以 不 用 点 操 作 符 而 直 接 使 用 实 例 变 量。 成 员 函 数 带 有 输 入 参 数, 具 有
某 种 类 型 的 返 回 值。 成 员 函 数 定 义 的 一 般 形 式 如 下: type methodname ( formal-parameter-list ) { method-body; } 这 里type指 的 是 成 员 函 数 的 返 回 值 的 类 型, 如 果 没 有 返 回 值, 就 用 无 值(void?copy; 类 型。 methodname可 以 是 任 何 合 法 的 标 识 符, 但 不 能 与 当 前 的 类 名 相 同。formal-parameter-list是 用 逗 号 分 隔 的 类 型、 标 识 符 对 的 序 列。 如 果 没 有 参 数, 括 号 里 就 是 空 的。 还 是 用 我 们 的University的 例 子, 下 面 的 成 员 函 数 用 来 初 始 化 两 个 实 例 变 量。 成 员 函 数 是 在 类 的 大 括 号 ?reg; 内 定 义 的, 和 实 例 变 量 所 处 的 范 围 相 同。 class University { String name, city; void init(String a, String b) { name = a; city = b; } }
注 意, 我 们 这 里 直 接 给name和city赋 值, 而 没 有 象 以 前 那 样 用u1.name。 这 是 因 为 每 个 成 员 函 数 都 在 类 的 个 别 实 例 内 执 行。 我 们 创 建 的 类 的 实 例 具 有 它 自 己 的 实 例 变 量, 所 以 成 员 函 数 可 直 接 使 用 它 们。
5.6 成 员 函 数 调 用
可 以 用 点(.?copy; 操 作 符 来 调 用 一 个 类 的 实 例 的 成 员 函 数。 成 员 函 数 调 用 的 一 般 形 式 如 下: objectreference.methodname( parameter-list ); 这 里,objectreference是 指 向 某 个 对 象 的 变 量,methodname是objectreference所 属 类 的 一 个 成 员 函 数,parameter-list是 用 逗 号 分 隔 的 变 量 或 表 达 式 的 序 列, 它 们 要 与 该 成 员 函 数 的 定 义 的 参 数 个 数 及 类 型 匹 配。 在 这 个 例 子 里, 我 们 可 以 对 任 何University对 象 调 用 成 员 函 数init来 给name和city赋 值。 下 面 的 程 序 段 说 明 了 怎 样 完 成 这 个 工 作。 University u = new University( ); u.init(\"北 ?copy; 大 学\", \"北 ?copy;\"); 这 个 例 子 创 建 了University的 一 个 实 例, 存 放 在u中。 通 过 点 操 作 符 来 调 用 这 个 实 例 的init 成 员 函 数, 把\"北 ?copy; 大 学\"和\"北 ?copy;\"分 别 传 递 给 参 数a和b。 在init成 员 函 数 内 部,name和city 直 接 指 向u所 指 向 的 对 象 的 实 例 变 量。 把name 赋 值 为\"北 ?copy; 大 学\",city赋 值 为\"北 ?copy;\", 然 后 返 回。 在 这 个 例 子 里,init被 定 义 为 无 值(void?copy; 返 回 类 型。 在 进 行 这 个 成 员 函 数 调 用 后,u指 向 这 个name值 和city值 改 变 了 的University对 象。
5.7 this Java有 一 个 特 殊 的 实 例 值 叫this, 它 用 来 在 一 个 成 员 函 数 内 部 指 向 当 前 的 对 象。 在 前 面 的 例 子 里, 我 们 调 用u.init, 一 ?copy; 进 入init成 员 函 数 内 部,this就 会 指 向u所 指 向 的 对 象。 在Java里, 在 同 一 个 范 围 定 义 两 个 相 同 名 字 的 局 部 变
量 是 不 可 以 的。 有 趣 的 是, 局 部 变 量、 成 员 函 数 的 参 数 可 以 和 实 例 变 量 的 名 字 相 同。 前 面 我 们 没 有 用name和city作 为 成 员 函 数init的 参 数 名 字, 因 为 这 样 它 们 在 成 员 函 数 的 范 围 里 就 把 实 例 变 量name和city隐 藏 了, 即name指 向 参 数name, 隐 藏 了 实 例 变 量name。this让 我 们 可 以 直 接 指 向 对 象 本 身。 下 面 是 另 一 个 版 本 的 init, 用name和city作 为 参 数 名 字, 用this来 接 收 当 前 对 象 的 实 例 变 量。
void init(String name, String city) { this.name = name; this.city = city; } 下 面 是 带 有 新 的init初 始 成 员 函 数 的TwoUniversity例 子。 class University { String name, city; void init(String name, String city) { this.name = name; this.city = city; } } class TwoUniversityInit { public static void main(String args[]) { University u1 = new University( ); University u2 = new University( ); u1.init(\"北 ?copy; 大 学\", \"北 ?copy;\"); u2.init(\"清 华 大 学\", \"北 ?copy;\"); System.out.println(\"大 学:\" + u1.name + \" 城 市:\" + u1.city); system.out.println(\"大 学:\" + u2.name + \" 城 市:\" + u2.city); } }
5.8 构 造 函 数(Constructor)
每 创 建 一 个 类 的 实 例 都 去 初 始 化 它 的 所 有 变 量 是 乏 味 的。 如 果 一 个 对 象 在 被 创 建 时 就 完 成 了 所 有 的 初 始 工 作, 将 是 简 单 的 和 简 洁 的。 因 此,Java在 类 里 提 ?copy 了 一 个 特 殊 的 成 员 函 数, 叫 做 构 造 函 数(Constructor?copy;。 一 个 构 造 函 数 是 对 象 被 创 建 时 初 始 对 象 的 成 员 函 数。 它 具 有 和 它 所 在 的 类 完 全 一 样 的 名 字。 一 ?copy; 定 义 好 一 个 构 造 函 数, 创 建 对 象 时 就 会 自 动 调 用 它。 构 造 函 数 没 有 返 回 类 型, 即 使 是void类 型 也 没 有。 这 是 因 为 一 个 类 的 构 造 函 数 的 返 回 值 的 类 型 就 是 这 个 类 本 身。 构 造 函 数 的 任 务 是 初 始 一 个 对 象 的 内 部 状 态, 所 以 用new操 作 符 创 建 一 个 实 例 后, 立 刻 就 会 得 到 一 个 清 楚、 可 用 的 对 象。 下 面 这 个 例 子 里, 用 构 造 函 数 取 代 了 成 员 函 数init。
class University { String name, city; University(String name, String city)
{ this.name = name; this.city = city; } } class UniversityCreate { public static void main(String args[]) { University u = new University(\"北 ?copy; 大 学\", \"北 ?copy;\"); System.out.println(\"大 学:\" + u.name + \" 城 市:\" + u.city); } } new语 句 中 类 名 后 的 参 数 是 传 给 构 造 函 数 的。
5.9 成 员 函 数 重 载
对 于 几 个 意 义 相 近 的 成 员 函 数, 有 时 使 用 相 同 的 名 字 便 于 理 解。 因 此,Java语 言 实 现 了 成 员 函 数 重 载, 即 可 以 创 建 几 个 名 字 相 同、 参 数 不 同 的 成 员 函 数。 成 员 函 数 重 载 提 ?copy; 了Java的 多 态 行 为。 下 面 的 例 子 用 到 了 重 载。 class University { String name, city; University(String name, String city) { this.name = name; this.city = city; } University( ) { name = \"北 ?copy; 大 学\"; city = \"北 ?copy;\"; } }
class UniversityCreateAlt { public static void main(String args[]) { University u = new University( ); System.out.println(\"大 学:\" + u.name + \" 城 市:\" + u.city); } }
这 个 例 子 创 建 了 一 个University对 象, 调 用 了 第 二 个 构 造 函 数。 下 面 是 它 的 运 行 结 果。
C:\\>java UniversityCreateAlt 大 学: 北 ?copy; 大 学 城 市: 北 ?copy; 一 个 构 造 函 数 可 以 调 用 另 一 个 构 造 函 数 来 创 建 实 例。 例 如:
class University { String name, city; University(String name, String city)
{ this.name = name; this.city = city; } University( ) { this(\"北 ?copy; 大 学\", \"北 ?copy;\"); } }
第 二 个 构 造 函 数 调 用 了 第 一 个 构 造 函 数 来 完 成 实 例 的 初 始 化。 你 也 可 以 用 重 载 来 创 建 一 般 的 成 员 函 数。 下 面 这 个 例 子 里 有University类 的 两 个 版 本 的 samecity成 员 函 数。samecity判 断 一 个 大 学 是 否 在 一 个 城 市 里 或 一 个 大 学 和 另 一 个 大 学 是 否 在 同 一 个 城 市 里。 一 个 成 员 函 数 用city作 参 数, 另 一 个 用University对 象 作 参 数。
class University { String name, city; University(String name, String city)
{ this.name = name; this.city = city; } boolean samecity(String city) { if
(city.equals(this.city)) return true; else return false; } boolean
samecity(University u) { return samecity(u.city); } }
class UniversityCity { public static void main(String args[]) { String
city = \"上海\"; University u1 = new University(\"北 ?copy; 大 学\", \"
北 ?copy;\"); University u2 = new University(\"清 华 大 学\", \"北 ?copy;\");
System.out.println(\"u1 = \" + u1.name + \", \" + u1.city);
System.out.println(\"u2 = \" + u2.name + \", \" + u2.city);
System.out.println(\"city = \" + city);
System.out.println(\"u1.samecity(u2) = \" + u1.samecity(u2));
System.out.println(\"u1.samecity(city) = \" + u1.samecity(city)); } }
下 面 是 该 程 序 的 运 行 结 果。
C:\\>java UniversityCity u1 = 北 ?copy; 大 学, 北 ?copy; u2 = 清 华 大 学, 北 ?copy; city = 上海 u1.samecity(u2) = true u1.samecity(city) = false
5.10 继 承
第 二 个 基 本 的 面 向 对 象 机 制 是 继 承。 继 承 是 关 于 有 层 次 关 系 的 类 ?reg; 间 的 概 念。 一 个 类 的 后 代 可 以 继 承 它 的 祖 先 的 所 有 变 量 和 成 员 函 数, 就 象 创 建 自 己 的 一 样。 一 个 类 的 直 接 父 亲 叫 做 它 的 超 类(superclass?copy;。 一 ?copy; 你 创 建 了 一 个 象University这 样 的 类, 创 建 它 的 子 类 是 很 简 单 的。 一 个 类 的 子 类 是 它 的 继 承 了 实 例 变 量 和 成 员 函 数 的 特 殊 的 版 本。 在 这 个 例 子 里, 我 们 把University类 派 生 为 含 有 叫 做country的 第 三 个 元 素 的 子 类。
class UniversityWorld extends University { String country; UniversityWorld(String name, String city, String country) { this.name = name; this.city = city; this.country = country; } UniversityWorld( ) { this(\"北 ?copy; 大 学\", \"北 ?copy;\", \"中 国\"); } }
关 键 词extends用 来 表 示 我 们 要 创 建University的 子 类。name和city不 需 再 在UniversityWorld 中 进 行 声 明, 因 为 它 们 是 从University中 继 承 的。Java允 许 在UniversityWorld中 声 明 变 量name 和city, 但 这 会 隐 藏University中 的name和city, 是 与 使 用 子 类 的 目 的 相 矛 盾 的, 应 当 避 免。 在 UniversityWorld的 实 例 中name、city和country的 地 位 是 一 样 的。
5.11 super 在UniversityWorld的 例 子 里, 有 一 段 代 码 和 它 的 超 类University的 重 复, 这 段 代 码 是 初 始 化 name和city的, this.name = name; this.city = city; 就 象 在University例 子 中 用this指 向 第 一 个 构 造 函 数 一 样, 在Java里 有 另 一 个 变 量 叫 做 super, 它 直 接 指 向 超 类 的 构 造 函 数。 下 面 这 个 例 子 用super来 初 始 化 变 量name和city, 然 后 打 印 出 这 个 对 象 的 内 容。
class UniversityWorld extends University { String country; UniversityWorld(String name, String city, String country) { super(name, city); // 调 用 了 构 造 函 数University(name, city) this.country = country; } public static void main(String args[]) { UniversityWorld u = new UniversityWorld(\"北 ?copy; 大 学\", \"北 ?copy;\", \"中 国\"); System.out.println(\"大 学:\" + u.name + \" 城 市:\" + u.city + \" 国 家:\" + u.country); } }
下 面 是 运 行 结 果。 C:\\>java UniversityWorld 大 学: 北 ?copy; 大 学 城 市: 北 ?copy; 国
家: 中 国
5.12 成 员 函 数 的 覆 盖
这 个University的 新 的 子 类 继 承 了 它 的 超 类 的 成 员 函 数samecity。 但 这 个 成 员 函 数samecity 判 断 的 是 两 个 城 市 的 名 字, 这 是 不 够 的, 因 为 有 可 能 两 个 两 个 名 字 一 样 的 城 市 属 于 不 同 的 国 家, 我 们 要 用 同 时 判 断 城 市 和 国 家 的 成 员 函 数 来 覆 盖 它。 下 面 就 是 实 现 覆 盖 的 例 子。
class University { String name, city; University(String name, String city)
{ this.name = name; this.city = city; } boolean samecity(String city) { if
(city.equals(this.city)) return true; else return false; } boolean
samecity(University u) { return samecity( u.city); } }
class UniversityWorld extends University { String country;
UniversityWorld(String name, String city, String country) { super(name,
city); this.country = country; } boolean samecity(String city, String
country) { if (city.equals(u.city) && country.equals(u.country)) return
true; else return false; } boolean samecity(UniversityWorld other)
{ return distance(other.city, other.country); } }
class UniversityWorldCity { public static void main(String args[])
{ String city = \"上海\"; String country = \"中 国\"; UniversityWorld u1 =
new UniversityWorld(\"北 ?copy; 大 学\", \"北 ?copy;\", \"中 国\");
UniversityWorld u2 = new UniversityWorld(\"清 华 大 学\", \"北 ?copy;\", \"
中 国\"); System.out.println(\"u1 = \" + u1.name + \", \" + u1.city + \", \" +
u1.country); System.out.println(\"u2 = \" + u2.name + \", \" + u2.city+ \",
\" + u2.country); System.out.println(\"city = \" + city + \", country = \" +
country); System.out.println(\"u1.samecity(u2) = \" + u1.samecity(u2));
System.out.println(\"u1.samecity(city, country) = \" + u1.samecity(city,
country)); } }
下 面 是 输 出 结 果。
C:\\>java UniversityWorldCity u1 = 北 ?copy; 大 学, 北 ?copy;, 中 国 u2= 清 华 大 学, 北 ?copy;, 中 国 city = 上海, country = 中 国 u1.samecity(u2) = true u1.samecity(city, country) = false
5.13 动 态 成 员 函 数 发 送
当 你 用 点 操 作 符 调 用 一 个 对 象 实 例 的 成 员 函 数 时, 对 象 实 例 所 属 的 类 在 编 译 时 要 被 检 查, 以 确 保 调 用 的 成 员 函 数 在 该 类 中 是 存 在 的。 在 运 行 时, 对 象 实 例 可 以 指 向 所 声 明 类 型 的 子 类 的 实 例。 在 这 ?copy; 情 况 下, 如 果 子 类 覆 盖 了 要 调 用 的 成 员 函 数,Java就 用 实 例 来 决 定 调 用 哪 一 个 成 员 函 数。 如 下 面 的 例 子, 两 个 类 是 子 类 和 超 类 的 关 系, 子 类 覆 盖 了 超 类 的 成 员 函 数。
class A { void callme( ) { System.out.println(\"在A的callme成 员 函 数 里\"); } }
class B extends A { void callme( ) { System.out.println(\"在B的callme成 员 函 数 里\"); } }
class Dispatch { public static void main(String args[]) { A a = new B( ); a.callme( ); } }
有 趣 的 是, 在 成 员 函 数main里, 我 们 把 变 量a声 明 为 类 型A, 然 后 把 类B的 一 个 实 例 存 放 到 它 上 面。 我 们 在a上 调 用 成 员 函 数callme,Java编 译 器 确 定 在 类A确 实 有 成 员 函 数callme, 但 是 在 运 行 时, 由 于a事 实 上 是B的 实 例, 所 以 调 用B的callme, 而 不 调 用A的。 下 面 是 运 行 结 果: C:\\>java Dispatch 在B的callme成 员 函 数 里
5.14 final
在 缺 省 情 况 下, 所 有 的 成 员 函 数 和 实 例 变 量 都 可 以 被 覆 盖。 如 果 你 希 望 你 的 变 量 或 成 员 函 数 不 再 被 子 类 覆 盖, 可 以 把 它 们 声 明 为final。 这 意 味 着 将 来 的 实 例 都 依 赖 这 个 定 义。 例 如: final int FILE_NEW = 1; final int FILE_OPEN = 2; final int FILE_SAVE = 3; fianl int FILE_SAVEAS = 4; final int FILE_QUIT = 5; final变 量 用 大 写 标 识 符 是 一 个 一 般 的 约 定。
5.15 静 态
如 果 你 想 要 创 建 一 个 可 以 在 实 例 的 外 部 调 用 的 成 员 函 数, 那 么 你 只 需 声 明 它 为 静 态 的 (static?copy;, 它 就 会 正 常 运 行。 静 态 成 员 函 数 只 能 直 接 调 用 其 他 静 态 成 员 函 数, 而 不 能 以 任 何 方 式 使 用this或super。 你 也 可 以 把 变 量 声 明 为 静 态 的。 如 果 你 想 初 始 化 一 个 静 态 变 量, 你 可 以 用 static声 明 一 个 恰 好 在 类 调 用 时 执 行 一 次 的 程 序 块。 下 面 的 例 子 是 一 个 带 有 一 个 静 态 成 员 函 数, 几 个 静 态 变
量, 和 一 个 静 态 初 始 块 的 类。
class Static { static int a = 3; static int b; static void method(int x){ System.out.println(\"x = \" + x); System.out.println(\"a = \" + a); System.out.println(\"b = \" + b); } static { System.out.println(\"静 态 初 始 块\"); b = a * 4; } public static void main(String args[]) { method(42); } } 这 个 类 被 调 用, 所 有 的 静 态 变 量 都 被 初 始 化,a被 赋 为3, 然 后 运 行static块, 这 将 打 印 出 一 段 消 息, 并 且 把b赋 为a*4, 即12。 然 后 解 释 器 调 用main成 员 函 数, 它 调 用 了 成 员 函 数 method, 参 数x为42。 这 三 个println语 句 打 印 了 两 个 静 态 变 量a、b和 局 部 变 量x。 下 面 是 运 行 结 果: C:\\>java Static 静 态 初 始 块 x = 42 a = 3 b = 12 一 个 静 态 成 员 函 数 可 以 通 过 它 所 属 的 类 名 来 调 用。 象 调 用 实 例 变 量 一 样, 你 可 以 用 点 操 作 符 通 过 类 名 来 调 用 静 态 成 员 函 数 和 静 态 变 量。Java就 是 这 样 实 现 了 全 局 函 数 和 全 局 变 量。 下 面 的 例 子 里, 我 们 创 建 了 带 有 一 个 静 态 成 员 函 数 和 两 个 静 态 变 量 的 类。 第 二 个 类 可 以 通 过 名 字 直 接 来 调 用 第 一 个 类 的 静 态 成 员 函 数 和 静 态 变 量。
class staticClass { static int a = 42; static int b = 99; static void
callme( ) { System.out.println(\"a = \" + a); } }
class StaticByName { public static void main(String args[])
{ StaticClass.callme( ); System.out.println(\"b = \" + staticClass.b); } }
下 面 是 运 行 结 果: C:\\>java staticByName a = 42 b = 99
5.16 抽 象
有 时 你 需 要 定 义 一 个 给 出 抽 象 结 构、 但 不 给 出 每 个 成 员 函 数 的 完 整 实 现 的 类。 如 果 某 个 成 员 函 数 没 有 完 整 实 现, 必 须 要 由 子 类 来 覆 盖, 你 可 把 它 声 明 为 抽 象(abstract?copy; 型。 含 有 抽 象 型 成 员 函 数 的 类 必 须 声 明 为 抽 象 的。 为 了 把 一 个 类 声 明 为 抽 象 的, 你 只 需 在 类 定 义 的class关 键 词 前 放 置 关 键 词abstract。 这 ?copy; 类 不 能 直 接 用new操 作 符 生 成 实 例, 因 为 它 们 的 完 整 实 现 还 没 有 定 义。 你 不 能 定 义 抽 象 的 构 造 函 数 或 抽 象 的 静 态 成 员 函 数。 抽 象 类 的 子 类 或 者 实 现 了 它 的 超 类 的 所 有 抽 象 的 成 员 函 数, 或 者 也 被 声 明 为 抽 象 的。 下 面 例 子 是 一 个 带 有 抽 象 成 员 函 数 的 类, 其 后 是 一 个 实 现 了 该 成 员 函 数 的 类。
abstract class A { abstract void callme( ) ; void metoo( ) { system.out.println(\"在A的metoo成 员 函 数 里\"); } } class B extends A { void callme( ) { System.out.println(\"在B的callme成 员 函 数 里\"); } } class Abstract { public static void main(String args[]) { A a = new B( );
a.callme( ); a.metoo( ); } }
下 面 是 运 行 结 果: C:\\>java Abstract 在B的callme成 员 函 数 里 在A的metoo成 员 函 数 里
本 章 小 结
1. 类 是Java语 言 面 向 对 象 编 程 的 基 本 元 素, 它 定 义 了 一 个 对 象 的 结 构 和 功 能。 2. Java通 过 在 类 定 义 的 大 括 号 里 声 明 变 量 来 把 数 据 封 装 在 一 个 类 里, 这 里 的 变 量 称 为 实 例 变 量。 3. 成 员 函 数, 是 类 的 功 能 接 口, 是 类 定 义 里 的 一 个 子 程 序, 在 类 的 定 义 里 和 实 例 变 量 处 于 同 一 级 别。
免责声明:本站相关技术文章信息部分来自网络,目的主要是传播更多信息,如果您认为本站的某些信息侵犯了您的版权,请与我们联系,我们会即时妥善的处理,谢谢合作!