513 动 态 成 员 函 数 发 送
当 你 用 点 操 作 符 调 用 一 个 对 象 实 例 的 成 员 函 数 时, 对 象 实 例 所 属 的 类 在 编 译 时 要 被 检 查, 以 确 保 调 用 的 成 员 函 数 在 该 类 中 是 存 在 的。 在 运 行 时, 对 象 实 例 可 以 指 向 所 声 明 类 型 的 子 类 的 实 例。 在 这 py; 情 况 下, 如 果 子 类 覆 盖 了 要 调 用 的 成 员 函 数,Java就 用 实 例 来 决 定 调 用 哪 一 个 成 员 函 数。 如 下 面 的 例 子, 两 个 类 是 子 类 和 超 类 的 关 系, 子 类 覆 盖 了 超 类 的 成 员 函 数。
lass A { vd all( ) { Systtprntln(\"在A的all成 员 函 数 里\"); } }
lass B xtnds A { vd all( ) { Systtprntln(\"在B的all成 员 函 数 里\"); } }
lass Dspath { pbl stat vd an(Strng args[]) { A a = nw B( ); aall( ); } }
有 趣 的 是, 在 成 员 函 数an里, 我 们 把 变 量a声 明 为 类 型A, 然 后 把 类B的 一 个 实 例 存 放 到 它 上 面。 我 们 在a上 调 用 成 员 函 数all,Java编 译 器 确 定 在 类A确 实 有 成 员 函 数all, 但 是 在 运 行 时, 由 于a事 实 上 是B的 实 例, 所 以 调 用B的all, 而 不 调 用A的。 下 面 是 运 行 结 果: C:\\>java Dspath 在B的all成 员 函 数 里
514 nal
在 缺 省 情 况 下, 所 有 的 成 员 函 数 和 实 例 变 量 都 可 以 被 覆 盖。 如 果 你 希 望 你 的 变 量 或 成 员 函 数 不 再 被 子 类 覆 盖, 可 以 把 它 们 声 明 为nal。 这 意 味 着 将 来 的 实 例 都 依 赖 这 个 定 义。 例 如: nal nt FILE_NEW = 1; nal nt FILE_OPEN = 2; nal nt FILE_SAVE = 3; anl nt FILE_SAVEAS = 4; nal nt FILE_QUIT = 5; nal变 量 用 大 写 标 识 符 是 一 个 一 般 的 约 定。
515 静 态
如 果 你 想 要 创 建 一 个 可 以 在 实 例 的 外 部 调 用 的 成 员 函 数, 那 么 你 只 需 声 明 它 为 静 态 的 (statpy;, 它 就 会 正 常 运 行。 静 态 成 员 函 数 只 能 直 接 调 用 其 他 静 态 成 员 函 数, 而 不 能 以 任 何 方 式 使 用ths或spr。 你 也 可 以 把 变 量 声 明 为 静 态 的。 如 果 你 想 初 始 化 一 个 静 态 变 量, 你 可 以 用 stat声 明 一 个 恰 好 在 类 调 用 时 执 行 一 次 的 程 序 块。 下 面 的 例 子 是 一 个 带 有 一 个 静 态 成 员 函 数, 几 个 静 态 变
量, 和 一 个 静 态 初 始 块 的 类。
lass Stat { stat nt a = 3; stat nt b; stat vd thd(nt x){ Systtprntln(\"x = \" + x); Systtprntln(\"a = \" + a); Systtprntln(\"b = \" + b); } stat { Systtprntln(\"静 态 初 始 块\"); b = a 4; } pbl stat vd an(Strng args[]) { thd(42); } } 这 个 类 被 调 用, 所 有 的 静 态 变 量 都 被 初 始 化,a被 赋 为3, 然 后 运 行stat块, 这 将 印 出 一 段 消 息, 并 且 把b赋 为a4, 即12。 然 后 解 释 器 调 用an成 员 函 数, 它 调 用 了 成 员 函 数 thd, 参 数x为42。 这 三 个prntln语 句 印 了 两 个 静 态 变 量a、b和 局 部 变 量x。 下 面 是 运 行 结 果: C:\\>java Stat 静 态 初 始 块 x = 42 a = 3 b = 12 一 个 静 态 成 员 函 数 可 以 通 过 它 所 属 的 类 名 来 调 用。 象 调 用 实 例 变 量 一 样, 你 可 以 用 点 操 作 符 通 过 类 名 来 调 用 静 态 成 员 函 数 和 静 态 变 量。Java就 是 这 样 实 现 了 全 局 函 数 和 全 局 变 量。 下 面 的 例 子 里, 我 们 创 建 了 带 有 一 个 静 态 成 员 函 数 和 两 个 静 态 变 量 的 类。 第 二 个 类 可 以 通 过 名 字 直 接 来 调 用 第 一 个 类 的 静 态 成 员 函 数 和 静 态 变 量。
lass statClass { stat nt a = 42; stat nt b = 99; stat vd
all( ) { Systtprntln(\"a = \" + a); } }
lass StatByNa { pbl stat vd an(Strng args[])
{ StatClassall( ); Systtprntln(\"b = \" + statClassb); } }
下 面 是 运 行 结 果: C:\\>java statByNa a = 42 b = 99
516 抽 象
有 时 你 需 要 定 义 一 个 给 出 抽 象 结 构、 但 不 给 出 每 个 成 员 函 数 的 完 整 实 现 的 类。 如 果 某 个 成 员 函 数 没 有 完 整 实 现, 必 须 要 由 子 类 来 覆 盖, 你 可 把 它 声 明 为 抽 象(abstratpy; 型。 含 有 抽 象 型 成 员 函 数 的 类 必 须 声 明 为 抽 象 的。 为 了 把 一 个 类 声 明 为 抽 象 的, 你 只 需 在 类 定 义 的lass关 键 词 前 放 置 关 键 词abstrat。 这 py; 类 不 能 直 接 用nw操 作 符 生 成 实 例, 因 为 它 们 的 完 整 实 现 还 没 有 定 义。 你 不 能 定 义 抽 象 的 构 造 函 数 或 抽 象 的 静 态 成 员 函 数。 抽 象 类 的 子 类 或 者 实 现 了 它 的 超 类 的 所 有 抽 象 的 成 员 函 数, 或 者 也 被 声 明 为 抽 象 的。 下 面 例 子 是 一 个 带 有 抽 象 成 员 函 数 的 类, 其 后 是 一 个 实 现 了 该 成 员 函 数 的 类。
abstrat lass A { abstrat vd all( ) ; vd t( ) { systtprntln(\"在A的t成 员 函 数 里\"); } } lass B xtnds A { vd all( ) { Systtprntln(\"在B的all成 员 函 数 里\"); } } lass Abstrat { pbl stat vd an(Strng args[]) { A a = nw B( );
aall( ); at( ); } }
下 面 是 运 行 结 果: C:\\>java Abstrat 在B的all成 员 函 数 里 在A的t成 员 函 数 里
本 章 小 结
1 类 是Java语 言 面 向 对 象 编 程 的 基 本 元 素, 它 定 义 了 一 个 对 象 的 结 构 和 功 能。 2 Java通 过 在 类 定 义 的 大 括 号 里 声 明 变 量 来 把 数 据 封 装 在 一 个 类 里, 这 里 的 变 量 称 为 实 例 变 量。 3 成 员 函 数, 是 类 的 功 能 接 口, 是 类 定 义 里 的 一 个 子 程 序, 在 类 的 定 义 里 和 实 例 变 量 处 于 同 一 级 别。
第 六 章 Java图 形 用 户 接 口
对 一 个 优 秀 的 应 用 程 序 来 说, 良 好 的 图 形 用 户 接 口 是 必 不 可 少 的。 缺 少 良 好 的 图 形 用 户 接 口, 将 会 给 用 户 理 解 和 使 用 应 用 程 序 带 来 很 多 不 便。 很 难 想 象 用 户 为 了 学 会 使 用 一 个 应 用 程 序, 去 记 一 大 堆 命 令。 Java提py; 了 生 成 一 个 良 好 的 图 形 用 户 接 口 所 需 要 的 一py; 基 本 元 件: 面 板(Panl py;、 按 钮 (Bttn py;、 标py;(Labl py;、 画 板(Canvass py;、 滚 动 条(Srllbar py;、 列 表 框(Lst py;、 文 本 域(Txt Fld py;、 文 本 区(Txt Ara py;。
61 面 板
面 板 提py; 了 建 立 应 用 程 序 的 空 间。 你 可 以 把 图 形 元 件(包 括 其 他 面 板 py; 放 在 一 个 面 板 上。 Applt类 提py; 了 一 个 基 本 的 面 板。
611 布 局 管 理
Java提py; 了 几 种 布 局: 顺 序 布 局(Flw Layt py;、 边 界 布 局(Brdr Layt py; 和 网 格 布 局 (Grd Layt)
6111 顺 序 布 局
顺 序 布 局(Flw Layt py; 是 最 基 本 的 一 种 布 局, 面 板 的 缺 省 布 局 就 是 顺 序 布 局。 顺 序 布 局 指 的 是 把 图 形 元 件 一 个 接 一 个 地rg; 平 地 放 在 面 板 上。 下 面 是 一 个 顺 序 布 局 的 例 子:
prt javaawt; prt javaappltApplt;
pbl lass yBttns xtnds Applt { Bttn bttn1, bttn2, bttn3;
pbl vd nt() { bttn1 = n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n3); } }
6112 边 界 布 局
边 界 布 局 包 括 五 个 区: 北 区、 南 区、 东 区、 西 区 和 中 区。 这 几 个 区 在 面 板 上 的 分 布 规 律 是\" 上 北 下 南, 左 西 右 东\"。 下 面 是 一 个 边 界 布 局 的 例 子:
prt javaawt; prt javaappltApplt;
pbl lass bttnDr xtnds Applt { Bttn bttnN, bttnS, bttnW, bttnE, bttnC;
pbl vd nt() { stLayt(n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷nC); } }
6113 网 格 布 局
网 格 布 局 把 面 板 分 成 一 个 个 的 网 格, 你 可 以 给 出 网 格 的 行 数 和 列 数。 下 面 是 一 个 网 格 布 局 的 例 子:
prt javaawt; prt javaappltApplt;
pbl lass bttnGrd xtnds Applt { Bttn bttn1, bttn2, bttn3, bttn4, bttn5, bttn6, bttn7, bttn8;
pbl vd nt() { stLayt(n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n(\"艮\");
bttn4 = n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n(\"兑\");
add(bttn1); add(bttn2); add(bttn3); add(bttn4); add(bttn5); add(bttn6); add(bttn7); add(bttn8); } }
62 按 钮
621 按 钮 事 件
用 户 点 一 下 按 钮, 就 会 有 一 个 按 钮 事 件 发 生。 你 可 以 通 过 覆 盖 一 个applt的atn成 员 函 数 来 捕 捉 按 钮 事 件。 pbl blan atn (Evnt , Objt ) { (targt nstan Bttn) { systtprntln ((strng) ); } ls { Systtprntln (\"Nn-bttn vnt\"); } rtrn tr; }
622 按 钮 类 型
Java提py; 了 标 准 的 按 压 式 按 钮, 同 时 也 提py; 了 选 择 式 按 钮 和 标 记 式 按 钮。
6221 选 择 式 按 钮
选 择 式 按 钮 提py; 了 从 几 个 选 项 中 选 一 个 选 项 的 功 能。 下 面 是 从 几 个 市 中 选 一 个 市 的 例 子, 市 名 放 在 选 择 式 按 钮 中:
CtyChsr = nw Ch();
CtyChsraddIt(\"北py;\"); CtyChsraddIt(\"上海\");
CtyChsraddIt(\"天 津\");
add(CtyChsr);
6222 标 记 式 按 钮
标 记 式 按 钮 的 状 态 作 为 标 记 框 事 件 的 对 象 参 数 返 回。 下 面 是 一 个 标 记 式 按 钮 的 例 子:
Chbx llStylBttn; llStylBttn = nw Chbx(\"Sld\");
pbl blan atn(Evnt , Objt arg) { (targt nstan
Chbx) { Systtprntln(\"Chbx: \" + arg); } rtrn tr; }
6223 按 键 式 按 钮
按 键 式 按 钮 是 一 组 按 钮, 用 户 可 以 选 中 其 中 一 个, 同 时 这 一 组 中 的 其 他 按 钮 将 被 关 闭。 下 面 是 一 个 按 键 式 按 钮 的 例 子: pbl lass ChBx xtnds Applt { ChbxGrp bg; pbl vd nt() { bg = n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hr\", bg, als)); } }
623 自 包 含 按 钮
Java语 言 的 面 向 对 象 特 性 使 我 们 能 够 创 建 完 全 自 包 含 的 按 钮。 在 自 包 含 按 钮 里, 你 可 以 在py; 展 按 钮 类 里 建 立 事 件 控 制 函 数。 下 面 是 一 个 自 包 含 按 钮 的 例 子:
prt javaawt; prt javaappltApplt;
lass Bttn xtnds Bttn {
pbl Bttn() { stLabl(\"O\"); }
pbl blan atn(Evnt , Objt arg)
{ Systtprntln(\"OKBttn\"); rtrn tr; } }
pbl lass bttntst xtnds Applt { Bttn yOBttn;
pbl vd nt() { yOBttn = nw Bttn(); add(yOBttn); } }
63 标py;
标py; 是 一 种 放 到 面 板 上 的 静 止 的 正 文。 下 面 是 一 个 标py; 的 例 子: prt javaa由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷CENTER, 10, 10)); Labl labl1 = nw Labl(\"你 好!\"); Labl labl2 = nw Labl(\"另 一 个 标py;\"); add(labl1); add(labl2); } }
64 列 表 框
列 表 框 使 用 户 易 于 操 作 大 量 的 选 项。 创 建 列 表 框 的 方 法 和Ch bttn有py; 相 似。 列 表 框 的 所 有 条 目 都 是 可 见 的, 如 果 选 项 很 多, 超 出 了 列 表 框 可 见 区 的 范 围, 则 列 表 框 的 旁 边 将 会 有 一 个 滚 动 条。 首 先, 创 建 列 表 框: Lst l = nw Lst(4, als); 这 个 成 员 函 数 创 建 了 一 个 显 示4行 的 列 表 框。 第 二 个 参 数\"als\"表 示 这 个 列 表 框 是 单 选 的, 如 果 是\"tr \", 则 表 示 是 多 选 的。 下 面 增 加 列 表 框 的 选 项: laddIt(\"北py; 大 学\"); laddIt(\"清 华 大 学\"); laddIt(\"吉林 大 学\"); laddIt(\"复py; 大 学\"); laddIt(\"南 开 大 学\"); laddIt(\"天 津 大 学\"); laddIt(\"南py; 大 学\"); add(l);
641 在 列 表 框 中 进 行 选 择
可 以 用 成 员 函 数gtSltdIt()或gtSltdIts()来 接 收 在 列 表 框 中 被 选 的 选 项。 在 单 选 列 表 框 里,\" 双 击\" 一 个 选 项 就 可 以 触 发 一 个 可 被atn()成 员 函 数 捕 捉 到 的 事 件。 pbl blan atn(Evnt , Objt arg) { (targt nstan Lst) { Systtprntln(\"Lst ntry:\" + arg); } }
642 多 选 列 表 框
对 于 多 选 列 表 框, 要 使 你 的 选 择 产 生 作 用, 需 要 使 用 其 他 的 外 部 事 件。 例 如, 你 可 以 使 用 按 钮 事 件: pbl blan atn(Evnt , Objt arg) { (targt nstan Bttn) { (\"O\"qals(arg)) { strng[] sltd ; sltd = lgtSltdIts( ); r (nt I = 0; I< sltdlngth; I++) {Systtprntln(sltd[]); } } } }
65 文 本 域
文 本 域 一 般 用 来 让 用 户 输 入 象 姓 名、 信 用 卡 号 这 样 的 信 息, 它 是 一 个 能 够 接 收 用 户 的 键 盘 输 入 的 小 块 区 域。
651 创 建 文 本 域
在 创 建 文 本 域 时, 有 四 种 类 型py; 你 选 择: 空 的、 空 的 并 且 具 有 指 定 长 度、 带 有 初 始 文 本 内 容 的 和 带 有 初 始 文 本 内 容 并 具 有 指 定 长 度 的。 下 面 是 生 成 这 四 种 文 本 域 的 代 码: TxtFld t1, t2, t3, t4; // 空 的 文 本 域 t1 = nw TxtFld() ; // 长 度 为20的 空 的 文 本 域 t2 = nw TxtFld(20) ; // 带 有 初 始 文 本 内 容 的 文 本 域 t3
= nw TxtFld(\"你 好\") ; // 带 有 初 始 文 本 内 容 并 具 有 指 定 长 度 的 文 本 域 t4 = nw TxtFld(\"你 好\", 30) ; add(t1) ; add(t2) ; add(t3) ; add(t4) ;
652 文 本 域 事 件
当 用 户 在 文 本 域 里 敲\" 回 车\" 键 时, 就 产 生 了 一 个 文 本 域 事 件。 象 其 他 事 件 一 样, 你 可 以 以 在 成 员 函 数atn()中 捕 捉 到 这 个 事 件。
pbl blan atn(Evnt , Objt arg) { (targt nstan TxtFld) { Systtprntln(\"TxtFld: \"+arg); } }
66 文 本 区
文 本 区 可 以 显 示 大 段 的 文 本。
661 创 建 文 本 区
与 文 本 域 类 似, 创 建 文 本 区 时 也 有 四 种 类 型py; 选 择, 但 如 果 指 定 文 本 区 的 大 小, 必 须 同 时 指 定 行 数 和 列 数。 TxtAra ta1, ta2; // 一 个 空 的 文 本 区 ta1 = nw TxtAra(); // 一 个 带 有 初 始 内 容、 大 小 为5 x 40 的 文 本 区 ta2 = nw TxtAra(\"你 好!\", 5, 40);
可 以 用 成 员 函 数stEdtabl()来 决 定 用 户 是 否 可 对 文 本 区 的 内 容 进 行 编 辑。 // 使 文 本 区 为 只 读 的 ta2stEdtabl(als)
662 接 收 文 本 区 的 内 容
可 以 用 成 员 函 数gtTxt()来 获 得 文 本 区 的 当 前 内 容。 例 如: Systtprntln(ta1gtTxt()); 文 本 区 本 身 不 产 生 自 己 的 事 件。 但 你 可 以 用 外 部 事 件 来 接 收 文 本 区 的 内 容: pbl blan atn(Evnt , Objt ) { (targt nstan Bttn) { (\"snd\"qals()) { Strng txtTSnd = ta1gtTxt ();
Systtprntln(\"sndng: \" + txtTsnd);
ySndFntn(txtTSnd); } } ls { } }
67 画 板
画 板 能 够 捕 捉 到py; 露 事 件、 鼠 标 事 件 和 其 他 类 似 的 事 件。 基 本 的 画 板 类 不 处 理 这py; 事 件, 但 你 可 以py; 展 它 来 创 建 有 你 所 需 功 能 的 画 板 类。
671 创 建 画 板
prt javaawt; prt javaappltApplt;
pbl lass sprGUI xtnds Applt { yCanvas ddl; pbl
vd nt() { // 建 立 我 们 的 画 板 ddl = nw yCanvas();
ddlrshap(0, 0, 100, 100); ltPanladd(\"Cntr\",ddl); } }
lass yCanvas xtnds Canvas { pbl vd pant(Graphs g)
{ gdrawRt(0, 0, 99, 99); gdrawStrng(\"Canvas\", 15, 40); } }
672 画 板 事 件
你 可 以 覆 盖 一 般 的 事 件 处 理 成 员 函 数。 下 面 是 一 个 包 含 了sDwn事 件 处 理 的 例 子: prt javaawt; prt javaappltApplt;
pbl lass anvas xtnds Applt {
Bttn b1;
pbl vd nt() { // St r layt as a Brdr styl stLayt(nw
BrdrLayt(15, 15)); b1 = nw Bttn(\"Tst\"); yCanvas 1 = nw
yCanvas(100, 100); // add th anvas and th bttn t th applt
add(\"Cntr\", 1); add(\"Sth\", b1); }
pbl blan atn(Evnt , Objt arg) { Systtprntln(\"Evnt:
\" + arg); rtrn tr; }
pbl blan sDwn(Evnt , nt x, nt y)
{ Systtprntln(\"Ms wrs: (\" + x + \",\" + y + \")\"); rtrn tr; } }
lass yCanvas xtnds Canvas { prvat nt wdth; prvat nt hght;
pbl yCanvas(nt 由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷 = h; rshap(0, 0, w,
h); }
pbl vd pant(Graphs g) { gstClr(Clrbl); gllRt(0, 0,
wdth, hght); }
pbl blan sDwn(Evnt , nt x, nt y) { (( x < wdth) && (y
第 七 章 多 线 程
71 多 线 程 的 概 念
多 线 程 编 程 的 含 义 是 你 可 将 程 序 任 务 分 成 几 个 并 行 的 子 任 务。 特 别 是 在 网 络 编 程 中, 你 会 发 现 很 多 功 能 是 可 以 并 发 执 行 的。 比 如 网 络 传 输 速 度 较 慢, 用 户 输 入 速 度 较 慢, 你 可 以 用 两 个 独 立 的 线 程 去 完 成 这 py; 功 能, 而 不 影 响 正 常 的 显 示 或 其 他 功 能。 多 线 程 是 与 单 线 程 比 较 而 言 的, 普 通 的WINDOWS采 用 单 线 程 程 序 结 构, 其 工 作 原 理 是: 主 程 序 有 一 个 消 息 循 环, 不 断 从 消 息 队 列 中 读 入 消 息 来 决 定 下 一 步 所 要 干 的 事 情, 一 般 是 一 个 子 函 数, 只 有 等 这 个 子 函 数 执 行 完 返 回 后, 主 程 序 才 能 接 收 另 外 的 消 息 来 执 行。 比 如 子 函 数 功 能 是 在 读 一 个 网 络 数 据, 或 读 一 个 文 件, 只 有 等 读 完 这 py; 数 据 或 文 件 才 能 接 收 下 一 个 消 息。 在 执 行 这 个 子 函 数 过 程 中 你 什 么 也 不 能 干。 但 往 往 读 网 络 数 据 和 等 待 用 户 输 入 有 很 多 时 间 处 于 等 待 状 态, 多 线 程 利 用 这 个 特 点 将 任 务 分 成 多 个 并 发 任 务 后, 就 可 以 解 决 这 个 问 题。
711 Java线 程 的 模 型
Java的 设 计 思 想 是 建 立 在 当 前 大 多 数 操 作 系 统 都 实 现 了 线 程 调 度。Java虚 拟 机 的 很 多 任 务 都 依 赖 线 程 调 度, 而 且 所 有 的 类 库 都 是 为 多 线 程 设 计 的。 实 时 上,Java支 持Mantsh和Ms-ds 的 平 台 rg; 所 以 迟 迟 未 出 来 就 是 因 为 这 两 个 平 台 都 不 支 持 多 线 程。Java利 用 多 线 程 实 现 了 整 个 执 行 环 境 是 异 步 的。 在Java程 序 里 没 有 主 消 息 循 环。 如 果 一 个 线 程 等 待 读 取 网 络 数 据, 它 可 以 运 行 但 不 停 止 系 统 的 其 他 线 程 执 行。 用 于 处 理 用 户 输 入 的 线 程 大 多 时 间 是 等 待 用 户 敲 键 盘 或 击 鼠 标。 你 还 可 以 使 动 画 的 每 一 帧 rg; 间 停 顿 一 秒 而 并 不 使 系 统 暂 停。 一 py; 线 程 启 动 后, 它 可 以 被 挂 起, 暂 时 不 让 它 执 行。 挂 起 的 线 程 可 以 重 新 恢 复 执 行。 任 何 时 间 线 程 都 可 以 被 停 止, 被 停 止 的 线 程 就 不 能 再 重 新 启 动。 Java语 言 里, 线 程 表 现 为 线 程 类, 线 程 类 封 装 了 所 有 需 要 的 线 程 操 作 控 制。 在 你 心 里, 必 须 很 清 晰 地 区 分 开 线 程 对 象 和 运 行 线 程, 你 可 以 将 线 程 对 象 看 作 是 运 行 线 程 的 控 制 面 板。 在 线 程 对 象 里 有 很 多 函 数 来 控 制 一 个 线 程 是 否 运 行, 睡 眠, 挂 起 或 停 止。 线 程 类 是 控 制 线 程 行 为 的 唯 一 的 段。 一 py; 一 个Java程 序 启 动 后, 就 已 经 有 一 个 线 程 在 运 行。 你 可 通 过 调 用ThradrrntThrad 函 数 来 查 看 当 前 运 行 的 是 哪 一 个 线 程。
你 得 到 一 个 线 程 的 控 制 柄, 你 就 可 以 作 很 有 趣 的 事 情, 即 使 单 线 程 也 一 样。 下 面 这 个 例 子 让 你 知 道 怎 样 操 纵 当 前 线 程。 Flna:tstthrad
lass tstthrad { pbl stat vd an(Strng args[]) { Thrad t
=ThradrrntThrad(); tstNa(\"Ths Thrad s rnnng\");
Systtprntln(\"Th rnnng thrad:\" + t); try { r (nt =0;<5;++)
{ Systtprntln(\"Slp t \"+); Thradslp(1000); }
} ath (IntrrptdExptn ) {Systtprntln(\"thrad has wrng\"); }
} }
执 行 结 果:java tstthrad Th rnnng thrad:Thrad[Ths Thrad s rnnng,5,an] Slp t 0 Slp t 1 Slp t 2 Slp t 3 Slp t 4
712 启 动 接 口
一 个 线 程 并 不 激 动 人 心, 多 个 线 程 才 有 实 际 意 义。 我 们 怎 样 创 建 更 多 的 线 程 呢? 我 们 需 要 创 建 线 程 类 的 另 一 个 实 例。 当 我 们 构 造 了 线 程 类 的 一 个 新 的 实 例, 我 们 必 须 告 诉 它 在 新 的 线 程 里 应 执 行 哪 一 段 程 序。 你 可 以 在 任 意 实 现 了 启动 接 口 的 对 象 上 启 动 一 个 线 程。 启 动 接 口 是 一 个 抽 象 接 口, 来 表 示 本 对 象 有 一 py; 函 数 想 异 步 执 行。 要 实 现 启 动 接 口, 一 个 类 只 需 要 有 一 个 叫rn的 函 数。 下 面 是 创 建 一 个 新 线 程 的 例 子:
Flna:twthradjava
lass twthrad plnts Rnnabl { twthrad() { Thrad t1
=ThradrrntThrad(); t1stNa(\"Th rst an thrad\");
Systtprntln(\"Th rnnng thrad:\" + t1); Thrad t2 = nw
Thrad(ths,\"th snd thrad\"); Systtprntln(\"rat anthr
thrad\"); t2start(); try { Systtprntln(\"rst thrad wll
slp\"); Thradslp(3000); }ath (IntrrptdExptn )
{Systtprntln(\"rst thrad has wrng\"); }
Systtprntln(\"rst thrad xt\"); } pbl vd rn() { try { r
(nt =0;<5;++) { Systtprntln(\"Slp t r thrad 2:\"+);
Thradslp(1000); }
} ath (IntrrptdExptn ) {Systtprntln(\"thrad has
wrng\"); }
Systtprntln(\"snd thrad xt\"); } pbl stat vd
an(Strng args[]) { nw twthrad(); } }
执 行 结 果:java twthrad
Th rnnng thrad:Thrad[Th rst an thrad,5,an] rat anthr
thrad rst thrad wll slp Slp t r thrad 2:0 Slp t r
thrad 2:1 Slp t r thrad 2:2 rst thrad xt Slp t r
thrad 2:3 Slp t r thrad 2:4 snd thrad xt
an线 程 用nw Thrad(ths, \"th snd thrad\")创 建 了 一 个Thrad对 象, 通 过 传 递 第 一 个 参 数 来 标 明 新 线 程 来 调 用ths对 象 的rn函 数。 然 后 我 们 调 用start函 数, 它 将 使 线 程 从rn函 数 开 始 执 行。
713 同 步
因 为 多 线 程 给 你 提 py; 了 程 序 的 异 步 执 行 的 功 能, 所 以 在 必 要 时 必 须 还 提 py; 一 种 同 步 机 制。 例 如, 你 想 两 个 线 程 通 讯 并 共 享 一 个 复 杂 的 数 据 结 构, 你 需 要 一 种 机 制 让 他 们 相 互 牵 制 并 正 确 执 行。 为 这 个 目 的,Java用 一 种 叫 监 视 器(ntr)的 机 制 实 现 了 进 程 间 的 异 步 执 行。 可 以 将 监 视 器 看 作 是 一 个 很 小 的 盒 子, 它 只 能 容 纳 一 个 线 程。 一 py; 一 个 线 程 进 入 一 个 监 视 器, 所 有 其 他 线 程 必 须 等 到 第 一 个 线 程 退 出 监 视 器 后 才 能 进 入。 这 py; 监 视 器 可 以 设 计 成 保 护 共 享 的 数 据 不 被 多 个 线 程 同 时 操 作。 大 多 数 多 线 程 系 统 将 这 py; 监 视 器 设 计 成 对 象,Java提 py; 了 一 种 更 清 晰 的 解 决 方 案。 没 有Mntr类; 每 个 对 象 通 过 将 他 们 的 成 员 函 数 定 义 成synhrnzd来 定 义 自 己 的 显 式 监 视 器, 一 py; 一 个 线 程 执 行 在 一 个synhrnzd函 数 里, 其 他 任 何 线 程 都 不 能 调 用 同 一 个 对 象 的
synhrnzd函 数。
714 消 息
你 的 程 序 被 分 成 几 个 逻 辑 线 程, 你 必 须 清 晰 的 知 道 这 py; 线 程 rg; 间 应 怎 样 相 互 通 讯。Java 提 了wat和nty等 功 能 来 使 线 程 rg; 间 相 互 交 谈。 一 个 线 程 可 以 进 入 某 一 个 对 象 的synhrnzd 函 数 进 入 等 待 状 态, 直 到 其 他 线 程 显 式 地 将 它 唤 醒。 可 以 有 多 个 线 程 进 入 同 一 个 函 数 并 等 待 同 一 个 唤 醒 消 息。
72 Java线 程 例 子
721 显 式 定 义 线 程
在 我 们 的 单 线 程 应 用 程 序 里, 我 们 并 没 有 看 见 线 程, 因 为Java能 自 动 创 建 和 控 制 你 的 线 程。 如 果 你 使 用 了 理 解Java语 言 的 浏 览 器, 你 就 已 经 看 到 使 用 多 线 程 的Java程 序 了。 你 也 许 注 意 到 两 个 小 程 序 可 以 同 时 运 行, 或 在 你 移 动 滚 动 条 时 小 程 序 继 续 执 行。 这 并 不 是 表 明 小 程 序 是 多 线 程 的, 但 说 明 这 个 浏 览 器 是 多 线 程 的。 多 线 程 应 用 程 序(或applt)可 以 使 用 好 几 个 执 行 上 下 文 来 完 成 它 们 的 工
作。 多 线 程 利 用 了 很 多 任 务 包 含 单 独 的 可 分 离 的 子 任 务 的 特 点。 每 一 个 线 程 完 成 一 个 子 任 务。 但 是, 每 一 个 线 程 完 成 子 任 务 时 还 是 顺 序 执 行 的。 一 个 多 线 程 程 序 允 许 各 个 线 程尽快 执 行 完 它 们。 这 种 特 点 会 有 更 好 的 实 时 输 入 反 应。
722 多 线 程 例 子
下 面 这 个 例 子 创 建 了 三 个 单 独 的 线 程, 它 们 分 别 印 自 己 的\"Hll Wrld\":
//Dn r spl thradsThy wll pas r a shrt t //and thn
prnt t thr nas and dlay ts lass TstThrad xtnds Thrad
{ prvat Strng wha; prvat nt dlay;
//Or nstrtr t str th na (wha) //and t t slp (dlay)
pbl TstThrad(Strng s, nt d) { wha = s; dlay = d; }
//Rn - th thrad thd slar t an() //Whn rn s nshd, th
thrad ds //Rn s alld r th start() thd Thrad pbl vd
rn() { //Try t slp r th spd t try { slp(dlay); }
ath(IntrrptdExptn ) {} //Nw prnt t r na
Systtprntln(\"Hll Wrld!\"+wha+\"\"+dlay); } } / Mlttst
A spl ltthrad thst prgra / pbl lass lttst { pbl
stat vd an(Strng args[]) { TstThrad t1,t2,t3; //Crat r tst
thrads t1 = nw TstThrad(\"Thrad1\",(nt)(Mathrad()2000)); t2 =
nw TstThrad(\"Thrad2\",(nt)(Mathrad()2000)); t3 = nw
TstThrad(\"Thrad3\",(nt)(Mathrad()2000));
//Start ah th thrads t1start(); t2start(); t3start(); } }
723 启 动 一 个 线 程
程 序 启 动 时 总 是 调 用an()函 数, 因 此an()是 我 们 创 建 和 启 动 线 程 的 地 方:
t1 = nw TstThrad(\"Thrad1\",(nt)(Mathrad()2000));
这 一 行 创 建 了 一 个 新 的 线 程。 后 面 的 两 个 参 数 传 递 了 线 程 的 名 称 和 线 程 在 印 信 息 rg; 前 的 延 时 时 间。 因 为 我 们 直 接 控 制 线 程, 我 们 必 须 直 接 启 动 它: t1start();
724 操 作 线 程
如 果 创 建 线 程 正 常,t1应 包 含 一 个 有 效 的 执 行 线 程。 我 们 在 线 程 的rn()函 数 里 控 制 线 程。 一 py; 我 们 进 入rn()函 数, 我 们 便 可 执 行 里 面 的 任 何 程 序。rn()好 象an()一 样。
rn() 执 行 完, 这 个 线 程 也 就 结 束 了。 在 这 个 例 子 里, 我 们 试 着 延 迟 一 个 随 机 的 时 间(通 过 参 数 传 递) slp(dlay);
slp()函 数 只 是 简 单 地 告 诉 线 程 休 息 多 少 个 毫 秒 时 间。
如 果 你 想 推 迟 一 个 线 程 的 执 行, 你 应 使 用slp()函 数。 当 线 程 睡 眠 是slp()并 不 占 用 系 统 资 源。 其 它 线 程 可 继 续 工 作。 一 py; 延 迟 时 间 完 毕, 它 将 印\"Hll Wrld\"和 线 程 名 称 及 延 迟 时 间。
725 暂 停 一 个 线 程
我 们 经 常 需 要 挂 起 一 个 线 程 而 不 指 定 多 少 时 间。 例 如, 如 果 你 创 建 了 一 个 含 有 动 画 线 程 的 小 程 序。 也 许 你 让 用 户 暂 停 动 画 至 到 他 们 想 恢 复 为 止。 你 并 不 想 将 动 画 线 程 仍 调, 但 想 让 它 停 止。 象 这 种 类 似 的 线 程 你 可 用sspnd()函 数 来 控 制: t1sspnd(); 这 个 函 数 并 不 永 久 地 停 止 了 线 程, 你 还 可 用rs()函 数 重 新 激 活 线 程: t1rs();
726 停 止 一 个 线 程
线 程 的 最 后 一 个 控 制 是 停 止 函 数stp()。 我 们 用 它 来 停 止 线 程 的 执 行: t1stp();
注 意: 这 并 没 有 消 灭 这 个 线 程, 但 它 停 止 了 线 程 的 执 行。 并 且 这 个 线 程 不 能 用t1start()重 新 启 动。 在 我 们 的 例 子 里, 我 们 从 来 不 用 显 式 地 停 止 一 个 线 程。 我 们 只 简 单 地 让 它 执 行 完 而 已。 很 多 复 杂 的 线 程 例 子 将 需 要 我 们 控 制 每 一 个 线 程。 在 这 种 情 况 下 会 使 用 到stp()函 数。 如 果 需 要, 你 可 以 测 试 你 的 线 程 是 否 被 激 活。 一 个 线 程 已 经 启 动 而 且 没 有 停 止 被 认 为 是 激 活 的。 t1sAlv() 如 果t1是 激 活 的, 这 个 函 数 将 返 回tr
727 动 画 例 子
下 面 是 一 个 包 含 动 画 线 程 的applt例 子:
prt javaawt; prt javaawtagIagPrdr; prt
javaappltApplt;
pbl lass atst3 xtnds Applt plnts Rnnabl { Iag ags[];
MdaTrar trar; nt ndx = 0; Thrad anatr;
nt axWdth,axHght; //Or -srn pnnts r dbl brng
Iag SrIag; Graphs SrGC;
//Can w pant ys blan ladd = als;
//Intalz th applt St r sz and lad th ags pbl vd nt()
[ //St p r ag ntr trar = nw MdaTrar(ths);
//St th sz and wdth r applt axWdth = 100; axHght =100;
ags = nw Iag[10]; //St p th dbl-br and rsz r applt
try { SrIag = ratIag(axWdth,axHght); SrGC =
SrIaggtGraphs(); SrGCstClr(ClrlghtGray);
SrGCllRt(0,0,axWdth,axHght);
rsz(axWdth,axHght); }ath (Exptn )
{ prntStaTra(); }
//lad th anatn ags nt an array r (nt =0;<10;++) { Strng
agFl = nw Strng (\"ags/D/T\" +StrngvalO(+1) +\"g\");
ags[] = gtIag(gtDntBas(),agFl): //Rgstr ths
ag wth th trar traraddIag(ags[],); } try { //Us
trar t a sr all th ags ar ladd trarwatFrAll(); }
ath (IntrrptdExptn ) {} ladd = tr; }
//Pant th rrnt ra pbl vd pant (Graphs g) { (ladd)
{ gdrawIag(SrIag,0,0,ths); } }
//Start ,stp r rst ag pbl vd start() { (trarhID
(ndx)) { SrGCdrawIag (ags[ndx],0,0,ths); } anatr = nw
Thrad(ths); anatrstart(); }
//Rn,d th anatn wr hr //Grab an ag, pas ,grab th nxt
pbl vd rn() { //Gt th d th rrnt thrad Thrad =
ThradrrntThrad();
//I r anatr thrad xst,and s th rrnt thrad whl
((anatr!= nll) && (anatr==)) { ( trarhID (ndx))
{ //Clar th bagrnd and gt th nxt ag
SrGCllRt(0,0,100,100);
SrGCdrawIag(ags[ndx],0,0,ths); ndx++; //Lp ba t th
bgnnng and p gng (ndx>= agslngth) { ndx = 0; } }
//Dlay hr s anatn ls nral try { anatrslp(200); }ath
(IntrrptdExptn ) {} //Draw th nxt ra rpant(); } } }
73 多 线 程 间 的 通 讯
731 生 产 者 和 消 费 者
多 线 程 的 一 个 重 要 特 点 是 它 们 rg; 间 可 以 互 相 通 讯。 你 可 以 设 计 线 程 使 用 公 用 对 象, 每 个 线 程 都 可 以 独 立 操 作 公 用 对 象。 典 型 的 线 程 间 通 讯 建 立 在 生 产 者 和 消 费 者 模 型 上: 一 个 线 程 产 生 输 出; 另 一 个 线 程 使 用 输 入br
让 我 们 创 建 一 个 简 单 的\"Alphabt Sp\"生 产 者 和 相 应 的 消 费 者
732 生 产 者
生 产 者 将 从thrad类 里 派 生: lass Prdr xtnds Thrad
{ prvat Sp sp; prvat Strng alphabt = \"
ABCDEFGHIJKLMNOPQRSTUVWXYZ\";
pbl Prdr(Sp s) { //Kp r wn py th shard bjt sp
= s; }
pbl vd rn() { har ; //Thrw 10 lttrs nt th sp r (nt
=0;<10;++) { = alphabtharAt((nt)(Mathrand() 26));
spadd(); //prnt a rrd sr addtn
Systtprntln(\"Addd\"+ + \"t th sp\"); //wat a bt br w
add th nxt lttr try { slp((nt)(Mathrand() 1000)); } ath
(IntrrptdExptn ) {} } } }
注 意 我 们 创 建 了Sp类 的 一 个 实 例。 生 产 者 用spadd()函 数 来 建 立 字 符 池。
733 消 费 者
让 我 们 看 看 消 费 者 的 程 序: lass Cnsr xtnds Thrad { prvat Sp sp;
pbl Cnsr (Sp s) { //p r wn py th shard bjt sp
= s; }
pbl vd rn() { har ; //Eat 10 lttrs r th alphabt sp r
(nt I=0 ;<10;++) { //grab n lttr = spat(); //Prnt t th
lttr that w rtrvd Systtprntln(\"At a lttr: \" +); //try
{ slp((nt)(Mathradd()2000)); } ath (IntrrptdExptn ) {} } } }
同 理, 象 生 产 者 一 样, 我 们 用spat()来 处 理 信 息。 那 么,Sp类 到 底 干 什 么 呢?
734 监 视
Sp类 执 行 监 视 两 个 线 程 rg; 间 传 输 信 息 的 功 能。 监 视 是 多 线 程 中 不 可 缺 少 的 一 部 分, 因 为 它 保 持 了 通 讯 的 流 py;。 让 我 们 看 看Spjava文 件: lass Sp { prvat har br[] = nw har[6]; prvat nt nxt = 0; //Flags t p tra
r br stats prvat blan sFll = als; prvat blan sEpty
= tr; pbl syshrnzd har at() { //W an\'t at thr sn\'t anythng
n th br 由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hs
whn sEpty trns als }ath (IntrrptdExptn ) {} } //drnt
th nt,sn w\'r gng t at n lttr nxt--; //Dd w at th
last lttr (nxt== 0) { sEpty = tr; } //W nw th br an\'t
b ll,bas w jst at sFll = als; nty(); //rtrn th lttr
t th thrad that s atng rtrn (br[nxt]); }
//thd t add lttrs t th br pbl synhrnzd vd add(har
) { //Wat arnd ntl thr\'s r t add anthr lttr whl (sFll
== tr ) { try{ 由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷h
(IntrrptdExptn ) {} } //add th lttr t th nxt avalabl spt
br[nxt]=; //Chang th nxt avalabl spt nxt++; //Ar w ll;
(nxt ==6) { sFll =tr; } sEpty =als; nty(); } } sp类 包 含 两 个 重 要 特 征: 数 据 成 员br[]是 私 有 的, 功 能 成 员add()和at()是 公 有 的。
数 据 私 有 避 免 了 生 产 者 和 消 费 者 直 接 获 得 数 据。 直 接 访 问 数 据 可 能 造 成 错 误。 例 如, 如 果 消 费 者 企 图 从 空 缓 冲 区 里 取 出 数 据, 你 将 得 到 不 必 要 的 异 常, 否 则, 你 只 能 锁 住 进 程。 同 步 访 问 方 法 避 免 了 破 坏 一 个 共 享 对 象。 当 生 产 者 向sp里 加 入 一 个 字 母 时, 消 费 者 不 能 吃 字 符, 诸 如 此 类。 这 种 同 步 是 维 持 共 享 对 象 完 整 性 的 重 要 方 面。nty()函 数 将 唤 醒 每 一 个 等 待 线 程。 等 待 线 程 将 继 续 它 的 访 问。
735 联 系 起 来
现 在 我 们 有 一 个 生 产 者, 一 个 消 费 者 和 一 个 共 享 对 象, 怎 样 实 现 它 们 的 交 互 呢? 我 们 只 需 要 一 个 简 单 的 控 制 程 序 来 启 动 所 有 的 线 程 并 确 信 每 一 个 线 程 都 是 访 问 的 同 一 个 共 享 对 象。 下 面 是 控 制 程 序 的 代 码,SpTstjava:
lass SpTst { pbl stat vd an(Strng args[]) { Sp s = nw
Sp(); Prdr p1 = nw Prdr(s); Cnsr 1 = nw Cnsr(s);
p1start(); 1start(); } }
736 监 视 生 产 者
生 产 者/消 费 者 模 型 程 序 经 常 用 来 实 现 远 程 监 视 功 能, 它 让 消 费 者 看 到 生 产 者 同 用 户 的 交 互 或 同 系 统 其 它 部 分 的 交 互。 例 如, 在 网 络 中, 一 组 生 产 者 线 程 可 以 在 很 多 工 作 站 上 运 行。 生 产 者 可 以 印 文 档, 文 档 印 后, 一 个 标 志 将 保 存 下 来。 一 个(或 多 个py; 消 费 者 将 保 存 标 志 并 在 晚 上 报 告 白 天 印 活 动 的 情 况。 另 外, 还 有 例 子 在 一 个 工 作 站 是 分 出 几 个 独 立 的 窗 口。 一 个 窗 口 用 作 用 户 输 入(生 产 者) 另 一 个 窗 口 作 出 对 输 入 的 反 应(消 费 者)。
74 线 程API列 表
下 面 是 一 个 常 用 的 线 程 类 的 方 法 函 数 列 表: 类 函 数: 以 下 是Thrad的 静 态 函 数, 即 可 以 直 接 从Thrad类 调 用。
rrntThrad 返 回 正 在 运 行 的Thrad对 象 yld 停 止 运 行 当 前 线 程, 让 系 统 运 行 下 一 个 线 程 slp(nt n) 让 当 前 线 程 睡 眠n毫 秒 对 象 函 数: 以 下 函 数 必 须 用Thrad的 实 例 对 象 来 调 用。
start start函 数 告 诉java运 行 系 统 为 本 线 程 建 立 一 个 执 行 环 境, 然 后 调 用 本 线 程 的rn()函 数。 rn 是 运 行 本 线 程 的 将 要 执 行 的 代 码, 也 是Rnnabl接 口 的 唯 一 函 数。 当 一 个 线 程 初 始 化 后, 由start函 数 来 调 用 它, 一 py;rn函 数 返 回, 本 线 程 也 就 终 止 了。 stp 让 某 线 程 马 上 终 止, 系 统 将 删 除 本 线 程 的 执 行 环 境 sspnd 与stp函 数 不 同,sspnd将 线 程 暂 停 执 行, 但 系 统 不 破 坏 线 程 的 执 行 环 境, 你 可 以 用rs来 恢 复 本 线 程 的 执 行 rs 恢 复 被 挂 起 的 线 程 进 入 运 行 状 态 stPrrty(nt p) 给 线 程 设 置 优 先 级 gtPrrty 返 回 线 程 的 优 先 级 stNa(Strng na) 给 线 程 设 置 名 称 gtNa 取 线 程 的 名 称
本 章 小 结:
1多 线 程 是java语 言 的 重 要 特 点,java语 言 用Thrad类 封 装 了 线 程 的 所 有 操 作。 2线 程 的 接 口 名 为Rnnabl 3线 程 间 同 步 机 制 为synhrnzd关 键 词 4线 程 间 通 讯 靠wat与nty消 息
第 八 章 Java的\" 异 常\"
\" 异 常\" 指 的 是 程 序 运 行 时 出 现 的 非 正 常 情 况。 在 用 传 统 的 语 言 编 程 时, 程 序 员 只 能 通 过 函 数 的 返 回 值 来 发 出 错 误 信 息。 这 易 于 导 致 很 多 错 误, 因 为 在 很 多 情 况 下 需 要 知 道 错 误 产 生 的 内 部 细 节。 通 常, 用 全 局 变 量rrn来 存 储\" 异 常\" 的 类 型。 这 容 易 导 致 误 用, 因 为 一 个rrn的 值 有 可 能 在 被 处 理 rg; 前 被 另 外 的 错 误 覆 盖 掉。 即 使 最 优 美 的C语 言 程 序, 为 了 处 理\" 异 常\" 情 况, 也 常 求 助 于gt语 句。 Java对\" 异 常\" 的 处 理 是 面 向 对 象 的。 一 个Java的Exptn是 一 个 描 述\" 异 常\" 情 况 的 对 象。 当 出 现\" 异 常\" 情 况 时, 一 个Exptn对 象 就 产 生 了, 并 放 到 产 生 这 个\" 异 常\" 的 成 员 函 数 里。
81 基础
Java的\" 异 常\" 处 理 是 通 过5个 关 键 词 来 实 现 的:try, ath, thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hrw(); //再 抛 出 这 个\" 异 常\" } nally { }
82 \"异 常\" 的 类 型
在\" 异 常\" 类 层 次 的 最 上 层 有 一 个 单 独 的 类 叫 做Thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷n, 它 是 程 序 运 行 时 自 动 地 对 某 py; 错 误 作 出 反 应 而 产 生 的。
83 不 捕 捉\" 异 常\"
\" 异 常\" 对 象 是Java在 运 行 时 对 某 py;\" 异 常\" 情 况 作 出 反 应 而 产 生 的。 例 如, 下 面 这 个 小 程 序 包 含 一 个 整 数 被0除 的\" 异 常\"。
lass Ex0 { pbl stat vd an(Strng args[]) { nt d = 0; nt a = 42/d; } }
当Java执 行 这 个 除 法 时, 由 于 分 母 是0, 就 会 构 造 一 个\" 异 常\" 对 象 来 使 程 序 停 下 来 并 处 理 这 个 错 误 情 况, 在 运 行 时\" 抛 出\"(thrwpy; 这 个\" 异 常\"。 说\" 抛 出\" 是 因 为 它 象 一 个 滚 烫 的 马 铃 薯, 你 必 须 把 它 抓 住 并 立 即 处 理。 程 序 流 将 会 在 除 号 操 作 符 处 被 断, 然 后 检 查 当 前 的 调 用 堆 栈 来 查 找\" 异 常\"。 一 个\" 异 常\" 处 理 器 是 用 来 立 即 处 理\" 异 常\" 情 况 的。 在 这 个 例 子 里, 我 们 没 有 编 一 个\" 异 常\" 处 理 器, 所 以 缺 省 的 处 理 器 就 发 挥 作 用 了。 缺 省 的 处 理 器 印Exptn的 字 符 rg; 值 和 发 生 \" 异 常\" 的 地 点。
下 面 是 我 们 的 小 例 子 的 输 出。
C:\\>java Ex0 javalangarthtExptn: / by zr at Ex0an(Ex0java:4)
84 try与ath
通 常 我 们 希 望 自 己 来 处 理\" 异 常\" 并 继 续 运 行。 可 以 用try来 指 定 一 块 预 防 所 有\" 异 常\" 的 的 程 序。 紧 跟 在try程 序 后 面, 应 包 含 一 个ath子 句 来 指 定 你 想 要 捕 捉 的\" 异 常\" 的 类 型。 例 如, 下 面 的 例 子 是 在 前 面 的 例 子 的 基础上 构 造 的, 但 它 包 含 一 个try程 序 块 和 一 个ath子 句。 lass x1 { pbl stat vd an(strng args[]) { try { nt d = 0; nt a = 42 / d; } ath (arthtxptn ) { systtprntln(\"dvsn by zr\"); } } }
ath子 句 的 目 标 是 解 决\" 异 常\" 情 况, 把 变 量 设 到 合 理 的 状 态, 并 象 没 有 出 错 一 样 继 续 运 行。 如 果 一 个 子 程 序 不 处 理 某 个\" 异 常\", 则 返 到 上 一 级 处 理, 直 到 最 外 一 级。
85 多 个ath子 句
在 某 情 况 下, 同 一 段 程 序 可 能 产 生 不 止 一 种\" 异 常\" 情 况。 你 可 以 放 置 多 个ath子 句, 其 中 每 一 种\" 异 常\" 类 型 都 将 被 检 查, 第 一 个 与 rg; 匹 配 的 就 会 被 执 行。 如 果 一 个 类 和 其 子 类 都 有 的 话, 应 把 子 类 放 在 前 面, 否 则 将 永 远 不 会 到 达 子 类。 下 面 是 一 个 有 两 个ath子 句 的 程 序 的 例 子。
lass MltCath { pbl stat vd an(Strng args[]) { try { nt a
= argslngth; Systtprntln(\"a = \" + a); nt b = 42/a; nt [] =
{1}; [42] = 99; } ath(ArthtExptn ) { Systtprntln(\"dv
by 0: \" + ); } ath(ArrayIndxOtOBndsExptn )
{ systtprntln(\"array ndx b: \" + ); } } }
如 果 在 程 序 运 行 时 不 跟 参 数, 将 会 引 起 一 个0做 除 数 的\" 异 常\", 因 为a的 值 为0。 如 果 我 们 提 py; 一 个 命 令 行 参 数, 将 不 会 产 生 这 个\" 异 常\", 因 为a的 值 大 于0。 但 会 引 起 一 个 ArrayIndxOtOBndxptn的\" 异 常\", 因 为 整 型 数 组的 长 度 是1, 却 给[42]赋 值。 下 面 是 以 上 两 种 情 况 的 运 行 结 果。
C:\\>java MltCath a = 0 dv by 0: javalangarthtxptn: / by
zr C:\\>java MtCath 1 a = 1 array ndx b:
javalangArrayIndxOtOBndsExptn:42
86 try语 句 的 嵌 套
你 可 以 在 一 个 成 员 函 数 调 用 的 外 面 写 一 个try语 句, 在 这 个 成 员 函 数 内 部, 写 另 一 个try语 句 保 护 其 他 代 码。 每 当 遇 到 一 个try语 句,\" 异 常\" 的 框 架 就 放 到 堆 栈 上 面, 直 到 所 有 的try语 句 都 完 成。 如 果 下 一 级 的try语 句 没 有 对 某 种\" 异 常\" 进 行 处 理, 堆 栈 就 会 展 开, 直 到 遇 到 有 处 理 这 种\" 异 常\" 的try语 句。 下 面 是 一 个try语 句 嵌 套 的 例 子。
lass MltNst { stat vd prdr() { try { nt [] = { 1 }: [42]
= 99; } ath(ArrayIndxOtOBndsxptn )
{ Systtprntln(\"array ndx b: \" + ); } } pbl stat vd
an(Strng args[]) { try { nt a = argslngth; systtprntln(\"a
= \" + a); nt b = 42/a; prdr(); } ath(arthtExptn )
{ Systtprntln(\"dv by 0: \" + ); } } }
成 员 函 数prdr里 有 自 己 的try/ath控 制, 所 以an不 用 去 处 理 ArrayIndxOtOBndsExptn。
87 thrw语 句
thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷hrw语 句 的 通 常 形 式。
thrw ThrwablInstan;
程 序 会 在thrw语 句 后 立 即 终 止, 它 后 面 的 语 句 执 行 不 到, 然 后 在 包 含 它 的 所 有try块 中 从 里 向 外 寻 找 含 有 与 其 匹 配 的ath子 句 的try块。 下 面 是 一 个 含 有thrw语 句 的 例 子。
lass Thr由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷ry { dpr(); }
ath(NllPntrExptn ) { systtprntln(\"raght: \" + ); } } }
88 thrws语 句
thrws用 来 标 明 一 个 成 员 函 数 可 能 抛 出 的 各 种\" 异 常\"。 对 大 多 数Exptn子 类 来 说,Java 编 译 器 会 强 迫 你 声 明 在 一 个 成 员 函 数 中 抛 出 的\" 异 常\" 的 类 型。 如 果\" 异 常\" 的 类 型 是Errr或 RntExptn, 或 它 们 的 子 类, 这 个 规 则 不 起 作 用, 因 为 这 py; 在 程 序 的 正 常 部 分 中 是 不 期 待 出 现 的。 如 果 你 想 明 确 地 抛 出 一 个RntExptn, 你 必 须 用thrws语 句 来 声 明 它 的 类 型。 这 就 重 新 定 义 了 成 员 函 数
的 定 义 语 法: typ thd-na(arg-lst) thrws xptn-lst { }
下 面 是 一 段 程 序, 它 抛 出 了 一 个\" 异 常\", 但 既 没 有 捕 捉 它, 也 没 有 用thrws来 声 明。 这 在 编 译 时 将 不 会 通 过。
lass ThrwsD1 { stat vd prdr( ) [ Systtprntln(\"nsd
prdr\"); thrw nw IllgalAssExptn(\"d\"); } pbl stat
vd an(Strng args[]) { prdr( ); } }
为 了 让 这 个 例 子 编 译 过 去, 我 们 需 要 声 明 成 员 函 数prdr抛 出 了IllgalAssExptn, 并 且 在 调 用 它 的 成 员 函 数an里 捕 捉 它。 下 面 是 正 确 的 例 子:
lass ThrwsD { stat vd prdr( ) thrws IllgalAssExptn
{ Systtprntln(\"nsd prdr\"); thrw nw
IllgalAssExptn(\"d\"); } pbl stat vd an(Strng args[])
{ try { prdr( ); } ath (IllgalAssExptn )
{ Systtprntln(\"aght \" + ); } } }
下 面 是 输 出 结 果:
C:\\>java ThrwsD nsd prdr aght
javalangIllgalAssExptn: d
89 nally
当 一 个\" 异 常\" 被 抛 出 时, 程 序 的 执 行 就 不 再 是 线 性 的, 跳 过 某 py; 行, 甚 至 会 由 于 没 有 与 rg; 匹 配 的ath子 句 而 过 早 地 返 回。 有 时 确 保 一 段 代 码 不 管 发 生 什 么\" 异 常\" 都 被 执 行 到 是 必 要 的, 关 键 词nally就 是 用 来 标 识 这 样 一 段 代 码 的。 即 使 你 没 有ath子 句,nally程 序 块 也 会 在 执 行 try程 序 块 后 的 程 序 rg; 前 执 行。 每 个try语 句 都 需 要 至 少 一 个 与 rg; 相 配 的ath子 句 或nally子 句。 一 个 成 员 函 数 返 回 到 调 用 它 的 成 员 函 数, 或 者 通 过 一 个 没 捕 捉 到 的\" 异 常\", 或 者 通 过 一 个 明 确 的rtrn语 句,nally子 句 总 是 恰 好 在 成 员 函 数 返 回 前 执 行。 下 面 是 一 个 例 子, 它 有 几 个 成 员 函 数, 每 个 成 员 函 数 用 不 同 的 途 径 退 出, 但 执 行 了nally子 句。
lass FnallyD { stat vd prA( ) { try
{ Systtprntln(\"nsd prA\"); thrw nw
RntExptn(\"d\"); } nally { Systtprntln(\"prA\'s
nally\"); } } stat vd prB( ) { try { Systtprntln(\"nsd
prB\"); rtrn; } nally { Systtprntln(\"prB\'s nally\"); } }
pbl stat vd an(Strng args[]) { try { prA( ); } ath (Exptn
); prB( ); } }
下 面 是 这 个 例 子 的 运 行 结 果:
C:\\>java FnallyD nsd prA prA\'s nally nsd prB prB\'s nally
本 章 小 结
1 \" 异 常\" 指 的 是 程 序 运 行 时 出 现 的 非 正 常 情 况。 2 在\" 异 常\" 类 层 次 的 最 上 层 的 类 叫Thrwabl, 它 有 两 个 直 接 的 子 类:Exptn和Errr。 3 Java的\" 异 常\" 处 理 通 过5个 关 键 词 来 实 现:try,ath,thrw,thrws和nally。
第 九 章 Java输 入 输 出 操 作
91 Java 输 入 输 出 流
所 有 的 程 序 语 言 都 提 py; 与 本 机 文 件 系 统 交 互 的 方 式;Java也 不 例 外。 我 们 将 看 看Java是 怎 样 处 理 标 准 文 件 输 入 输 出 的(包 括stdn,stt,stdrr)。 当 你 在 网 络 上 开 发 小 程 序 时, 你 必 须 注 意 直 接 文 件 输 入 输 出 是 不 安 全 因 素 的 关 键。 大 多 数 用 户 设 置 他 们 的 浏 览 器, 可 让 你 自 由 的 访 问 他 们 的 文 件 系 统, 但 有 py; 不 让 你 访 问。 当 然, 如 果 你 开 发 你 内 部 的 应 用 程 序, 你 也 许 需 要 直 接 访 问 文 件。 标 准 输 入 输 出 Unx的 用 户, 或 其 他 基 于 命 令 行 系 统 的 用 户(如DOS), 都 知 道 标 准 输 入 输 出 的 含 义。 标 准 输 入 文 件 是 键 盘, 标 准 输 出 文 件 是 你 的 终 端 屏 幕。 标 准 错 误 输 出 文 件 也 指 向 屏 幕, 如 果 有 必 要, 它 也 可 以 指 向 另 一 个 文 件 以 便 和 正 常 输 出 区 分。
系 统 类 Java通 过 系 统 类 达 到 访 问 标 准 输 入 输 出 的 功 能。 上 面 提 到 的 三 个 文 件 在 这 个 系 统 类 中 实 现: Stdn Systn作 为InptStra类 的 一 个 实 例 来 实 现stdn, 你 可 以 使 用rad()和sp(lng n)两 个 成 员 函 数。rad()让 你 从 输 入 中 读 一 个 字 节,sp(lng n)让 你 在 输 入 中 跳 过n个 字 节。
Stt Systt作 为PrntStra来 实 现stdt, 你 可 以 使 用prnt()和prntln()两 个 成 员 函 数。 这 两 个 函 数 支 持Java的 任 意 基 本 类 型 作 为 参 数。
Stdrr Systrr同stdt一 样 实 现stdrr。 象Systt一 样, 你 可 以 访 问PrntStra 成 员 函 数。
92 标 准 输 入 输 出 例 子
这 里 有 一 个 例 子, 功 能 象Unx里 的at或typ: prt java lass yCat{ pbl vd an(Strng args[]) thrws IOExptn{ nt b; nt nt = 0; whl ((b = Systnrad()) !=
-1){ nt++; Systtprnt((har)b); } Systtprntln();
//blan ln Systrrprntln(\"ntd\"+nt+\"ttal byts\"); } }
93 普 通 输 入 输 出 类
除 了 基 本 的 键 盘 输 入 和 屏 幕 输 出 外, 我 们 还 需 要 联 系 文 件 的 输 入 输 出。 我 们 将 学 习 下 面 几 个 类: l FlInptStra l DataInptStra l FlOtptStra l DataOtptStra
作 为 参 考, 再 列 出 一 py; 特 定 应 用 的 类: l PpdInptStra l BrdInptStra l PshBaInptStra l StraTnzr l PpdOtptStra l BrdOtptStra l RandAssFl
我 们 不 在 此 讨 论 这 py; 类, 但 你 可 以 在JAVA_HOME/sr/java/目 录 里 查 看 每 个 类 的 成 员 函 数 定 义。
94 文 件
在 我 们 进 行 文 件 操 作 时, 需 要 知 道 关 于 文 件 的 信 息。Fl类 提 py; 了 一 py; 成 员 函 数 来 操 纵 文 件 和 获 得 文 件 的 信 息。
941 创 建 一 个 新 的 文 件 对 象
你 可 用 下 面 三 个 方 法 来 创 建 一 个 新 文 件 对 象: Fl yFl; yFl = n由小说迷 www.xiaoshuom.com 收集整理,看更快的更新请到小説迷d\");
这 三 种 方 法 取 决 于 你 访 问 文 件 的 方 式。 例 如, 如 果 你 在 应 用 程 序 里 只 用 一 个 文 件, 第 一 种 创 建 文 件 的 结 构 是 最 容 易 的。 但 如 果 你 在 同 一 目 录 里 开 数 个 文 件, 则 第 二 种 或 第 三 种 结 构 更 好。
942 文 件 测 试 和 使 用
一 但 你 创 建 了 一 个 文 件 对 象, 你 便 可 以 使 用 以 下 成 员 函 数 来 获 得 文 件 相 关 信 息: 文 件 名 l Strng gtNa() l Strng gtPath() l Strng gtAbsltPath() l Strng gtParnt() l blan rnaT(Fl nwNa) 文 件 测 试 l blan xsts() l blan anWrt() l blan anRad() l blan sFl() l blan sDrtry() l blan sAbslt() 一 般 文 件 信 息 l lng lastMdd() l lng lngth() 目 录 用 法 l blan dr() l Strng[] lst()
943 文 件 信 息 获 取 例 子 程 序
这 里 是 一 个 独 立 的 显 示 文 件 的 基 本 信 息 的 程 序, 文 件 通 过 命 令 行 参 数 传 输:
prt java; lass lIn{ Fl lTCh; pbl stat vd an(Strng args[]) thrws IOExptn{ (argslngth>0){ r (nt =0;
如果你在阅读得很入味的时候,又正好有事离开,那请进行以下操作.