﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Merlin-随笔分类-java基础篇</title><link>http://www.cppblog.com/yunduan5158/category/1607.html</link><description>Life was like a box of chocolates. You never know what you're gonna get.</description><language>zh-cn</language><lastBuildDate>Wed, 21 May 2008 13:59:00 GMT</lastBuildDate><pubDate>Wed, 21 May 2008 13:59:00 GMT</pubDate><ttl>60</ttl><item><title>[转]developerWorks：Java 技术：重锤痛击 Robocode！</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10235.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Wed, 19 Jul 2006 12:55:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10235.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/10235.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/10235.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/10235.html</trackback:ping><description><![CDATA[
		<blockquote>
				<font face="Arial" color="#000080" size="2">有可能在闪躲炮弹和执行精确攻击的演练中学会继承、多态性、事件处理以及内部类这些内容吗？Robocode 这个游戏即将为全世界的 Java 开发者实现这个愿望，它把游戏风潮变成了教学工具，人们对它的上瘾程度令人吃惊。请跟随 Sing Li 一起拆解 Robocode，同时着手建造属于自己的、定制的、小而精悍的战斗机器。</font>
		</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<font face="Arial" color="#000080" size="2">Robocode 是一个很容易使用的机器人战斗仿真器，可以在所有支持 Java 2 的平台上运行。您创建一个机器人，把它放到战场上，然后让它同其他开发者们创建的机器人对手拼死战斗到底。Robocode 里有一些预先做好的机器人对手让你入门，但一旦您不再需要它们，就可以把您自己创建的机器人加入到正在世界范围内形成的某个联盟里去和世界最强手对阵。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">每个 Robocode 参加者都要利用 Java 语言元素创建他或她的机器人，这样就使从初学者到高级黑客的广大开发者都可以参与这一娱乐活动。初级的 Java 的开发者们可以学习一些基础知识：调用 API 代码、阅读 Javadoc、继承、内部类、事件处理等等。高级开发者们可以在构建“最优品种”的软件机器人全球竞赛中提高他们的编程技巧。在本文中，我们将介绍 Robocode，并指导您从构建您平生第一个 Robocode 机器人开始征服世界。我们还将看一下迷人的“后台”机制，正是它使得 Robocode 起作用。</font>
		</p>
		<p>
				<a name="1">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">下载并安装 Robocode</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">Robocode 是 Mathew Nelson 的智慧之作，他是 IBM Internet 部门 Advanced Technology 的软件工程师。请首先访问 IBM alphaWorks </font>
				<a href="http://www.alphaworks.ibm.com/tech/robocode/">
						<font face="Arial" color="#000080" size="2">Robocode</font>
				</a>
				<font face="Arial" color="#000080" size="2">页面。在这个页面上，您可以找到 Robocode 系统最新的可执行文件。这个分发包是一个自包含的安装文件，在下载该分发包之后，您就可以使用下面的命令行在您的系统上安装这个软件包（当然，我们假定您的机器上已经预安装了 Java VM（JDK 1.3.x））：</font>
				<font face="Arial" color="#000080" size="2">
						<code class="section">
								<br />
								<br />
						</code>
						<font face="Courier New">java -jar robocode-setup.jar<br /></font>
						<br /> 在安装过程中，Robocode 将问您是否要使用这个外部的 Java VM 来编译机器人。您也可以选择使用作为 Robocode 分发包一部分而提供的 Jikes 编译器。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">安装完成后，您可以通过 shell 脚本（robocode.sh）、批处理文件（robocode.bat）或桌面上的图标来启动 Robocode 系统。此时，战场将会出现。在此，您可以通过菜单调用 Robot Editor 和 compiler。</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">Robocode 系统组件</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">当您激活 Robocode 时，将看到两个相关的 GUI 窗口，这两个窗口构成了 Robocode 的 IDE：</font>
		</p>
		<ul>
				<li>
						<font face="Arial" color="#000080" size="2">战场 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">Robot Editor </font>
				</li>
		</ul>
		<p>
				<font face="Arial" color="#000080" size="2">图 1 展示了处于工作状态的战场和 Robot Editor。</font>
		</p>
		<br />
		<a name="figure1">
				<b>
						<font face="Arial" color="#000080" size="2">图 1. Robocode IDE</font>
				</b>
		</a>
		<br />
		<font face="Arial" color="#000080" size="2">
				<img height="509" alt="Robocode IDE" src="http://www-128.ibm.com/developerworks/cn/java/j-robocode/fig1.gif" width="600" />
				<br />
		</font>
		<p>
				<font face="Arial" color="#000080" size="2">战场是机器人之间进行战斗直至分出胜负的场地。主要的仿真引擎被置于其中，并且允许您在这里创建战斗、保存战斗以及打开新建的或现有的战斗。通过界面区域内的控件，您可以暂停或继续战斗、终止战斗、消灭任何机器人个体或获取任何机器人的统计数据。此外，您可以在此屏幕上激活 Robot Editor。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">Robot Editor 是一个定制的文本编辑器，它可以用于编辑生成机器人的 Java 源文件。在它的菜单里集成了 Java 编译器（用于编译机器人代码）以及定制的 Robot 打包器。由 Robot Editor 创建并成功编译的所有机器人都会处于战场上一个部署就绪的位置。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">Robocode 里的每个机器人都由一个或多个 Java 类构成。这些类可以被压缩成一个 JAR 包。为此，Robocode 的最新版本提供了一个可以在战场 GUI 窗口中激活的“Robot Packager”。</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="3">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">对 Robocode 机器人的详细分析</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">在写这篇文章时，Robocode 机器人是一个图形化的坦克。图 2 是一个典型的 Robocode 机器人的图解。</font>
		</p>
		<br />
		<a name="figure2">
				<b>
						<font face="Arial" color="#000080" size="2">图 2. 对 Robocode 机器人的详细分析</font>
				</b>
		</a>
		<br />
		<font face="Arial" color="#000080" size="2">
				<img height="209" alt="Robocode 机器人" src="http://www-128.ibm.com/developerworks/cn/java/j-robocode/fig2.gif" width="240" />
				<br />
		</font>
		<p>
				<font face="Arial" color="#000080" size="2">请注意，机器人有一门可以旋转的炮，炮上面的雷达也是可以旋转的。机器人坦克车（Vehicle）、炮（Gun）以及雷达（Radar）都可以单独旋转，也就是说，在任何时刻，机器人坦克车、炮以及雷达都可以转向不同的方向。缺省情况下，这些方向是一致的，都指向坦克车运动的方向。</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="4">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">Robot 命令</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">Robocode 机器人的命令集都收录在 Robocode API Javadoc 中。您将会发现这些命令都是 <code>robocode.Robot</code> 类的公共方法。在这一部分，我们将分类讨论每个可用的命令。 </font>
		</p>
		<p>
				<a name="N100C3">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">移动机器人、炮和雷达</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">让我们从移动机器人及其装备的基本命令开始：</font>
		</p>
		<ul>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>turnRight(double degree)</code> 和 <code>turnLeft(double degree)</code> 使机器人转过一个指定的角度。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>ahead(double distance)</code> 和 <code>back(double distance)</code> 使机器人移动指定的像素点距离；这两个方法在机器人碰到墙或另外一个机器人时即告完成。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>turnGunRight(double degree)</code> 和 <code>turnGunLeft(double degree)</code> 使炮可以独立于坦克车的方向转动。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>turnRadarRight(double degree)</code> 和 <code>turnRadarLeft(double degree)</code> 使炮上面的雷达转动，转动的方向也独立于炮的方向（以及坦克车的方向）。 </font>
								</font>
						</font>
				</li>
		</ul>
		<p>
				<font face="Arial" color="#000080" size="2">这些命令都是在执行完毕后才把控制权交还给程序。此外，转动坦克车的时候，除非通过调用下列方法分别指明炮（和雷达）的方向，否则炮（和雷达）的指向也将移动。</font>
		</p>
		<ul>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>setAdjustGunForRobotTurn(boolean flag)</code> ：如果 flag 被设置成 true，那么坦克车转动时，炮保持原来的方向。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>setAdjustRadarForRobotTurn(boolean flag)</code> ：如果 flag 被设置成 true，那么坦克车（和炮）转动时，雷达会保持原来的方向。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>setAdjustRadarForGunTurn(boolean flag)</code> ：如果 flag 被设置成 true，那么炮转动时，雷达会保持原来的方向。而且，它执行的动作如同调用了 <code>setAdjustRadarForRobotTurn(true)</code> 。 </font>
								</font>
						</font>
				</li>
		</ul>
		<p>
				<a name="N10124">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">获取关于机器人的信息</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">有许多方法可以得到关于机器人的信息。下面简单列举了常用的方法调用：</font>
		</p>
		<ul>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>getX()</code> 和 <code>getY()</code> 可以捕捉到机器人当前的坐标。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>getHeading()</code> 、 <code>getGunHeading()</code> 和 <code>getRadarHeading()</code> 可以得出坦克车、炮或雷达当前的方向，该方向是以角度表示的。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>getBattleFieldWidth()</code> 和 <code>getBattleFieldHeight()</code> 可以得到当前这一回合的战场尺寸。 </font>
								</font>
						</font>
				</li>
		</ul>
		<p>
				<a name="N10159">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">射击命令</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">一旦您掌握了移动机器人以及相关的武器装备的方法，您就该考虑射击和控制损害的任务了。每个机器人在开始时都有一个缺省的“能量级别”，当它的能量级别减小到零的时候，我们就认为这个机器人已经被消灭了。射击的时候，机器人最多可以用掉三个能量单位。提供给炮弹的能量越多，对目标机器人所造成的损害也就越大。 <code>fire(double power)</code> 和 <code>fireBullet(double power)</code> 用来发射指定能量（火力）的炮弹。调用的 <code>fireBullet()</code> 版本返回 <code>robocode.Bullet</code> 对象的一个引用，该引用可以用于高级机器人。 </font>
		</p>
		<p>
				<a name="N10172">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">事件</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">每当机器人在移动或转动时，雷达一直处于激活状态，如果雷达检测到有机器人在它的范围内，就会触发一个事件。作为机器人创建者，您有权选择处理可能在战斗中发生的各类事件。基本的 <code>Robot</code> 类中包括了所有这些事件的缺省处理程序。但是，您可以覆盖其中任何一个“什么也不做的”缺省处理程序，然后实现您自己的定制行为。下面是一些较为常用的事件： </font>
		</p>
		<ul>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>ScannedRobotEvent</code> 。通过覆盖 <code>onScannedRobot()</code> 方法来处理 <code>ScannedRobotEvent</code> ；当雷达检测到机器人时，就调用该方法。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>HitByBulletEvent</code> 。通过覆盖 <code>onHitByBullet()</code> 方法来处理 <code>HitByBulletEvent</code> ；当机器人被炮弹击中时，就调用该方法。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>HitRobotEvent</code> 。通过覆盖 <code>onHitRobot()</code> 方法来处理 <code>HitRobotEvent</code> ；当您的机器人击中另外一个机器人时，就调用该方法。 <br /></font>
								</font>
						</font>
				</li>
				<li>
						<font face="Arial">
								<font size="2">
										<font color="#000080">
												<code>HitWallEvent</code> 。通过覆盖 <code>onHitWall()</code> 方法来处理 <code>HitWallEvent</code> ；当您的机器人撞到墙时，就调用该方法。 </font>
								</font>
						</font>
				</li>
		</ul>
		<p>
				<font face="Arial" color="#000080" size="2">我们只需要知道这些就可以创建一些相当复杂的机器人了。您可以通过战场的帮助菜单或 Robot Editor 的帮助菜单访问 Javadoc 中其余的 Robocode API。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">现在，我们该把学到的知识付诸实践了。</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="5">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">创建机器人</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">要创建一个新的机器人，请启动 Robot Editor 并选择 <b>File</b>-&gt; <b>New</b>-&gt; <b>Robot</b>。系统将会提示您输入机器人的名称，这个名称将成为 Java 类名。请您在提示符处输入 <b>DWStraight</b>。接下来，系统还会提示您输入一个独一无二的包前缀，它将用作存放机器人（还可能有相关的 Java 文件）的包的名称。请在该提示符处输入 <b>dw</b>。 </font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">Robot Editor 就会显示您要控制这个机器人需要编写的 Java 代码。清单 1 是您将会看到的代码的一个示例：</font>
		</p>
		<br />
		<a name="code1">
				<b>
						<font face="Arial" color="#000080" size="2">清单 1. Robocode 生成的 Robot 代码</font>
				</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Arial" color="#000080" size="2">package dw;
import robocode.*;

/**
 * DWStraight - a robot by (developerWorks)
 */
public class DWStraight extends Robot
{
    ...  // &lt;&lt;Area 1&gt;&gt;
    /**
     * run: DWStraight's default behavior
     */
    public void run() {
        ... // &lt;&lt;Area 2&gt;&gt;
        while(true) {
        ... // &lt;&lt;Area 3&gt;&gt;
        }
    }
      ... // &lt;&lt;Area 4&gt;&gt;
    public void onScannedRobot(ScannedRobotEvent e) {
        fire(1);
    }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<font face="Arial" color="#000080" size="2">突出显示的区域就是我们添加控制机器人的代码的地方：</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 1</b>
										<br />我们可以在这片空白里声明类作用域变量并设置这些变量的值。这些变量可以在机器人的 <code>run()</code> 方法内以及其他一些您可能创建的助手方法内使用。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 2</b>
										<br />战斗管理器调用 <code>run()</code> 方法激活机器人。典型情况下，run() 方法包括两个区域（即在清单 1 中指出的 Area 2 和 Area 3），您可以在这两块空白里添加代码。您在 Area 2 中加入的代码每个机器人实例只运行一次。这部分代码通常用于使机器人先处于一种预设状态后再开始执行重复行为。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 3</b>
										<br />这是典型的 <code>run()</code> 方法实现的第二部分。在此，我们将在无限 <code>while</code> 循环内对机器人可能执行的重复行为进行编程。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 4</b>
										<br />您可以在这一区域内添加机器人在 <code>run()</code> 逻辑内使用的助手方法。您也可以在此添加您想要覆盖的任何事件处理程序。例如，清单 1 里的代码处理 <code>ScannedRobot</code> 事件，每当雷达检测到机器人的时候，只是直接向其发射炮弹。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">我们对第一个机器人（DWStraight）的代码的更新如清单 2 中红色标记所示。</font>
		</p>
		<br />
		<a name="code2">
				<b>
						<font face="Arial" color="#000080" size="2">清单 2. DWStraight 机器人代码的增加部分</font>
				</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Arial" color="#000080" size="2">package dw;
import robocode.*;

public class DWStraight extends Robot
{
    public void run() {
        turnLeft(getHeading());
        while(true) {
            ahead(1000);
            turnRight(90);

        }
    }
         public void onScannedRobot(ScannedRobotEvent e) {
        fire(1);
    }
    public void onHitByBullet(HitByBulletEvent e) {
        turnLeft(180);
    }
      
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<font face="Arial" color="#000080" size="2">下面我们逐区地描述这个第一个机器人将做些什么：</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 1</b>我们没有在这个机器人的程序中指定任何类作用域变量。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 2</b>
										<br />为了使机器人处于已知的状态，我们通过 <code>turnLeft(getHeading())</code> 使它转到 0 度的方向。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 3</b>
										<br />在这个重复性的部分，我们使用语句 <code>ahead(1000)</code> 让机器人尽其所能向前移动到最远的地方。当机器人撞到墙或其他机器人时，就会停下来。接着，我们通过 <code>turnRight(90)</code> 使它向右转。在重复执行这一行为时，机器人基本上是在沿着墙按顺时针方向移动。 </font>
						</font>
				</font>
		</p>
		<p>
				<font face="Arial">
						<font size="2">
								<font color="#000080">
										<b>Area 4</b>
										<br />在此，除处理自动生成的 <code>ScannedRobot</code> 事件并向被发现的机器人直接射击之外，我们还会检测 <code>HitByBullet</code> 事件，并且让机器人在被击中的时候转过 180 度（沿顺时针方向或逆时针方向）。 </font>
						</font>
				</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="6">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">编译以及测试机器人</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">在 Robot Editor 菜单上选择 <b>Compiler</b>-&gt; <b>Compile</b>编译您的机器人代码。现在我们可以尝试第一回合的战斗了。切换回战场并选择菜单上的 <b>Battle</b>-&gt; <b>New</b>，将会出现一个类似于图 3 中所示的对话框。 </font>
		</p>
		<br />
		<a name="figure3">
				<b>
						<font face="Arial" color="#000080" size="2">图 3. New Battle 对话框</font>
				</b>
		</a>
		<br />
		<font face="Arial" color="#000080" size="2">
				<img height="440" alt="New Battle 对话框" src="http://www-128.ibm.com/developerworks/cn/java/j-robocode/fig3.gif" width="584" />
				<br />
		</font>
		<p>
				<font face="Arial" color="#000080" size="2">请先将我们的机器人 dw.DWStraight 添加到战斗中，然后再添加一个对手机器人，比如 sample.SittingDuck。单击 <b>Finish</b>，战斗就开始了。不可否认，同 SittingDuck 战斗并不怎么有趣，但是您可以目睹这个叫做 DWStraight 的机器人在缺省情况下的行为。试试 sample 文件夹里的其他机器人，看看 DWStraight 同这些机器人的战斗情况如何。 </font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">当您准备开始研究另外一个机器人的代码时，请先看看随 </font>
				<a href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#resources">
						<font face="Arial" color="#000080" size="2">参考资料</font>
				</a>
				<font face="Arial" color="#000080" size="2">中的代码分发包一起提供的 dw.DWRotater 这个机器人的代码。在缺省情况下，这个机器人将会： </font>
		</p>
		<ul>
				<li>
						<font face="Arial" color="#000080" size="2">移动到战场中心 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">一直转动它的炮，直到检测到机器人 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">每次尝试以不同的角度在离被检测到的机器人前方不远的地方射击 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">每当它被另外一个机器人击中时，它都会迅速的来回移动 </font>
				</li>
		</ul>
		<p>
				<font face="Arial" color="#000080" size="2">这段代码简单易懂，所以我们在这里就不做分析了，但是我鼓励您试验一下。Robocode 中的 sample 包还提供了许多其他机器人的代码。</font>
		</p>
		<p>
				<a name="N102AF">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">附加的机器人支持类</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">随着您设计机器人的水平的提高，机器人的代码主体将充分增长。对这些代码的一种模块化处理方法是把代码分解成独立的 Java 类，然后通过打包器把这些 Java 类打包成一个单独的包（JAR 文件），并将它包括在您的机器人分发包内。Robocode 将自动在它的 robots 目录下的包里找到 robot 类。</font>
		</p>
		<p>
				<a name="N102B8">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">其他 Robot 子类</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">任何人都可以创建 <code>Robot</code> 子类并添加用于构建机器人的新功能。Robocode 提供了一个叫做 <code>AdvancedRobot</code> 的 <code>Robot</code> 子类，它允许异步 API 调用。虽然对 <code>AdvancedRobot</code> 类的描述超出了本文的范围，但我鼓励您在掌握了基本的 <code>Robot</code> 类的操作后，试验一下这个高级类。 </font>
		</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
										</font>
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="sidebar">
																				<b>
																						<font face="Arial" color="#000080" size="2">设计 Robocode 的目的</font>
																				</b>
																		</a>
																		<br />
																		<p>
																				<font face="Arial" color="#000080" size="2">我碰见了 Robocode 的创建者 Mathew Nelson，向他请教创建 Robocode 最初的设计目的。Mat 所说的是：“编写 Robocode 的一部分目的是为了向世界证明：象‘Java 比较慢’以及‘Java 不可以用来写游戏’之类的论断不再正确。我认为我证明了这一点。”</font>
																		</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="7">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">战斗仿真器的体系结构</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">通过“在后台”对 Robocode 进行分析，我们发现复杂的仿真引擎既具高性能（为了以现实的速度生成战斗）又具灵活性（使创建复杂的机器人逻辑不存在障碍）。特别感谢 Robocode 的创建者 Mathew Nelson 无私的提供了仿真引擎体系结构的内部信息。</font>
		</p>
		<p>
				<a name="N102EA">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">利用 Java 平台进行设计</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">图 4 中所示的仿真引擎利用的是大多数现代的 Java VM 都提供的非抢占式线程技术，并结合使用了 JDK GUI 和 2D 图形库提供的生成功能。</font>
		</p>
		<br />
		<a name="figure4">
				<b>
						<font face="Arial" color="#000080" size="2">图 4. Robocode 仿真引擎体系结构</font>
				</b>
		</a>
		<br />
		<font face="Arial" color="#000080" size="2">
				<img height="233" alt="仿真引擎" src="http://www-128.ibm.com/developerworks/cn/java/j-robocode/fig4.gif" width="450" />
				<br />
		</font>
		<p>
				<font face="Arial" color="#000080" size="2">请注意，所仿真的每个机器人都在它自己的 Java 线程上，它可以在任何可适用的地方利用 VM 本地线程映射机制。战斗管理器线程是系统的控制器：它安排仿真并驱动图形化的生成子系统。图形化的生成子系统本身是基于 Java 2D 和 AWT 的。</font>
		</p>
		<p>
				<a name="N10305">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">松散的线程耦合</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">为了减少共享资源可能带来的问题（以及有可能随之出现的死锁或阻塞仿真引擎），战斗管理器线程和机器人线程之间的耦合应当非常松散。为了实现这种松散耦合，每个机器人线程都将有属于自己的事件队列。获取及处理这些事件都是在每个机器人自己的线程内进行。这种基于线程的队列有效地消除了战斗管理器线程和机器人线程之间（或机器人线程本身之间）可能存在的任何争用。</font>
		</p>
		<p>
				<a name="N1030E">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">Robocode 内部结构</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">您可以把 Robocode 仿真器引擎看作是一个仿真器程序，该程序在运行时会使用一些插件（定制机器人）；这些插件可以利用已有的 API（ <code>robocode.Robot</code> 类的方法）。实际上，每个机器人都是一个独立的 Java 线程，同时 <code>run()</code> 方法内包含了每个线程上将要执行的逻辑。 </font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">在任何时候，机器人线程都可以调用由它的父类 <code>robocoode.Robot</code> 类所提供的 API。典型情况下，这将通过调用 <code>Object.wait()</code> 阻塞机器人线程。 </font>
		</p>
		<p>
				<a name="N1032A">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">战斗管理器线程</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">战斗管理器线程管理机器人、炮弹及它们在战场上的生成。仿真“时钟”是根据战场上生成的帧的数目来标记的。用户可以调整真实的帧的速度。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">在一个典型的回合中，战斗管理器线程唤醒每个机器人线程，然后等待机器人完成它的一轮战斗(即，再次调用一个阻塞 API）。等待的间隔时间通常是几十毫秒，即使是最复杂的机器人，使用现今典型的系统速度进行策略安排和计算，也只要 1 到 2 毫秒的时间。</font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">以下是战斗管理器线程执行的逻辑的伪代码：</font>
		</p>
		<br />
		<a name="code3">
				<b>
						<font face="Arial" color="#000080" size="2">清单 3. 战斗管理器的逻辑的伪代码</font>
				</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Arial" color="#000080" size="2">while (round is not over) do
   call the rendering subsystem to draw robots, bullets, explosions
   for  each robot do
       wake up the robot
       wait for it to make a blocking call, up to a max time interval
   end for
   clear all robot event queue
   move bullets, and generate event into robots' event queue if applicable
   move robots, and generate event into robots' event queue if applicable
   do battle housekeeping and generate event into robots' event queue
         if applicable
   delay for frame rate if necessary
end do
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<font face="Arial" color="#000080" size="2">请注意，在 for 循环内部，战斗管理器线程的等待时间不会超过最大的时间间隔。如果机器人线程没有及时调用阻塞 API（典型情况下是由于一些应用程序逻辑错误或无限循环），那么，它将继续进行战斗。生成一个 <code>SkippedTurnEvent</code> 并将其加入机器人事件队列中，用来通知高级机器人。 </font>
		</p>
		<p>
				<a name="N1034A">
						<span class="smalltitle">
								<strong>
										<font face="Arial" color="#000080" size="2">可替换的生成子系统</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">AWT 和 Java 2D 线程就是当前实现中的生成子系统，它从战斗管理器中获取命令并生成战场。它同系统的其余部分是完全分离的。我们可以预见到，在这个生成子系统将来的修订版中，它可以被替换掉（比如，用 3-D 生成器）。在当前的实现中，只要 Robocode 应用程序被最小化，生成就禁用了，这可以以更快的速度进行仿真。</font>
		</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="8">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">Robocode 的未来</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">通过 alphaWorks Robocode 站点上的一个讨论组（请参阅 </font>
				<a href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#resources">
						<font face="Arial" color="#000080" size="2">参考资料</font>
				</a>
				<font face="Arial" color="#000080" size="2">），Mathew Nelson 可以同 Robocode 用户社区保持紧密的反馈联系。许多反馈都并入了真实的代码中。Mathew 已计划即将要进行的一些改进有： </font>
		</p>
		<ul>
				<li>
						<font face="Arial" color="#000080" size="2">通过不同的物体和障碍来定制战场地图 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">基于团队的战斗 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">对联赛或联盟的集成支持 </font>
				</li>
				<li>
						<font face="Arial" color="#000080" size="2">用户可选择坦克车体／炮／雷达／武器的样式 </font>
				</li>
		</ul>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Arial" color="#000080" size="2">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Arial" color="#000080" size="2">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-robocode/#main">
																				<b>
																						<font face="Arial" color="#000080" size="2">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="9">
						<span class="atitle">
								<font face="Arial" color="#000080" size="2">挡不住的 Robocode 风潮</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">对于一个从 2001 年 7 月 12 日出现在公众面前的项目，Robocode 的出名简直让人吃惊。尽管最新的可用版本还不到 1.0（在写这篇文章时是版本 0.98.2），但它已经是全世界的大学校园以及公司的 PC 机上颇受欢迎的娱乐活动了。Robocode 联盟（或 <i>roboleagues</i>）正如雨后春笋般出现，在这些联盟里，人们通过因特网让自己定制的作品相互较量。大学教授们一直在挖掘 Robocode 的教育特性，并且已经把它纳入了大学里的计算机科学课程。在因特网上，Robocode 用户组、讨论列表、FAQ、教程和 Webring 随处可见。 </font>
		</p>
		<p>
				<font face="Arial" color="#000080" size="2">显然，Robocode 已经填补了大众化的寓教于乐领域的空白 ― 它为学生们和熬夜的工程师们提供简便、有趣、非胁迫却富竞争力的方式，释放他们的创造力，而且有可能实现他们征服世界的梦想。</font>
		</p>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/10235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-19 20:55 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/19/10235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]学习的方法（工作两年之后的总结）</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10228.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Wed, 19 Jul 2006 08:32:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10228.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/10228.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/19/10228.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/10228.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/10228.html</trackback:ping><description><![CDATA[
		<font face="Arial" color="#000080" size="2">作为程序员，应该是最为辛苦的一件事情，通宵达旦的熬夜，把自己的血汗无偿的捐献给了Boss ，同时还得小心自己落伍，明天要学习，再学习，因为技术更新实在是太快，JDK1.4还没有搞定， JDK5.0已经开始普及了，等俺们开始用上了5.0，6.0已经开始发布测试版了，7.0也在磨刀霍霍之中，危机感始终是笼罩在自己头上，怎么办？ 难道我们程序员就是这样的生活？ <br /><br />    真想好好的休息一下，放松自己的神经！ 但是不能！怎么办？ 工作两年了，真的是感觉到了这种辛苦。那怎么才能够改变这种现象呢？方法，改变我们学习的方法，这是我最近一直在思考的事情。新技术曾出不穷，我们不可能永远跟得上脚步，所以我们要掌握自己的主动权。 <br /><br />   第一，要有好的心态，我们选择了这一行，没有什么可以抱怨的。<br /><br />   第二，经常反省自己，看能不能变得更好。 每天都会有收获，所以呢，每天都可以发现自己的不足。Matrin Folwer说，如果，两年后，你还是认为两年前的自己已经很优秀的话，那说明你没有进步。 <br /><br />   第三，要总结，把自己明天的心得都记下来，记录自己的脚步。 <br /><br />   第四，要钻研，要做就把它做好。碰到困难更是要迎难而上，这时候才是学习的最好机会。<br /><br />   第五，不要有畏惧心理，不要怕做不好。相信自己。<br /><br />   第六，要学会使用文档，俺的头这一点最让人佩服，不会的问题，看文档，很快就可以搞定，当然，前提是他英语实在是高。没有语言障碍。 <br /><br />    第七，就是上面说的，作为程序员，要学好英语。这是很重要。 <br /><br />    还有就是，程序员每天该做的事，好东西。<br /><font color="#ff0000"><br /><br />写的真的很好，不过我发现人坚持干一件事情真的很难。</font></font>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/10228.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-19 16:32 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/19/10228.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java线程总结 </title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9763.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Wed, 12 Jul 2006 08:38:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9763.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9763.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9763.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9763.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9763.html</trackback:ping><description><![CDATA[
		<font face="Arial" color="#000080" size="2">在论坛上面常常看到初学者对线程的无可奈何，所以总结出了下面一篇文章，希望对一些正在学习使用java线程的初学者有所帮助。<br /><br />首先要理解线程首先需要了解一些基本的东西，我们现在所使用的大多数操作系统都属于多任务，分时操作系统。正是由于这种操作系统的出现才有了多线程这个概念。我们使用的windows,linux就属于此列。什么是分时操作系统呢，通俗一点与就是可以同一时间执行多个程序的操作系统，在自己的电脑上面，你是不是一边听歌，一边聊天还一边看网页呢？但实际上，并不上cpu在同时执行这些程序，cpu只是将时间切割为时间片，然后将时间片分配给这些程序，获得时间片的程序开始执行，不等执行完毕，下个程序又获得时间片开始执行，这样多个程序轮流执行一段时间，由于现在cpu的高速计算能力，给人的感觉就像是多个程序在同时执行一样。<br />一般可以在同一时间内执行多个程序的操作系统都有进程的概念.一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源.在进程概念中,每一个进程的内部数据和状态都是完全独立的.因此可以想像创建并执行一个进程的系统开像是比较大的，所以线程出现了。在java中，程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务.多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行.（你可以将前面一句话的程序换成进程，进程是程序的一次执行过程,是系统运行程序的基本单位）<br /><br />线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈.所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程也被称为轻负荷进程(light-weight process).一个进程中可以包含多个线程.<br /><br />多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程，同进程一样,一个线程也有从创建,运行到消亡的过程,称为线程的生命周期.用线程的状态(state)表明线程处在生命周期的哪个阶段.线程有创建,可运行,运行中,阻塞,死亡五中状态.通过线程的控制与调度可使线程在这几种状态间转化每个程序至少自动拥有一个线程,称为主线程.当程序加载到内存时,启动主线程.<br /><br />[线程的运行机制以及调度模型] <br />java中多线程就是一个类或一个程序执行或管理多个线程执行任务的能力，每个线程可以独立于其他线程而独立运行，当然也可以和其他线程协同运行，一个类控制着它的所有线程，可以决定哪个线程得到优先级，哪个线程可以访问其他类的资源，哪个线程开始执行，哪个保持休眠状态。<br />下面是线程的机制图：<br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://blog.matrix.org.cn/resources/Kaizen/Thread.jpg" onload="javascript:imgLoad(this);" border="0" /><br /><br />线程的状态表示线程正在进行的活动以及在此时间段内所能完成的任务.线程有创建,可运行,运行中,阻塞,死亡五中状态.一个具有生命的线程,总是处于这五种状态之一：<br /><b>1.创建状态</b><br />使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread)<br /><b>2.可运行状态</b><br />使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable)<br /><b>3.运行中状态</b><br />Java运行系统通过调度选中一个Runnable的线程,使其占有CPU并转为运行中状态(Running).此时,系统真正执行线程的run()方法.<br /><b>4.阻塞状态</b><br />一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态(Blocked)<br /><b>5.死亡状态</b><br />线程结束后是死亡状态(Dead)<br /><br />同一时刻如果有多个线程处于可运行状态,则他们需要排队等待CPU资源.此时每个线程自动获得一个线程的优先级(priority),优先级的高低反映线程的重要或紧急程度.可运行状态的线程按优先级排队,线程调度依据优先级基础上的"先到先服务"原则.<br />线程调度管理器负责线程排队和CPU在线程间的分配,并由线程调度算法进行调度.当线程调度管理器选种某个线程时,该线程获得CPU资源而进入运行状态.<br /><br />线程调度是先占式调度,即如果在当前线程执行过程中一个更高优先级的线程进入可运行状态,则这个线程立即被调度执行.先占式调度分为:独占式和分时方式.<br />独占方式下,当前执行线程将一直执行下去,直 到执行完毕或由于某种原因主动放弃CPU,或CPU被一个更高优先级的线程抢占<br />分时方式下,当前运行线程获得一个时间片,时间到时,即使没有执行完也要让出CPU,进入可运行状态,等待下一个时间片的调度.系统选中其他可运行状态的线程执行<br />分时方式的系统使每个线程工作若干步,实现多线程同时运行<br /><br />另外请注意下面的线程调度规则（如果有不理解，不急，往下看）：<br />①如果两个或是两个以上的线程都修改一个对象，那么把执行修改的方法定义为被同步的（Synchronized）,如果对象更新影响到只读方法，那么只度方法也应该定义为同步的<br />②如果一个线程必须等待一个对象状态发生变化，那么它应该在对象内部等待，而不是在外部等待，它可以调用一个被同步的方法，并让这个方法调用wait()<br />③每当一个方法改变某个对象的状态的时候，它应该调用notifyAll()方法，这给等待队列的线程提供机会来看一看执行环境是否已发生改变<br />④记住wait(),notify(),notifyAll()方法属于Object类，而不是Thread类，仔细检查看是否每次执行wait()方法都有相应的notify()或notifyAll()方法，且它们作用与相同的对象 在java中每个类都有一个主线程，要执行一个程序，那么这个类当中一定要有main方法，这个man方法也就是java class中的主线程。你可以自己创建线程，有两种方法，一是继承Thread类，或是实现Runnable接口。一般情况下，最好避免继承，因为java中是单根继承，如果你选用继承，那么你的类就失去了弹性，当然也不能全然否定继承Thread,该方法编写简单,可以直接操作线程,适用于单重继承情况。至于选用那一种，具体情况具体分析。<br /><br /><br /><b>eg.继承Thread</b><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public class MyThread_1 extends Thread<br />{<br />public void run()<br />{<br />//some code <br />}<br />}</font>
		</pre>
		<br />
		<br />
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<b>eg.实现Runnable接口</b>
								<br />
						</font>
				</font>
		</font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public class MyThread_2 implements Runnable<br />{<br />public void run()<br />{<br />//some code <br />}<br />}</font>
		</pre>
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">当使用继承创建线程，这样启动线程：<br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">new MyThread_1().start()</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">当使用实现接口创建线程，这样启动线程：<br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">new Thread(new MyThread_2()).start()</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">注意，其实是创建一个线程实例，并以实现了Runnable接口的类为参数传入这个实例，当执行这个线程的时候，MyThread_2中run里面的代码将被执行。<br />下面是完成的例子：<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public class MyThread implements Runnable<br />{ <br /><br />public void run()<br />{ <br />System.out.println("My Name is "+Thread.currentThread().getName()); <br />} <br />public static void main(String[] args)<br />{<br />new Thread(new MyThread()).start(); <br />}<br />} </font>
		</pre>
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">执行后将打印出：<br /><span style="COLOR: blue">My Name is Thread-0</span><br /><br />你也可以创建多个线程，像下面这样<br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">new Thread(new MyThread()).start();<br />new Thread(new MyThread()).start();<br />new Thread(new MyThread()).start();</font>
		</pre>
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">那么会打印出：<br /></font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">My Name is Thread-0<br />My Name is Thread-1<br />My Name is Thread-2</span>
								<br />
								<br />看了上面的结果，你可能会认为线程的执行顺序是依次执行的，但是那只是一般情况，千万不要用以为是线程的执行机制；影响线程执行顺序的因素有几点：首先看看前面提到的优先级别<br /><br /><br /></font>
				</font>
		</font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public class MyThread implements Runnable<br />{ <br /><br />public void run()<br />{ <br />System.out.println("My Name is "+Thread.currentThread().getName()); <br />} <br />public static void main(String[] args)<br />{<br />Thread t1=new Thread(new MyThread());<br />Thread t2=new Thread(new MyThread());<br />Thread t3=new Thread(new MyThread());<br />t2.setPriority(Thread.MAX_PRIORITY);//赋予最高优先级<br />t1.start();<br />t2.start();<br />t3.start();<br />}<br />} </font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">再看看结果：<br /></font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">My Name is Thread-1<br />My Name is Thread-0<br />My Name is Thread-2</span>
								<br />
								<br />
								<br />线程的优先级分为10级，分别用1到10的整数代表，默认情况是5。上面的t2.setPriority(Thread.MAX_PRIORITY)等价与t2.setPriority(10）<br />然后是线程程序本身的设计，比如使用sleep,yield,join，wait等方法（详情请看JDKDocument)<br /><br /></font>
				</font>
		</font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public class MyThread implements Runnable<br />{ <br />public void run()<br />{ <br />try<br />{<br />int sleepTime=(int)(Math.random()*100);//产生随机数字，<br />Thread.currentThread().sleep(sleepTime);//让其休眠一定时间，时间又上面sleepTime决定<br />//public static void sleep(long millis)throw InterruptedException （API）<br />System.out.println(Thread.currentThread().getName()+" 睡了 "+sleepTime);<br />}catch(InterruptedException ie)//由于线程在休眠可能被中断，所以调用sleep方法的时候需要捕捉异常<br />{<br />ie.printStackTrace();<br />} <br />} <br />public static void main(String[] args)<br />{<br />Thread t1=new Thread(new MyThread());<br />Thread t2=new Thread(new MyThread());<br />Thread t3=new Thread(new MyThread());<br />t1.start();<br />t2.start();<br />t3.start();<br />}<br />}</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">执行后观察其输出：<br /><br /></font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">Thread-0 睡了 11<br />Thread-2 睡了 48<br />Thread-1 睡了 69</span>
								<br />
								<br />
								<br />
								<br />上面的执行结果是随机的，再执行很可能出现不同的结果。由于上面我在run中添加了休眠语句，当线程休眠的时候就会让出cpu，cpu将会选择执行处于runnable状态中的其他线程，当然也可能出现这种情况，休眠的Thread立即进入了runnable状态，cpu再次执行它。<br />[线程组概念]<br />线程是可以被组织的，java中存在线程组的概念，每个线程都是一个线程组的成员,线程组把多个线程集成为一个对象,通过线程组可以同时对其中的多个线程进行操作,如启动一个线程组的所有线程等.Java的线程组由java.lang包中的Thread——Group类实现.<br />ThreadGroup类用来管理一组线程,包括:线程的数目,线程间的关系,线程正在执行的操作,以及线程将要启动或终止时间等.线程组还可以包含线程组.在Java的应用程序中,最高层的线程组是名位main的线程组,在main中还可以加入线程或线程组,在mian的子线程组中也可以加入线程和线程组,形成线程组和线程之间的树状继承关系。像上面创建的线程都是属于main这个线程组的。<br />借用上面的例子，main里面可以这样写：<br /><br /></font>
				</font>
		</font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">public static void main(String[] args)<br />{<br />/***************************************<br />ThreadGroup(String name) <br />ThreadGroup(ThreadGroup parent, String name) <br />***********************************/<br />ThreadGroup group1=new ThreadGroup("group1");<br />ThreadGroup group2=new ThreadGroup(group1,"group2");<br />Thread t1=new Thread(group2,new MyThread());<br />Thread t2=new Thread(group2,new MyThread());<br />Thread t3=new Thread(group2,new MyThread());<br />t1.start();<br />t2.start();<br />t3.start();<br />}</font>
		</pre>
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">线程组的嵌套，t1,t2,t3被加入group2,group2加入group1。<br />另外一个比较多就是关于线程同步方面的，试想这样一种情况，你有一笔存款在银行，你在一家银行为你的账户存款，而你的妻子在另一家银行从这个账户提款，现在你有1000块在你的账户里面。你存入了1000，但是由于另一方也在对这笔存款进行操作，人家开始执行的时候只看到账户里面原来的1000元，当你的妻子提款1000元后，你妻子所在的银行就认为你的账户里面没有钱了，而你所在的银行却认为你还有2000元。<br />看看下面的例子：<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">class BlankSaving //储蓄账户<br />{<br />private static int money=10000;<br />public void add(int i)<br />{<br />money=money+i;<br />System.out.println("Husband 向银行存入了 [￥"+i+"]");<br />}<br />public void get(int i)<br />{<br />money=money-i;<br />System.out.println("Wife 向银行取走了 [￥"+i+"]");<br />if(money&lt;0)<br />System.out.println("余额不足！"); <br />}<br />public int showMoney()<br />{<br />return money;<br />}<br />} <br /><br /><br />class Operater implements Runnable<br />{<br />String name;<br />BlankSaving bs;<br />public Operater(BlankSaving b,String s)<br />{<br />name=s;<br />bs=b;<br /><br /><br /><br />}<br />public static void oper(String name,BlankSaving bs)<br />{<br /><br /><br /><br />if(name.equals("husband"))<br />{<br />try<br />{<br />for(int i=0;i&lt;10;i++)<br />{<br />Thread.currentThread().sleep((int)(Math.random()*300));<br />bs.add(1000);<br />}<br />}catch(InterruptedException e){}<br />}else<br />{<br />try<br />{<br /><br /><br /><br />for(int i=0;i&lt;10;i++)<br />{<br />Thread.currentThread().sleep((int)(Math.random()*300));<br />bs.get(1000);<br />}<br />}catch(InterruptedException e){}<br />}<br />}<br />public void run()<br />{<br />oper(name,bs);<br />} <br />}<br />public class BankTest <br />{<br />public static void main(String[] args)throws InterruptedException<br />{<br />BlankSaving bs=new BlankSaving();<br />Operater o1=new Operater(bs,"husband");<br />Operater o2=new Operater(bs,"wife");<br />Thread t1=new Thread(o1);<br />Thread t2=new Thread(o2);<br />t1.start();<br />t2.start();<br />Thread.currentThread().sleep(500);<br />}<br /><br /><br /><br />}</font>
		</pre>
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">下面是其中一次的执行结果：<br /><br /><br /><br /></font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">---------first--------------<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Husband 向银行存入了 [￥1000]</span>
								<br />
								<br />看到了吗，这可不是正确的需求，在husband还没有结束操作的时候，wife就插了进来，这样很可能导致意外的结果。解决办法很简单，就是将对数据进行操作方法声明为synchronized,当方法被该关键字声明后，也就意味着，如果这个数据被加锁，只有一个对象得到这个数据的锁的时候该对象才能对这个数据进行操作。也就是当你存款的时候，这笔账户在其他地方是不能进行操作的，只有你存款完毕，银行管理人员将账户解锁，其他人才能对这个账户进行操作。<br />修改public static void oper(String name,BlankSaving bs)为public static void oper(String name,BlankSaving bs)，再看看结果:<br /><br /></font>
				</font>
		</font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Husband 向银行存入了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]<br />Wife 向银行取走了 [￥1000]</span>
								<br />
								<br />
								<br />
								<br />当丈夫完成操作后，妻子才开始执行操作，这样的话，对共享对象的操作就不会有问题了。<br />[wait and notify]<br />你可以利用这两个方法很好的控制线程的执行流程，当线程调用wait方法后，线程将被挂起，直到被另一线程唤醒（notify）或则是如果wait方法指定有时间得话，在没有被唤醒的情况下，指定时间时间过后也将自动被唤醒。但是要注意一定，被唤醒并不是指马上执行，而是从组塞状态变为可运行状态，其是否运行还要看cpu的调度。<br />事例代码：<br /><br /></font>
				</font>
		</font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">class MyThread_1 extends Thread<br />{<br />Object lock;<br />public MyThread_1(Object o)<br />{<br />lock=o;<br />}<br />public void run()<br />{<br />try<br />{<br />synchronized(lock)<br />{<br />System.out.println("Enter Thread_1 and wait");<br />lock.wait();<br />System.out.println("be notified");<br />}<br />}catch(InterruptedException e){}<br />}<br />}<br />class MyThread_2 extends Thread<br />{<br />Object lock;<br />public MyThread_2(Object o)<br />{<br />lock=o;<br />}<br />public void run()<br />{<br />synchronized(lock)<br />{<br />System.out.println("Enter Thread_2 and notify");<br />lock.notify();<br />}<br />}<br />}<br />public class MyThread<br />{ <br />public static void main(String[] args)<br />{<br />int[] in=new int[0];//notice<br />MyThread_1 t1=new MyThread_1(in);<br />MyThread_2 t2=new MyThread_2(in);<br />t1.start();<br />t2.start();<br />}<br />}</font>
		</pre>
		<br />
		<br />
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">执行结果如下：<br /></font>
		<font face="Arial">
				<font size="2">
						<font color="#000080">
								<span style="COLOR: blue">Enter Thread_1 and wait<br />Enter Thread_2 and notify<br />Thread_1 be notified</span>
								<br />
								<br />可能你注意到了在使用wait and notify方法得时候我使用了synchronized块来包装这两个方法，这是由于调用这两个方法的时候线程必须获得锁，也就是上面代码中的lock[]，如果你不用synchronized包装这两个方法的得话，又或则锁不一是同一把，比如在MyThread_2中synchronized(lock)改为synchronized(this),那么执行这个程序的时候将会抛出java.lang.IllegalMonitorStateException执行期异常。另外wait and notify方法是Object中的，并不在Thread这个类中。最后你可能注意到了这点：int[] in=new int[0];为什么不是创建new Object而是一个0长度的数组，那是因为在java中创建一个0长度的数组来充当锁更加高效。<br /><br />Thread作为java中一重要组成部分，当然还有很多地方需要更深刻的认识，上面只是对Thread的一些常识和易错问题做了一个简要的总结，若要真正的掌握java的线程，还需要自己多做总结</font>
				</font>
		</font>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9763.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-12 16:38 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/12/9763.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]经典java问题</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9753.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Wed, 12 Jul 2006 08:02:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9753.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9753.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/12/9753.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9753.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9753.html</trackback:ping><description><![CDATA[
		<font face="Arial" color="#000080" size="2">第一，谈谈final, finally, finalize的区别。<br /><br />　　<br />final—修饰符（关键字）如果一个类被声明为final，意味着它不能再派生出新的子类，不能作为父类被继承。因此一个类不能既被声明为 abstract的，又被声明为final的。将变量或方法声明为final，可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值，而在以后的引用中只能读取，不可修改。被声明为final的方法也同样只能使用，不能重载。<br /><br />　　<br />finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常，那么相匹配的 catch 子句就会执行，然后控制就会进入 finally 块（如果有的话）。<br /><br />　　<br />finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的，因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。<br /><br /><br />　　<br />第二，Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)?<br /><br />　　<br />匿名的内部类是没有名字的内部类。不能extends(继承) 其它类，但一个内部类可以作为一个接口，由另一个内部类实现。<br /><br /><br />　　<br />第三，Static Nested Class 和 Inner Class的不同，说得越多越好(面试题有的很笼统)。<br /><br />　　<br />Nested Class （一般是C++的说法），Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&amp;page=1<br /><br />　　<br />注： 静态内部类（Inner Class）意味着1创建一个static内部类的对象，不需要一个外部类对象，2不能从一个static内部类的一个对象访问一个外部类对象<br /><br /><br />　　<br />第四，&amp;和&amp;&amp;的区别。<br /><br />　　<br />&amp;是位运算符。&amp;&amp;是布尔逻辑运算符。<br /><br /><br />　　<br />第五，HashMap和Hashtable的区别。<br /><br />　　<br />都属于Map接口的类，实现了将惟一键映射到特定的值上。<br /><br />　　<br />HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。<br /><br />　　<br />Hashtable 类似于 HashMap，但是不允许 null 键和 null 值。它也比 HashMap 慢，因为它是同步的。<br /><br /><br />　　<br />第六，Collection 和 Collections的区别。<br /><br />　　<br />Collections是个java.util下的类，它包含有各种有关集合操作的静态方法。<br /><br />　　<br />Collection是个java.util下的接口，它是各种集合结构的父接口。<br /><br /><br /><br />　　<br />第七，什么时候用assert。<br /><br />　　<br />断言是一个包含布尔表达式的语句，在执行这个语句时假定该表达式为 true。如果表达式计算为 false，那么系统会报告一个 Assertionerror。它用于调试目的：<br /><br />　　<br />assert(a &gt; 0); // throws an Assertionerror if a &lt;= 0<br /><br />　　<br /><br />断言可以有两种形式：<br /><br />　　<br />assert Expression1 ;<br /><br />　 <br />assert Expression1 : Expression2 ; <br /><br />　　<br />Expression1 应该总是产生一个布尔值。<br /><br />　　<br />Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。<br /><br />　　<br />断言在默认情况下是禁用的。要在编译时启用断言，需要使用 source 1.4 标记：<br /><br />　　<br />javac -source 1.4 Test.java<br /><br />　　<br />要在运行时启用断言，可使用 -enableassertions 或者 -ea 标记。<br /><br />　　<br />要在运行时选择禁用断言，可使用 -da 或者 -disableassertions 标记。<br /><br />　　<br />要系统类中启用断言，可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。<br /><br />　　<br />可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过，断言不应该用于验证传递给公有方法的参数，因为不管是否启用了断言，公有方法都必须检查其参数。不过，既可以在公有方法中，也可以在非公有方法中利用断言测试后置条件。另外，断言不应该以任何方式改变程序的状态。 <br /><br /><br />　　<br />第八，GC是什么? 为什么要有GC? (基础)。 <br /><br />　　<br />GC是垃圾收集器。Java 程序员不用担心内存管理，因为垃圾收集器会自动进行管理。要请求垃圾收集，可以调用下面的方法之一：<br /><br />　　<br />System.gc() <br /><br />　　<br />Runtime.getRuntime().gc() <br /><br /><br />　　<br />第九，String s = new String("xyz");创建了几个String Object? <br /><br />　　<br />两个对象，一个是"xyx",一个是指向"xyx"的引用对象s。<br /><br /><br />　　<br />第十，Math.round(11.5)等於多少? Math.round(-11.5)等於多少?<br /><br />　　　　<br />Math.round(11.5)返回（long）12，Math.round(-11.5)返回（long）-11;<br /><br /><br />　　<br />第十一，short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?<br /><br />　　<br />short s1 = 1; s1 = s1 + 1;有错，s1是short型，s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。<br /><br /><br />　　<br />第十二，sleep() 和 wait() 有什么区别? 搞线程的最爱<br /><br />　　<br />sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后，线程不一定立即恢复执行。这是因为在那个时刻，其它线程可能正在运行而且没有被调度为放弃执行，除非<br /><br />(a)"醒来"的线程具有更高的优先级。<br /><br />　　<br />(b)正在运行的线程因为其它原因而阻塞。<br /><br />　　<br />wait()是线程交互时，如果线程对一个同步对象x 发出一个wait()调用，该线程会暂停执行，被调对象进入等待状态，直到被唤醒或等待时间到。<br /><br /><br />　　<br />第十三，Java有没有goto?<br /><br />　　<br />Goto—java中的保留字，现在没有在java中使用。<br /><br /><br />　　<br />第十四，数组有没有length()这个方法? String有没有length()这个方法？<br /><br />　　<br />数组没有length()这个方法，有length的属性。<br /><br />　　<br />String有有length()这个方法。<br /><br /><br />　　<br />第十五，Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?<br /><br />　　<br />方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写 (Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。<br /><br /><br />　　<br />第十六，Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?<br /><br />　　<br />Set里的元素是不能重复的，那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。<br /><br />　　<br />equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖，为的是当两个分离的对象的内容和类型相配的话，返回真值。<br /><br /><br />　　<br />第十七，给我一个你最常见到的runtime exception。<br /><br />　　<br />ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, 　　ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException <br /><br /><br />　　<br />第十八，error和exception有什么区别?<br /><br />　　<br />error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。<br /><br />　　<br />exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况。<br /><br /><br />　　<br />第十九，List, Set, Map是否继承自Collection接口?<br /><br />　　<br />List，Set是<br /><br />　　<br />Map不是<br /><br /><br />　　<br />第二十，abstract class和interface有什么区别?<br /><br />　　<br />声明方法的存在而不去实现它的类被叫做抽象类（abstract class），它用于要创建一个体现某些基本行为的类，并为该类声明方法，但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量，其类型是一个抽象类，并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。<br /><br />　　<br />接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口。<br /><br /><br />　　<br />第二十一，abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized? <br /><br />　　<br />都不能<br /><br /><br />　　<br />第二十二，接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? <br /><br />　　<br />接口可以继承接口。抽象类可以实现(implements)接口，抽象类是否可继承实体类，但前提是实体类必须有明确的构造函数。<br /><br /><br />　 <br />第二十三，启动一个线程是用run()还是start()?<br /><br />　　<br />启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。<br /><br /><br />　　<br />第二十四，构造器Constructor是否可被override?<br /><br />　　<br />构造器Constructor不能被继承，因此不能重写Overriding，但可以被重载Overloading。<br /><br /><br />　　<br />第二十五，是否可以继承String类?<br /><br />　　<br />String类是final类故不可以继承。<br /><br /><br />　　<br />第二十六，当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法? <br /><br />　　<br />不能，一个对象的一个synchronized方法只能由一个线程访问。<br /><br /><br />　　<br />第二十七，try {}里有一个return语句，那么紧跟在这个try后的finally {}里的code会不会被执行，什么时候被执行，在return前还是后?<br /><br />　　<br />会执行，在return前执行。<br /><br /><br />　　<br />二十八，编程题: 用最有效率的方法算出2乘以8等於几?<br /><br />　　<br />有C背景的程序员特别喜欢问这种问题。 <br /><br /><br />　　<br />第二十九，两个对象值相同(x.equals(y) == true)，但却可有不同的hash code，这句话对不对? <br /><br />　 <br />不对，有相同的hash code。 <br /><br /><br />　　<br />第三十，当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递?<br /><br />　　<br />是值传递。Java 编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时，参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变，但对象的引用是永远不会改变的。 <br /><br /><br />　　<br />第三十一，swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上?<br /><br />　　<br />switch（expr1）中，expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。<br /><br /><br />　　<br />第三十二，编程题: 写一个Singleton出来。<br /><br />　　<br />Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。<br /><br />　 <br />一般Singleton模式通常有几种种形式: <br /><br />　　<br />第一种形式: 定义一个类，它的构造函数为private的，它有一个static的private的该类变量，在类初始化时实例话，通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。 <br /><br />　　<br />public class Singleton {<br /><br />　　<br />private Singleton(){} <br /><br />　　<br />//在自己内部定义自己一个实例，是不是很奇怪？ <br /><br />　　<br />//注意这是private 只供内部调用 <br /><br />　　<br />private static Singleton instance = new Singleton(); <br /><br />　　<br />//这里提供了一个供外部访问本class的静态方法，可以直接访问　　<br /><br />　　<br />public static Singleton getInstance() { <br /><br />　　<br />return instance; 　　 <br /><br />　　<br />} <br /><br />　　<br />} <br /><br /><br />　　<br />第二种形式: <br /><br />　　<br />public class Singleton { <br /><br />　　<br />private static Singleton instance = null; <br /><br />　　<br />public static synchronized Singleton getInstance() { <br /><br />　　<br />//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　 <br /><br />　　 　 　<br />　//使用时生成实例，提高了效率！ <br /><br />　　<br />if (instance==null) <br /><br />　　<br />instance＝new Singleton();<br /><br />　　<br />return instance; 　　} <br /><br />　　<br />} <br /><br />　　<br />其他形式: <br /><br />　　<br />定义一个类，它的构造函数为private的，所有方法为static的。 <br /><br />　　<br />一般认为第一种形式要更加安全些 <br /><br />　　<br />Hashtable和HashMap <br /><br />　　<br />Hashtable继承自Dictionary类，而HashMap是Java1.2引进的Map interface的一个实现<br /><br />　　<br />HashMap允许将null作为一个entry的key或者value，而Hashtable不允许 <br /><br />　　<br />还有就是，HashMap把Hashtable的contains方法去掉了，改成containsvalue和containsKey。因为contains方法容易让人引起误解。<br /><br />　　<br />最大的不同是，Hashtable的方法是Synchronize的，而HashMap不是，在 <br /><br />　　<br />多个线程访问Hashtable时，不需要自己为它的方法实现同步，而HashMap <br /><br />　　<br />就必须为之提供外同步。 <br /><br />　　<br />Hashtable和HashMap采用的hash/rehash算法都大概一样，所以性能不会有很大的差异。<br /></font>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-12 16:02 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/12/9753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]对String的深刻理解</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9706.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Tue, 11 Jul 2006 14:29:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9706.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9706.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9706.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9706.html</trackback:ping><description><![CDATA[
		<font face="Arial" color="#000080" size="2">近期到CSDN论坛看看一些网友贴的面试题，其中关于String的问题常常被提及。我一直以为自己很清楚这个东西了，其实深究起来，发现自己并不那么清楚，会犯一些错误；同时也产生了一些联想。小结一下。<br /><br />1、"abc"与new String("abc");<br />    经常会问到的面试题：String s = new String("abc");创建了几个String Object?【如这里创建了多少对象? 和一道小小的面试题 】<br /><br />    这个问题比较简单，涉及的知识点包括：<br /><br />引用变量与对象的区别； <br />字符串文字"abc"是一个String对象； <br />文字池[pool of literal strings]和堆[heap]中的字符串对象。<br />    一、引用变量与对象：除了一些早期的Java书籍和现在的垃圾书籍，人们都可以从中比较清楚地学习到两者的区别。A aa;语句声明一个类A的引用变量aa[我常常称之为句柄]，而对象一般通过new创建。所以题目中s仅仅是一个引用变量，它不是对象。[ref 句柄、引用与对象]<br /><br />    二、Java中所有的字符串文字[字符串常量]都是一个String的对象。有人[特别是C程序员]在一些场合喜欢把字符串"当作/看成"字符数组，这也没有办法，因为字符串与字符数组存在一些内在的联系。事实上，它与字符数组是两种完全不同的对象。<br /><br />        System.out.println("Hello".length());<br />        char[] cc={'H','i'};<br />        System.out.println(cc.length);<br /><br />    三、字符串对象的创建:由于字符串对象的大量使用[它是一个对象，一般而言对象总是在heap分配内存]，Java中为了节省内存空间和运行时间[如比较字符串时，==比equals()快]，在编译阶段就把所有的字符串文字放到一个文字池[pool of literal strings]中，而运行时文字池成为常量池的一部分。文字池的好处，就是该池中所有相同的字符串常量被合并，只占用一个空间。我们知道，对两个引用变量，使用==判断它们的值[引用]是否相等，即指向同一个对象：<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">String s1 = "abc" ;<br />String s2 = "abc" ;<br />if( s1 == s2 ) <br />    System.out.println("s1,s2 refer to the same object");<br />else     System.out.println("trouble");</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">    这里的输出显示，两个字符串文字保存为一个对象。就是说，上面的代码只在pool中创建了一个String对象。<br /><br />    现在看String s = new String("abc");语句，这里"abc"本身就是pool中的一个对象，而在运行时执行new String()时，将pool中的对象复制一份放到heap中，并且把heap中的这个对象的引用交给s持有。ok，这条语句就创建了2个String对象。<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">String s1 = new String("abc") ;<br />String s2 = new String("abc") ;<br />if( s1 == s2 ){ //不会执行的语句}</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">    这时用==判断就可知，虽然两个对象的"内容"相同[equals()判断]，但两个引用变量所持有的引用不同，<br /><br />    BTW：上面的代码创建了几个String Object? [三个，pool中一个，heap中2个。]<br />    [Java2 认证考试学习指南 (第4版)( 英文版)p197-199有图解。]<br /><br /><br />2、字符串的+运算和字符串转换<br />    字符串转换和串接是很基础的内容，因此我以为这个问题简直就是送分题。事实上，我自己就答错了。<br /><br />String str = new String("jf"); // jf是接分<br />str = 1+2+str+3+4;<br />一共创建了多少String的对象？[我开始的答案：5个。jf、new、3jf、3jf3、3jf34]<br /><br />    首先看JLS的有关论述：<br /><br />    一、字符串转换的环境[JLS 5.4 String Conversion]<br /><br />    字符串转换环境仅仅指使用双元的+运算符的情况，其中一个操作数是一个String对象。在这一特定情形下，另一操作数转换成String，表达式的结果是这两个String的串接。<br /><br />    二、串接运算符[JLS 15.18.1 String Concatenation Operator + ]<br /><br />    如果一个操作数/表达式是String类型，则另一个操作数在运行时转换成一个String对象，并两者串接。此时，任何类型都可以转换成String。[这里，我漏掉了"3"和"4"]<br /><br />如果是基本数据类型，则如同首先转换成其包装类对象，如int x视为转换成Integer(x)。 <br />现在就全部统一到引用类型向String的转换了。这种转换如同[as if]调用该对象的无参数toString方法。[如果是null则转换成"null"]。因为toString方法在Object中定义，故所有的类都有该方法，而且Boolean, Character, Integer, Long, Float, Double, and String改写了该方法。 <br />关于+是串接还是加法，由操作数决定。1+2+str+3+4 就很容易知道是"3jf34"。[BTW :在JLS的15.18.1.3中举的一个jocular little example，真的很无趣。]<br />    下面的例子测试了改写toString方法的情况.。<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">class A{<br />    int i = 10;<br />    public static void main(String []args){<br />        String str = new String("jf");<br />        str += new A();<br />        System.out.print(str);<br />    }<br /><br />    public String toString(){<br />        return " a.i ="+i+"\n";<br />    }<br />}</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">三、字符串转换的优化<br /><br />按照上述说法，str = 1+2+str+3+4;语句似乎应该就应该生成5个String对象：<br /><br />1+2 ＝3，then 3→Integer(3)→"3" in pool? [假设如此] <br />"3"+str(in heap) = "3jf"     (in heap) <br />"3jf" +3 ,first 3→Integer(3)→"3" in pool? [则不创建] then "3jf3" <br />"3jf3"+4 create "4"  in pool <br />then "3jf34"<br /><br />    这里我并不清楚3、4转换成字符串后是否在池中，所以上述结果仍然是猜测。<br /><br />    为了减少创建中间过渡性的字符串对象，提高反复进行串接运算时的性能，a Java compiler可以使用StringBuffer或者类似的技术，或者把转换与串接合并成一步。例如：对于 a + b + c ，Java编译器就可以将它视为[as if]<br /><br />    new StringBuffer().append(a).append(b).append(c).toString();<br /><br />    注意，对于基本类型和引用类型，在append(a)过程中仍然要先将参数转换，从这个观点看，str = 1+2+str+3+4;创建的字符串可能是"3"、"4"和"3jf34"[以及一个StringBuffer对象]。<br /><br />    现在我仍然不知道怎么回答str = 1+2+str+3+4;创建了多少String的对象，。或许，这个问题不需要过于研究，至少SCJP不会考它。<br /><br />3、这又不同：str = "3"+"jf"+"3"+"4";<br />    如果是一个完全由字符串文字组成的表达式，则在编译时，已经被优化而不会在运行时创建中间字符串。测试代码如下：<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">String str1 ="3jf34";<br />        String str2 ="3"+"jf"+"3"+"4"; <br />        if(str1 == str2) {<br />            System.out.println("str1 == str2");<br />        }else {<br />            System.out.println("think again");<br />        }<br />        if(str2.equals(str1))<br />            System.out.println("yet str2.equals(str1)");</font>
		</pre>
		<br />
		<br />
		<font face="Arial" color="#000080" size="2">    可见，str1与str2指向同一个对象，这个对象在pool中。所有遵循Java Language Spec的编译器都必须在编译时对constant expressions 进行简化。JLS规定：Strings computed by constant expressions (&amp;yacute;15.28) are computed at compile time and then treated as if they were literals. <br /><br />    对于String str2 ="3"+"jf"+"3"+"4";我们说仅仅创建一个对象。注意，“创建多少对象”的讨论是说运行时创建多少对象。<br /><br />    BTW：编译时优化<br /><br /></font>
		<pre class="overflow">
				<font face="Arial" color="#000080" size="2">    String x = "aaa " + "bbb ";<br />    if (false) {<br />        x = x + "ccc ";<br />    }<br />    x +=  "ddd ";<br /><br />    等价于：<br /><br />    String x = "aaa bbb ";<br />    x = x + "ddd ";</font>
		</pre>
		<font face="Arial">
				<font color="#000080">
						<font size="2">
								<font style="BACKGROUND-COLOR: #ffffff">
										<font color="#ff0000">//这个地方我自己进行了编译，不过和他的结论不一样，好像当用x+="ddd"的时候和直接的x="aaa"+"bbb"+"ddd" 不同，但是具体为什么我也不清楚，正在研究中。。。</font>
										<br />
										<br />
								</font>4、不变类<br />    String对象是不可改变的(immutable)。有人对str = 1+2+str+3+4;语句提出疑问,怎么str的内容可以改变？其实仍然是因为不清楚：引用变量与对象的区别。str仅仅是引用变量，它的值——它持有的引用可以改变。你不停地创建新对象，我就不断地改变指向。[参考TIJ的Read-only classes。]<br /><br />    不变类的关键是，对于对象的所有操作都不可能改变原来的对象[只要需要，就返回一个改变了的新对象]。这就保证了对象不可改变。为什么要将一个类设计成不变类？有一个OOD设计的原则：Law of Demeter。其广义解读是：<br /><br />    使用不变类。只要有可能，类应当设计为不变类。<br /></font>
				</font>
		</font>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-11 22:29 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/11/9706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]abstract class和interface相关整理</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9703.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Tue, 11 Jul 2006 11:53:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9703.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9703.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9703.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9703.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9703.html</trackback:ping><description><![CDATA[
		<p align="left">
				<font face="Arial" color="#000080">abstract class和interface在Java语言中都是用来进行抽象类定义的<br /><br />Interface ,给外界的接口,按照规定办事；<br />Abstract  ,内部继承关系；<br /><br />interface 就是一组操作的集合,它定义了一个行为集但不作任何具体的实现,这样的话,具体的操作 都可以放在实现类中去,<br />          体现设计与实现分离的设计思想。<br /><br />在面向对象的概念中，所有的对象都是通过类来描绘，如果一个类中没有包含足够的信息来描绘一个具体的对象，这样的类就是抽象类<br />抽象概念在问题领域没有对应的具体概念，所以用以表征抽象概念的抽象类是不能够实例化的。<br /><br />=====================================================================================================================<br />使用abstract class的方式定义Demo抽象类的方式如下：<br /><br /></font>
		</p>
		<pre class="overflow">
				<font face="Arial" color="#000080">abstract class Demo {<br />abstract void method1();<br />abstract void method2();<br />…<br />}</font>
		</pre>
		<p align="left">
				<br />
				<br />
				<font face="Arial" color="#000080">使用interface的方式定义Demo抽象类的方式如下：<br /><br /></font>
		</p>
		<pre class="overflow">
				<font face="Arial" color="#000080">interface Demo {<br />void method1();<br />void method2();<br />…<br />}</font>
		</pre>
		<p align="left">
				<br />
				<br />
				<font face="Arial" color="#000080">====================================================================================================================<br />从编程层面看abstract class和interface<br /><br />abstract class在Java语言中表示的是一种继承关系，一个类只能使用一次继承关系<br />一个类却可以实现多个interface<br /><br />在abstract class的定义中，我们可以赋予方法的默认行为<br />在interface的定义中，方法却不能拥有默认行为<br /><br />======================================================================================================================<br />例如要设计一个形状类MShape，从此类可以派生 方形、圆形、三角形等子类。我们就可以将MShape这个父类设计为abstract类。<br /><br />比如，子类都有 color 属性，因此可以把 color 这个数据成员，以及给 color 赋值的method均设计在父类中，<br />这样就不用在每个子类中设计相同的代码来处理 color 这个属性。<br />而如果想计算几何形状的面积，由于各个几何形状的面积计算方式都不相同，所以把计算面积的method的处理放在父类中就不合适，<br />但由于每个几何形状都需要用到这个method，因此可以在父类中只声明计算面积的method "area()"，而把具体的处理放在子类中定义。<br />即把area()设计为抽象类。<br /><br />以下是程序代码：<br />//abstract类 MShape       <br /></font>
		</p>
		<pre class="overflow">
				<font face="Arial" color="#000080">abstract class MShape<br />{<br />        protected String color;   //数据成员<br />        public void setColor(String mcolor)   //一般方法，定义了具体的处理 <br />        {<br />           color=mcolor;<br />        }<br />        abstract void area();   //抽象方法，没有定义具体的处理<br />}</font>
		</pre>
		<p align="left">
				<br />
				<br />
				<font face="Arial" color="#000080">//方形类<br /></font>
		</p>
		<pre class="overflow">
				<font face="Arial" color="#000080">class RectShape extends MShape<br />{       <br />        int width,height,rectarea;    <br />        public RectShape(int w,int h)<br />        {  <br />                 width=w;<br />                 height=h;        <br />        }<br />        public void area()  //计算面积<br />        {          <br />          rectarea=width*height;<br />        }<br />}</font>
		</pre>
		<p align="left">
				<br />
				<br />
				<font face="Arial" color="#000080">//使用<br /></font>
		</p>
		<pre class="overflow">
				<font face="Arial" color="#000080">public class myapp<br />{<br />        public static void main(String args[])<br />        {<br />          RectShape rect=new RectShape(3,6);<br />          rect.setColor("Red");<br />          rect.area();<br />          System.out.print("color="+rect.color+", area="+rect.rectarea);<br />        }<br />}</font>
		</pre>
		<p align="left">
				<br />
				<br />
				<font face="Arial" color="#000080">由此可见，在abstract中不仅可以定义一般的方法（即可以进行具体处理的方法），还可以象interface一样定义抽象方法。<br />而在interface中只能定义抽象方法。</font>
		</p>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9703.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-11 19:53 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/11/9703.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]JAVA操作数据库方式与设计模式应用</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9696.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Tue, 11 Jul 2006 11:10:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9696.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9696.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9696.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9696.html</trackback:ping><description><![CDATA[
		<font face="Arial" color="#000080" size="2">1.   在业务层使用JDBC直接操作数据库－最简单，最直接的操作<br /><br />1）数据库url,username,password写死在代码中<br />    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br />    String url="jdbc:oracle:thin:@localhost:1521:orcl"; <br />    String user="scott"; <br />    String password="tiger"; <br />    Connection conn= DriverManager.getConnection(url,user,password);  <br />    Statement stmt=conn.createStatement(<br />ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br />    String sql="select * from test"; <br />    ResultSet rs=stmt.executeQuery(sql); <br /><br />2）采用Facade和Command模式，使用DBUtil类封装JDBC操作；<br />      数据库url,username,password可以放在配置文件中（如xml,properties,ini等）。<br />      这种方法在小程序中应用较多。<br /><br />2.DAO(Data Accessor Object)模式－松耦合的开始<br />DAO = data + accessor + domain object<br /><br />例如User类－domain object (javabean)<br />UserDAO类－accessor ，提供的方法getUser(int id)，save(User user)内包含了JDBC操作<br />在业务逻辑中使用这两个类来完成数据操作。<br /><br />使用Factory模式可以方便不同数据库连接之间的移植。<br /><br />3.数据库资源管理模式<br />3.1 数据库连接池技术<br />资源重用，避免频繁创建，释放连接引起大大量性能开销；<br />更快的系统响应速度；<br /><br />通过实现JDBC的部分资源对象接口( Connection, Statement, ResultSet )，可以使用Decorator设计模式分别产生三种逻辑资源对象: PooledConnection, PooledStatement和 PooledResultSet。<br /><br /><br />一个最简单地数据库连接池实现：<br />public class ConnectionPool {<br /><br />       private static Vector pools;<br />       private final int POOL_MAXSIZE = 25;<br />       /**<br />        * 获取数据库连接<br />        * 如果当前池中有可用连接，则将池中最后一个返回；若没有，则创建一个新的返回<br />        */<br />       public synchronized Connection getConnection() {<br />              Connection conn = null;<br />              if (pools == null) {<br />                     pools = new Vector();<br />              }<br /><br />              if (pools.isEmpty()) {<br />                     conn = createConnection();<br />              } else {<br />                     int last_idx = pools.size() - 1;<br />                     conn = (Connection) pools.get(last_idx);<br />                     pools.remove(last_idx);<br />              }<br /><br />              return conn;<br />       }<br /><br />       /**<br />        * 将使用完毕的数据库连接放回池中<br />        * 若池中连接已经超过阈值，则关闭该连接；否则放回池中下次再使用<br />        */<br />       public synchronized void releaseConnection(Connection conn) {<br />              if (pools.size() &gt;= POOL_MAXSIZE)<br />                     try {<br />                            conn.close();<br />                     } catch (SQLException e) {<br />                            // TODO自动生成 catch 块<br />                            e.printStackTrace();<br />                     } else<br />                     pools.add(conn);<br />       }<br /><br />       public static Connection createConnection() {<br />              Connection conn = null;<br />              try {<br />                     Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();<br />                     String url = "jdbc:oracle:thin:@localhost:1521:orcl";<br />                     String user = "scott";<br />                     String password = "tiger";<br />                     conn = DriverManager.getConnection(url, user, password);<br />              } catch (InstantiationException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (IllegalAccessException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (ClassNotFoundException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (SQLException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              }<br />              return conn;<br />       }<br />}<br /><br />注意：利用getConnection()方法得到的Connection，程序员很习惯地调用conn.close()方法关闭了数据库连接，那么上述的数据库连接机制便形同虚设。在调用conn.close()方法方法时如何调用releaseConnection()方法？这是关键。这里，我们使用Proxy模式和java反射机制。 <br /><br />public synchronized Connection getConnection() {<br />              Connection conn = null;<br />              if (pools == null) {<br />                     pools = new Vector();<br />              }<br /><br />              if (pools.isEmpty()) {<br />                     conn = createConnection();<br />              } else {<br />                     int last_idx = pools.size() - 1;<br />                     conn = (Connection) pools.get(last_idx);<br />                     pools.remove(last_idx);<br />              }<br />        <br />        ConnectionHandler handler=new ConnectionHandler(this);<br />              return handler.bind(con);<br />       }<br /><br />public class ConnectionHandler implements InvocationHandler {<br />     private Connection conn;<br />     private ConnectionPool pool;<br />     <br />     public ConnectionHandler(ConnectionPool pool){<br />            this.pool=pool;<br />     }<br />     <br />     /**<br />      * 将动态代理绑定到指定Connection<br />      * @param conn<br />      * @return<br />      */<br />     public Connection bind(Connection conn){<br />            this.conn=conn;<br />Connection proxyConn=(Connection)Proxy.newProxyInstance(<br />conn.getClass().getClassLoader(), conn.getClass().getInterfaces(),this);<br />          return proxyConn;<br />     }<br />     <br />       /* （非 Javadoc）<br />        * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])<br />        */<br />       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {<br />              // TODO自动生成方法存根<br />              Object obj=null;<br />              if("close".equals(method.getName())){<br />                     this.pool.releaseConnection(this.conn);<br />              }<br />              else{<br />                     obj=method.invoke(this.conn, args);<br />              }<br />              <br />              return obj;<br />       }<br />}<br /><br />      在实际项目中，并不需要你来从头开始来设计数据库连接池机制，现在成熟的开源项目，如C3P0,dbcp,Proxool等提供了良好的实现。一般推荐使用Apache dbcp，基本使用实例：<br />DataSource ds = null;<br />   try{<br />     Context initCtx = new InitialContext();<br />     Context envCtx = (Context) initCtx.lookup("java:comp/env");<br />     ds = (DataSource)envCtx.lookup("jdbc/myoracle");<br />        if(ds!=null){<br />                out.println("Connection is OK!");<br />                Connection cn=ds.getConnection();<br />                if(cn!=null){<br />                        out.println("cn is Ok!");<br />                Statement stmt = cn.createStatement();<br />                 ResultSet rst = stmt.executeQuery("select * from BOOK");<br />                out.println("&lt;p&gt;rst is Ok!" + rst.next());<br />                while(rst.next()){<br />                        out.println("&lt;P&gt;BOOK_CODE:" + rst.getString(1));<br />                  }<br />                        cn.close();<br />                }else{<br />                        out.println("rst Fail!");<br />                }<br />        }<br />        else <br />                out.println("Fail!");<br />           }catch(Exception ne){ out.println(ne);<br />         }<br /><br /><br />3.2 Statement Pool<br />普通预编译代码：<br />String strSQL=”select name from items where id=?”;<br />PreparedStatement ps=conn.prepareStatement(strSQL);<br />ps.setString(1, “2”);<br />ResultSet rs=ps.executeQuery();<br /><br />但是PreparedStatement 是与特定的Connection关联的，一旦Connection关闭，则相关的PreparedStatement 也会关闭。<br />为了创建PreparedStatement 缓冲池，可以在invoke方法中通过sql语句判断池中还有没有可用实例。<br /><br />4. 持久层设计与O/R mapping 技术<br />1） Hernate：适合对新产品的开发，进行封闭化的设计 <br />Hibernate 2003年被Jboss接管，通过把java pojo对象映射到数据库的table中，采用了xml/javareflection技术等。3.0提供了对存储过程和手写sql的支持，本身提供了hql语言。<br />开发所需要的文件：<br />hibernate配置文件： hibernate.cfg.xml 或 hibernate.properties<br />hibernate 映射文件： a.hbm.xml<br />pojo类源文件： a.java　　<br /><br />导出表与表之间的关系：<br />a. 从java对象到hbm文件：xdoclet <br />b. 从hbm文件到java对象：hibernate extension <br />c. 从数据库到hbm文件：middlegen <br />d. 从hbm文件到数据库：SchemaExport<br /><br />2）Iatis ：适合对遗留系统的改造和对既有数据库的复用，有很强的灵活性 3） Apache OJB：优势在于对标准的全面支持 4）EJB：适合集群服务器，其性能也不象某些人所诟病的那么差劲 5） JDO (java data object) <br />设置一个Properties对象，从而获取一个JDO的PersistenceManagerFactory（相当于JDBC连接池中的DataSource），进而获得一个PersistenceManager对象（相当于JDBC中的Connection对象），之后，你可以用这个PersistenceManager对象来增加、更新、删除、查询对象。<br />JDOQL是JDO的查询语言；它有点象SQL，但却是依照Java的语法的。<br /><br />5. 基于开源框架的Struts+Spring+Hibernate实现方案<br />示例：这是一个3层架构的web 程序，通过一个Action 来调用业务代理，再通过它来回调 DAO类。下面的流程图表示了MyUsers是如何工作的。数字表明了流程的先后顺序，从web层(UserAction)到中间层(UserManager)，再到数据层(UserDAO)，然后返回。<br />Spring是AOP, UserManager和UserDAO都是接口.<br />1)       web层(UserAction) ：调用中间层的接口方法，将UserManager作为属性注入。<br />             采用流行的Struts框架，虽然有很多人不屑一顾，但是这项技术在业界用的比较普遍，能满足基本的功能，可以减少培训学习成本。<br />2)       中间层(UserManager)：将UserDAO作为属性注入，其实现主要是调用数据层接口的一些方法；它处于事务控制中。<br />            采用Spring框架实现，IOC与AOP是它的代名词，功能齐全，非常棒的一个架构。<br />3)       数据层(UserDAO)：实现类继承HibernateDaoSupport类，在该类中可以调用getHibernateTemplate()的一些方法执行具体的数据操作。<br />            采用Hibernate做O/R mapping，从种种迹象可以看出，Hibernate就是EJB3.0的beta版。</font>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-11 19:10 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/11/9696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]初学Java注意什么？</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9691.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Tue, 11 Jul 2006 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9691.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9691.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/11/9691.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9691.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9691.html</trackback:ping><description><![CDATA[Java总有它的千般好处使你选择它，但这些随便翻翻书或在网上逛一圈就能找到答案。在本文中，笔者把自己学习Java的一些切身体会和过程写出来，供初学者做个参考。 <br /><br />我在学习Java的过程中主要围绕以下几个方面来学习： <br /><br />1．时刻提醒自己Java是一种OOP语言工具，而不仅仅是编码，只有这样才能总体把握和运用Java。 <br /><br />2．在学习的过程中，最好能够了解Java的底层机制，而不是仅仅停留在表层，不是抄书上的例子运行出结果就可以。要注意，即便对一个简单的例子也要有耐心去琢磨、调试、改动。 <br /><br />3．在学习的过程中一定要动手做、写代码，而不是抱一本书看看就行。很多东西和体会必须自己动手才能真正属于自己，最好能参与一些实际的项目。 <br /><br />4．在学到一定阶段后，你开始希望用学过的东西做些什么。这时的你应该开始学习一些更多、更复杂的知识，比如J2EE平台的构建、EJB的开发等。对于这一部分，我建议最好找一本较薄的书先了解一个大概，心里有个总体的认识，对更多的技术术语做个初步掌握。我认为这个阶段看看《J2EE技术实践》很不错，它可以让你了解J2EE包含的各种技术和框架，同时提供很多实际的例子来加深对J2EE的整体了解。 <br /><br />学习Java的兴趣和决心起了很关键的作用。在有了上述基础后，我便开始一步一步地学习Java。 <br /><br /><br />Java环境的搭建<br /><br /><br />要运行Java程序，必须安装JDK。JDK是整个Java的核心，其中包括了Java编译器、JVM、大量的Java工具以及Java基础API。 <br /><br />可以从http://Java.sun.com下载JDK，有1.4版本和1.31版本。我的学习环境中首先，采用的是1.31版本。 <br /><br />解压安装。然后，进行环境设置。 <br /><br />1.对于Windows平台要进行以下设置： <br /><br />set PATH=YOUR_INSTALL_ DIR\bin; C:\Windows;C:\Windows\Command<br />set classpath=. ;YOUR_INSTALL_DIR\lib\tools.jar<br /><br /><br /><br />2.对于Linux平台要编辑/etc/profile文件： <br /><br />JAVA_HOME=your_install_dir/JDK/j2sdk<br />CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/td.jar:$JAVA_HOME/jr  <br />-e/lib/rt.jar:.<br />PATH=$PATH:$JAVA_HOME/bin<br />export PATH PS1 USER LOGNAME MAIL HOSTNAME HISTSIZE HISTFILESIZE   <br />INPUTRC JAVA_HOME CLASSPATH RESIN_HOME<br /><br /><br /><br />最后，在终端上输入Java看能不能找到这个命令，如果能找到安装就成功了。 <br /><br />下面介绍一下JDK的几个重要的命令： <br /><br />◆Java执行工具，是启动JVM（虚拟机）并执行class（BYTE CODE）文件的命令； <br /><br />◆javac 编译器，由.java文件生成.class文件； <br /><br />◆jar Java压缩打包工具； <br /><br />◆Javadoc 文档生成器。 <br /><br />最后就是JDK Documentation，这是JDK的联机帮助文档，是最有用和最重要的学习参考文档，应该多看。 <br /><br /><br />开始写自己的代码<br /><br /><br />现在环境有了，应该写个简单的代码进行测试了。还是从经典的“hello word”开始。 <br /><br />1． 先用编辑器写一代码（我用的是Linux的vi）： <br /><br />[stone@coremsg work]$ vi Hello.Java<br />  public class Hello{<br />        public static void main(String []argc){<br />                System.out.println("Hello Word!");<br />        }<br />  }<br /><br /><br /><br />2． 编译： <br /><br />[stone@coremsg work]$ Javac Hello.Java<br /><br /><br /><br />3． 执行： <br /><br />[stone@coremsg work]$ Java Hello<br />     Hello Word!<br /><br /><br /><br />成功了！这就是我的第一个Java程序。从那时起我知道已开始走进Java的世界，接下来就靠自己的努力了。在这个过程中，笔者认为有几点需要注意。 <br /><br />学习一门新的语言，参考书是离不开的。我的建议是开始最好找一本篇幅较短的入门书来学习那些最简单、最基本的东西，包括学习Java语法等。同时，对一个最简单的程序也应该多去调试，多想想如果改动一下会出现什么结果？为什么必须那样写？多去想想这些问题然后去操作，会让你有更多的收获。这样反复地思考是很有用的。此外，在这一阶段还应该多看JDK的联机帮助，尽量多地掌握JDK提供的Java基本类库API。 <br /><br />在有一定基础、能够写一些简单的程序后，可以开始看《Thinking in Java》这本书。它比较完整地介绍了Java的语法、面向对象的特性、核心类库等。通过这一层次的学习能够加深对Java的理解和底层原理的运用，同时又可以完整地了解Java的整个体系。在这一阶段，应该重点学习Java的面向对象编程语言的特性，比如继承、构造器、抽象类、接口、方法的多态、重载、覆盖、Java的异常处理机制等，要对上述概念有非常清楚的了解。这样做的目的，是要让自己把这些技术应用到实践中进行合理的程序设计（比如，你会考虑一个类是用抽象还是接口来设计等）。这就要求必须在大量的实践中去应用和学习。这也是当初很多朋友给我的建议。 <br /><br /><br />学习更多<br /><br /><br />如果要用Java来完成各种功能更强大的任务，那么就要学习语言以外的更多的东西。 <br /><br />1.Java Web编程 <br /><br />对于Java Web 编程来说，应该而且必须熟悉和掌握HTTP协议，可以参考 Stevens的《TCP/IP 详解》第三卷。Java Servlet技术提供了生成动态Web页面内容的能力，这在你的Java项目中是最基本的功能之一，所以必须学习。通过这一阶段的学习应该掌握Servlet/JSP的Web编程。 <br /><br />2. J2EE的学习 <br /><br />J2EE包含的技术太多了。如果你想坐在桌子旁边抱着一大堆书来学习的话，效果不大的。我建议在开始这一阶段的学习的时候，可以按以下步骤来做，总的思想是“总体把握，各个击破”。 <br /><br />◆ 了解J2EE中的技术术语的含义。 <br /><br />我的感觉是J2EE标准中涉及到的各种技术很多，如果一开始就一个一个去学习的话是不现实的，也是没效果的。我的建议是，先对其中的技术有个大概的了解，比如EJB、JavaIDL、JTA等。可能你不知道怎么去写一个EJB，但是要知道什么是EJB、它能做什么，当有了这样的概念后，再去有目的地学习它就会快很多。我还要再重复一句——必须要在实践中动手去做才行。 <br /><br />◆ 了解J2EE中的设计模式，这样能帮助你对J2EE做个整体把握。 <br /><br />MVC开发模式被证明是有效的处理方法之一。它可以分离数据访问和数据表现。你可以开发一个有伸缩性的、便于扩展的控制器，来维护整个流程。通过这一层次的学习，当你面对一个项目的时候，应该首先把握它的总体架构的设计，以及决定采用J2EE标准中的哪些技术。 <br /><br />◆ 了解一些J2EE平台的典型案列，加深对这一技术的概念和理解。 <br /><br />平时可以多留意这方面，熟悉一些典型案例，分析它为什么要采用那个时间？那样做能达到什么样的目的？然后联系到自己身边的项目是否可以作为参考。 <br /><br />◆ 学习J2EE下的各种技术。 <br /><br />在有了前几阶段的学习后，可以自己搭建一个J2EE平台开始具体学习每一种技术。你可以参与公司相关项目进行学习，也可以自己搭建一个平台进行学习。这时候应该找点相关的书来一步一步学习，没有捷径可走。如果你不满足于这些，那么还应该更深入地学习UML、设计模式等方面的东西<img src ="http://www.cppblog.com/yunduan5158/aggbug/9691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-11 17:00 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/11/9691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]利用XMLBean轻轻松松读写XML</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9659.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Mon, 10 Jul 2006 12:20:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9659.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9659.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9659.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9659.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9659.html</trackback:ping><description><![CDATA[　<b>一、关于XML解析</b><br />　　<br />　　XML在Java应用程序里变得越来越重要, 广泛应用于数据存储和交换. 比如我们常见的配置文件,都是以XML方式存储的. XML还应用于Java Message Service和Web Services等技术作为数据交换.<br />　　<br />　　因此,正确读写XML文档是XML应用的基础.<br />　　<br />　　Java提供了SAX和DOM两种方式用于解析XML,但即便如此,要读写一个稍微复杂的XML,也不是一件容易的事.<br />　　<br />　　<b>二、XMLBean简介</b><br />　　<br />　　Hibernate已经成为目前流行的面向Java环境的对象/关系数据库映射工具.<br />　　<br />　　在Hibernate等对象/关系数据库映射工具出现之前,对数据库的操作是通过JDBC来实现的,对数据库的任何操作,开发人员都要自己写SQL语句来实现. 对象/关系数据库映射工具出现后,对数据库的操作转成对JavaBean的操作,极大方便了数据库开发. 所以如果有一个类似的工具能够实现将对XML的读写转成对JavaBean的操作,将会简化XML的读写,即使对XML不熟悉的开发人员也能方便地读写XML. 这个工具就是XMLBean.<br />　　<br />　　<b>三、准备XMLBean和XML文档</b><br />　　<br />　　XMLBean是Apache的一个开源项目,可以从http://www.apache.org下载,最新的版本是2.0. 解压后目录如下:<br />　　xmlbean2.0.0<br />　　+---bin<br />　　+---docs<br />　　+---lib<br />　　+---samples<br />　　+---schemas<br />　　<br />　　另外还要准备一个XML文档(customers.xml),在本文的例子里,我们将对这个文档进行读写操作. 文档源码如下:<br />　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;Customers&gt;<br />　　&lt;customer&gt;<br />　　&lt;id&gt;1&lt;/id&gt;<br />　　&lt;gender&gt;female&lt;/gender&gt;<br />　　&lt;firstname&gt;Jessica&lt;/firstname&gt;<br />　　&lt;lastname&gt;Lim&lt;/lastname&gt;<br />　　&lt;phoneNumber&gt;1234567&lt;/phoneNumber&gt;<br />　　&lt;address&gt;<br />　　&lt;primaryAddress&gt;<br />　　&lt;postalCode&gt;350106&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;#25-1&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;SHINSAYAMA 2-CHOME&lt;/<br />　　addressLine2&gt;<br />　　&lt;/primaryAddress&gt;<br />　　&lt;billingAddress&gt;<br />　　&lt;receiver&gt;Ms Danielle&lt;/receiver&gt;<br />　　&lt;postalCode&gt;350107&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;#167&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;NORTH TOWER HARBOUR CITY&lt;/addressLine2&gt;<br />　　&lt;/billingAddress&gt;<br />　　&lt;/address&gt;<br />　　&lt;/customer&gt;<br />　　&lt;customer&gt;<br />　　&lt;id&gt;2&lt;/id&gt;<br />　　&lt;gender&gt;male&lt;/gender&gt;<br />　　&lt;firstname&gt;David&lt;/firstname&gt;<br />　　&lt;lastname&gt;Bill&lt;/lastname&gt;<br />　　&lt;phoneNumber&gt;808182&lt;/phoneNumber&gt;<br />　　&lt;address&gt;<br />　　&lt;primaryAddress&gt;<br />　　&lt;postalCode&gt;319087&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;1033 WS St.&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;Tima Road&lt;/addressLine2&gt;<br />　　&lt;/primaryAddress&gt;<br />　　&lt;billingAddress&gt;<br />　　&lt;receiver&gt;Mr William&lt;/receiver&gt;<br />　　&lt;postalCode&gt;672993&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;1033 WS St.&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;Tima Road&lt;/addressLine2&gt;<br />　　&lt;/billingAddress&gt;<br />　　&lt;/address&gt;<br />　　&lt;/customer&gt;&lt;/Customers&gt;<br />　　<br />　　这是一个客户的数据模型,每个客户都有客户编号(ID),姓名,性别(gender),电话号码(phoneNumber)和地址,其中地址有两个: 首要地址(PrimaryAddress)和帐单地址(BillingAddress),每个地址有邮编,地址1,和地址2组成.其中帐单地址还有收件人(receiver).<br />　　<br />　　此外,还要准备一个配置文件(文件名customer.xsdconfig),这个文件的作用我后面会讲,它的内容如下:<br />　　&lt;xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config"&gt;<br />　　&lt;xb:namespace&gt;<br />　　&lt;xb:package&gt;sample.xmlbean&lt;/xb:package&gt;<br />　　&lt;/xb:namespace&gt;&lt;/xb:config&gt;<br />　　<br />　　<b>四、XMLBean使用步骤</b><br />　　<br />　　和其他面向Java环境的对象/关系数据库映射工具的使用步骤一样,在正式使用XMLBean前,我们要作两个准备.<br />　　<br />　　1. 生成XML Schema文件<br />　　<br />　　什么是XML Schema文件? 正常情况下,每个XML文件都有一个Schema文件,XML Schema文件是一个XML的约束文件,它定义了XML文件的结构和元素.以及对元素和结构的约束. 通俗地讲,如果说XML文件是数据库里的记录,那么Schema就是表结构定义.<br />　　<br />　　为什么需要这个文件? XMLBean需要通过这个文件知道一个XML文件的结构以及约束,比如数据类型等. 利用这个Schema文件,XMLBean将会产生一系列相关的Java Classes来实现对XML的操作. 而作为开发人员,则是利用XMLBean产生的Java Classes来完成对XML的操作而不需要SAX或DOM.<br />　　<br />　　怎样产生这个Schema文件呢? 如果对于熟悉XML的开发人员,可以自己来写这个Schema文件,对于不熟悉XML的开发人员,可以通过一些工具来完成.<br />　　<br />　　比较有名的如XMLSPY和Stylus Studio都可以通过XML文件来生成Schema文件. 加入我们已经生成这个Schema文件(customer.xsd):<br />　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />　　&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"<br />　　elementFormDefault="qualified"&gt;<br />　　&lt;xs:element name="Customers"&gt;<br />　　&lt;xs:complexType&gt;<br />　　&lt;xs:sequence&gt;<br />　　&lt;xs:element maxOccurs="unbounded" name="customer"<br />　　type="customerType"/&gt;<br />　　&lt;/xs:sequence&gt;<br />　　&lt;/xs:complexType&gt;<br />　　&lt;/xs:element&gt;<br />　　&lt;xs:complexType name="customerType"&gt;<br />　　&lt;xs:sequence&gt;<br />　　&lt;xs:element name="id" type="xs:int"/&gt;<br />　　&lt;xs:element name="gender" type="xs:string"/&gt;<br />　　&lt;xs:element name="firstname" type="xs:string"/&gt;<br />　　&lt;xs:element name="lastname" type="xs:string"/&gt;<br />　　&lt;xs:element name="phoneNumber" type="xs:string"/&gt;<br />　　&lt;xs:element name="address" type="addressType"/&gt;<br />　　&lt;/xs:sequence&gt;<br />　　&lt;/xs:complexType&gt;<br />　　&lt;xs:complexType name="addressType"&gt;<br />　　&lt;xs:sequence&gt;<br />　　&lt;xs:element name="primaryAddress" type="primaryAddressType"/&gt;<br />　　&lt;xs:element name="billingAddress" type="billingAddressType"/&gt;<br />　　&lt;/xs:sequence&gt;<br />　　&lt;/xs:complexType&gt;<br />　　&lt;xs:complexType name="primaryAddressType"&gt;<br />　　&lt;xs:sequence&gt;<br />　　&lt;xs:element name="postalCode" type="xs:string"/&gt;<br />　　&lt;xs:element name="addressLine1" type="xs:string"/&gt;<br />　　&lt;xs:element name="addressLine2" type="xs:string"/&gt;<br />　　&lt;/xs:sequence&gt;<br />　　&lt;/xs:complexType&gt;<br />　　&lt;xs:complexType name="billingAddressType"&gt;<br />　　&lt;xs:sequence&gt;<br />　　&lt;xs:element name="receiver" type="xs:string"/&gt;<br />　　&lt;xs:element name="postalCode" type="xs:string"/&gt;<br />　　&lt;xs:element name="addressLine1" type="xs:string"/&gt;<br />　　&lt;xs:element name="addressLine2" type="xs:string"/&gt;<br />　　&lt;/xs:sequence&gt;<br />　　&lt;/xs:complexType&gt;<br />　　&lt;/xs:schema&gt;<br />　　<br />　　2. 利用scomp来生成Java Classes<br />　　<br />　　scomp是XMLBean提供的一个编译工具,它在bin的目录下. 通过这个工具,我们可以将以上的Schema文件生成Java Classes.<br />　　<br />　　scomp的语法如下:-<br />　　<br />　　scomp [options] [dirs]* [schemaFile.xsd]* [service.wsdl]* [config.xsdconfig]*<br />　　<br />　　主要参数说明:<br />　　-src [dir]　　　　　　　　　-- 生成的Java Classes存放目录<br />　　-srconly　　　　　　　　　-- 不编译Java Classes,不产生Jar文件<br />　　-out [jarFileName]　-- 生成的Jar文件,缺省是xmltypes.jar<br />　　-compiler　　　　　　　　 -- Java编译器的路径,即Javac的位置<br />　　schemaFile.xsd　　-- XML Schema文件位置<br />　　config.xsdconfig　 -- xsdconfig文件的位置, 这个文件主要用来制定生成的Java Class<br />　　的一些文件名规则和Package的名称,在本文,package是sample.xmlbean<br />　　<br />　　在本文,我是这样运行的:<br />　　scomp -src build\src　-out build\customerXmlBean.jar schema\customer.xsd<br />　　-compiler C:\jdk142_04\bin\javac customer.xsdconfig<br />　　<br />　　这个命令行的意思是告诉scomp生成customerXmlBean.jar,放在build目录下,同时<br />　　生成源代码放在build\src下, Schema文件是customer.xsd,xsdconfig文件是customer.xsdconfig.<br />　　<br />　　其实, 生成的Java源代码没有多大作用,我们要的是jar文件.我们先看一下build\src\sample\xmlbean下生成的Classes.<br />　　CustomersDocument.java<br />　　-- 整个XML文档的Java Class映射<br />　　CustomerType.java<br />　　-- 节点sustomer的映射<br />　　AddressType.java<br />　　-- 节点address的映射<br />　　BillingAddressType.java<br />　　-- 节点billingAddress的映射<br />　　PrimaryAddressType.java<br />　　-- 节点primaryAddress的映射<br />　　<br />　　好了,到此我们所有的准备工作已经完成了. 下面就开始进入重点：利用刚才生成的jar文件读写XML.<br />　　<br />　　<b>五、利用XMLBean读XML文件</b><br />　　<br />　　新建一个Java Project,将XMLBean2.0.0\lib\下的Jar文件和刚才我们生成的customerXmlBean.jar加入<br />　　<br />　　到Project的ClassPath.<br />　　<br />　　新建一个Java Class: CustomerXMLBean.　源码如下:<br />　　package com.sample.reader;<br />　　import java.io.File;<br />　　import sample.xmlbean.*;<br />　　import org.apache.commons.beanutils.BeanUtils;<br />　　import org.apache.xmlbeans.XmlOptions;<br />　　public class CustomerXMLBean {<br />　　private String filename = null;<br />　　public CustomerXMLBean(String filename) {<br />　　super();<br />　　this.filename = filename;<br />　　}<br />　　public void customerReader() {<br />　　try {<br />　　File xmlFile = new File(filename);<br />　　CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);<br />　　CustomerType[] customers = doc.getCustomers().getCustomerArray();<br />　　for (int i = 0; i &lt; customers.length; i++) {<br />　　CustomerType customer = customers[i];<br />　　println("Customer#" + i);<br />　　println("Customer ID:" + customer.getId());<br />　　println("First name:" + customer.getFirstname());<br />　　println("Last name:" + customer.getLastname());<br />　　println("Gender:" + customer.getGender());<br />　　println("PhoneNumber:" + customer.getPhoneNumber());<br />　　// Primary address<br />　　PrimaryAddressType primaryAddress = customer.getAddress().getPrimaryAddress();<br />　　println("PrimaryAddress:");<br />　　println("PostalCode:" + primaryAddress.getPostalCode());<br />　　println("AddressLine1:" + primaryAddress.getAddressLine1());<br />　　println("AddressLine2:" + primaryAddress.getAddressLine2());<br />　　// Billing address<br />　　BillingAddressType billingAddress = customer.getAddress().getBillingAddress();<br />　　println("BillingAddress:");<br />　　println("Receiver:" + billingAddress.getReceiver());<br />　　println("PostalCode:" + billingAddress.getPostalCode());<br />　　println("AddressLine1:" + billingAddress.getAddressLine1());<br />　　println("AddressLine2:" + billingAddress.getAddressLine2());<br />　　}<br />　　} catch (Exception ex) {<br />　　ex.printStackTrace();<br />　　}<br />　　}<br />　　private void println(String str) {<br />　　System.out.println(str);　　}　 public static void main(String[] args) {<br />　　String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers.xml";<br />　　CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);<br />　　customerXMLBean.customerReader();<br />　　}<br />　　}<br />　　<br />　　运行它,参看输出结果:<br />　　Customer#0<br />　　Customer ID:1<br />　　First name:Jessica<br />　　Last name:Lim<br />　　Gender:female<br />　　PhoneNumber:1234567<br />　　PrimaryAddress:<br />　　PostalCode:350106<br />　　AddressLine1:#25-1<br />　　AddressLine2:SHINSAYAMA 2-CHOME<br />　　BillingAddress:<br />　　Receiver:Ms Danielle<br />　　PostalCode:350107<br />　　AddressLine1:#167<br />　　AddressLine2:NORTH TOWER HARBOUR CITY<br />　　Customer#1<br />　　Customer ID:2<br />　　First name:David<br />　　Last name:Bill<br />　　Gender:male<br />　　PhoneNumber:808182<br />　　PrimaryAddress:<br />　　PostalCode:319087<br />　　AddressLine1:1033 WS St.<br />　　AddressLine2:Tima Road<br />　　BillingAddress:<br />　　Receiver:Mr William<br />　　PostalCode:672993<br />　　AddressLine1:1033 WS St.<br />　　AddressLine2:Tima Road<br />　　怎么样,是不是很轻松? XMLBean的威力.<br />　　<br />　　<b>六、利用XMLBean写XML文件</b><br />　　<br />　　利用XMLBean创建一个XML文档也是一件轻而易举的事.我们再增加一个Method,<br />　　请看一下的Java Class:<br />　　public void createCustomer() {<br />　　try {<br />　　// Create Document<br />　　CustomersDocument doc = CustomersDocument.Factory.newInstance();<br />　　// Add new customer<br />　　CustomerType customer = doc.addNewCustomers().addNewCustomer();<br />　　// set customer info<br />　　customer.setId(3);<br />　　customer.setFirstname("Jessica");<br />　　customer.setLastname("Lim");<br />　　customer.setGender("female");<br />　　customer.setPhoneNumber("1234567");<br />　　// Add new address<br />　　AddressType address = customer.addNewAddress();<br />　　// Add new PrimaryAddress<br />　　PrimaryAddressType primaryAddress = address.addNewPrimaryAddress();<br />　　primaryAddress.setPostalCode("350106");<br />　　primaryAddress.setAddressLine1("#25-1");<br />　　primaryAddress.setAddressLine2("SHINSAYAMA 2-CHOME");<br />　　// Add new BillingAddress<br />　　BillingAddressType billingAddress = address.addNewBillingAddress();<br />　　billingAddress.setReceiver("Ms Danielle");<br />　　billingAddress.setPostalCode("350107");<br />　　billingAddress.setAddressLine1("#167");<br />　　billingAddress.setAddressLine2("NORTH TOWER HARBOUR CITY");<br />　　File xmlFile = new File(filename);<br />　　doc.save(xmlFile);　　　　} catch (Exception ex) {<br />　　ex.printStackTrace();　　　　}　}<br />　　修改main method.<br />　　public static void main(String[] args) {<br />　　String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";<br />　　CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);<br />　　customerXMLBean.createCustomer();<br />　　}<br />　　运行,打开customers_new.xml:<br />　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />　　&lt;Customers&gt;<br />　　&lt;customer&gt;<br />　　&lt;id&gt;3&lt;/id&gt;<br />　　&lt;gender&gt;female&lt;/gender&gt;<br />　　&lt;firstname&gt;Jessica&lt;/firstname&gt;<br />　　&lt;lastname&gt;Lim&lt;/lastname&gt;<br />　　&lt;phoneNumber&gt;1234567&lt;/phoneNumber&gt;<br />　　&lt;address&gt;<br />　　&lt;primaryAddress&gt;<br />　　&lt;postalCode&gt;350106&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;#25-1&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;SHINSAYAMA 2-CHOME&lt;/addressLine2&gt;<br />　　&lt;/primaryAddress&gt;<br />　　&lt;billingAddress&gt;<br />　　&lt;receiver&gt;Ms Danielle&lt;/receiver&gt;<br />　　&lt;postalCode&gt;350107&lt;/postalCode&gt;<br />　　&lt;addressLine1&gt;#167&lt;/addressLine1&gt;<br />　　&lt;addressLine2&gt;NORTH TOWER HARBOUR CITY&lt;/addressLine2&gt;<br />　　&lt;/billingAddress&gt;<br />　　&lt;/address&gt;<br />　　&lt;/customer&gt;<br />　　&lt;/Customers&gt;<br />　　<br />　　<b>七、利用XMLBean修改XML文件</b><br />　　<br />　　我们再增加一个Method:<br />　　public void updateCustomer(int id,String lastname) {<br />　　try {<br />　　File xmlFile = new File(filename);<br />　　CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);<br />　　CustomerType[] customers = doc.getCustomers().getCustomerArray();<br />　　for (int i = 0; i &lt; customers.length; i++) {<br />　　CustomerType customer = customers[i];<br />　　if(customer.getId()==id){<br />　　customer.setLastname(lastname);<br />　　break;<br />　　}<br />　　}<br />　　doc.save(xmlFile);<br />　　} catch (Exception ex) {<br />　　ex.printStackTrace();<br />　　}<br />　　}<br />　　main method:<br />　　public static void main(String[] args) {<br />　　String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";<br />　　CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);<br />　　customerXMLBean.updateCustomer(3,"last");　　}<br />　　运行之后,我们将会看到客户编号为3的客户的lastname已经改为last.<br />　　<br />　　<b>八、利用XMLBean删除一个customer</b><br />　　<br />　　再增加一个Method:<br />　　public void deleteCustomer(int id) {<br />　　try {<br />　　File xmlFile = new File(filename);<br />　　CustomersDocument doc = CustomersDocument.Factory.parse(xmlFile);<br />　　CustomerType[] customers = doc.getCustomers().getCustomerArray();<br />　　for (int i = 0; i &lt; customers.length; i++) {<br />　　CustomerType customer = customers[i];<br />　　if(customer.getId()==id){<br />　　customer.setNil() ;<br />　　break;<br />　　}<br />　　}<br />　　doc.save(xmlFile);<br />　　} catch (Exception ex) {<br />　　ex.printStackTrace();<br />　　}<br />　　}<br />　　<br />　　main method:<br />　　public static void main(String[] args) {<br />　　String filename = "F://JavaTest//Eclipse//XMLBean//xml//customers_new.xml";<br />　　CustomerXMLBean customerXMLBean = new CustomerXMLBean(filename);<br />　　customerXMLBean.deleteCustomer(3);<br />　　}<br />　　<br />　　运行,我们将会看到客户编号为3的客户的资料已经被删除.<br />　　<br />　　<b>九、查询XML<br />　　</b><br />　　除了本文在以上讲述的,利用XMLBean能轻轻松松完成XML的读写操作外,结合XPath和XQuery,<br />　　<br />　　XMLBean还能完成象SQL查询数据库一样方便地查询XML数据. 关于XML查询以及如何创建XML数据库, 我将在另一篇文章里讨论.<br />　　<br />　　<b>十、结束语</b><br />　　<br />　　XMLBean能帮助我们轻易读写XML,这将有助于我们降低XML的学习和使用,有了这个基础,开发人员将为学习更多地XML相关技术和Web Services,JMS等其他J2EE技术打下良好地基础. <img src ="http://www.cppblog.com/yunduan5158/aggbug/9659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-10 20:20 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/10/9659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java与XML（三）web上的读写应用</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9653.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Mon, 10 Jul 2006 10:31:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9653.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9653.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9653.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9653.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9653.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 利用（二）中我写的两个函数（放在package src中），这次实现web页面的操作。index.html:&lt;%@ page language="java" pageEncoding="GB2312"%&gt;&lt;body&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt...&nbsp;&nbsp;<a href='http://www.cppblog.com/yunduan5158/archive/2006/07/10/9653.html'>阅读全文</a><img src ="http://www.cppblog.com/yunduan5158/aggbug/9653.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-10 18:31 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/10/9653.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java与XML（二）用java编写xml的读写程序</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9652.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Mon, 10 Jul 2006 10:16:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9652.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9652.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9652.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9652.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9652.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这是读取xml文件的java程序，我调试好的。采用的是dom方式读取xml文件到Vector中。						 1								package				 src;				 2																		import				 java.io.				*				;				 3																		import...&nbsp;&nbsp;<a href='http://www.cppblog.com/yunduan5158/archive/2006/07/10/9652.html'>阅读全文</a><img src ="http://www.cppblog.com/yunduan5158/aggbug/9652.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-10 18:16 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/10/9652.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java与XML（一）基础</title><link>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9649.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Mon, 10 Jul 2006 09:33:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9649.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/9649.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/07/10/9649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/9649.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/9649.html</trackback:ping><description><![CDATA[
		<p>JAXP API--嵌入不同的解释器</p>
		<p>SAX解释器+DOM解释器+XSL转换器</p>
		<p>javax.xml.parsers中加载XML文档的类：<br />DocumentBuilder<br />DocumentBuildrFactory<br />SAXParser<br />SAXParserFactory<br />=====================================<br />SAX API<br /><br />SAX的XML解释器：Apache的Xerces或Crimson<br /><br />处理XML文档的接口：<br />ContentHandler<br />EntityResolver<br />ErroHandler<br />DTDHandler<br /><br />DeclHandler<br />LexicalHandler<br />======================================<br />DOM API<br /><br />两个DOM标准：DOM Level1 DOM Level 2 Core<br /><br />节点<br />Node-节点类型接口层次结构的根。<br />Document-树结构的根<br />Element-XML元素<br />Text-元素内的文本<br />Attr-元素的特性<br />CDATA Sectionn-CDATA<br />NodeList-子节点的集合<br />ProcessingInstruction-指令<br />Comment-包含注释的信息<br />DocumentFragment-Document的消减版，用于在树中移动节点<br />DocumentType-文档类型定义的子集。<br />Entity-DTD中的实体标记<br />EntityReference-XML文档中的实体引用<br />Notation-DTD中的符号标记<br /><br /><br />从程序中读取X M L文档基本上有三种方式：<br />1把X M L只当做一个文件读取，然后自己挑选出其中的标签。这是黑客们的方法，我们不推荐这种方式。<br />你很快会发现处理所有的特殊情况（包括不同的字符编码，例外约定，内部和外部实体，缺省属性等）比想象的困难得多；<br />你可能不能够正确地处理所有的特殊情况，这样你的程序会接收到一个非常规范的X M L文档，却不能正确地处理它。<br />要避免这种想法：XML解析器似乎并不昂贵（大多数是免费的）。<br />2可以用解析器分析文档并在内存里创建对文档内容树状的表达方式：解析器将输出传递给文档对象模型，即DOM。<br />这样程序可以从树的顶部开始遍历，按照从一个树单元到另一个单元的引用，从而找到需要的信息。<br />3也可以用解析器读取文档，当解析器发现标签时告知程序它发现的标签。<br />例如它会告知它何时发现了一个开始标签，何时发现了一些特征数据，以及何时发现了一个结束标签。<br />这叫做事件驱动接口，因为解析器告知应用程序它遇到的有含义的事件。<br />如果这正是你需要的那种接口，可以使用SAX。<br /><br />SAX是只读的<br />DOM可以从XML原文件中读取文档，也可以创建和修改内存中的文档。相比较而言，SAX是用来读取XML文档而不是书写文档。<br /><br />可扩展样式语言(XSL,eXtensible Sytlesheet Language）是一种基于XML的语言，<br />它被设计用来转换XML文档到另一种XML文档或转换XML文档为可翻译对象。<br />原始的XSL语言已经被分割成三种不同的语言：<br />1转换工具（XSLT）是一种转换XML文档到其他XML文档的语言<br />2翻译工具（XSLF—可以包括X S LT的使用）<br />3XML分级命令处理工具（XPath）<br />XSL有它自已的根，不管是在层叠样式表（CSS）中还是在一种叫DSSSL(文档样式语义和规格语言—读为'deessel')的语言中。<br />随着它的发展，XSL的样式表现变得更接近于CSS和远离DSSSL<br /></p>
<img src ="http://www.cppblog.com/yunduan5158/aggbug/9649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-07-10 17:33 <a href="http://www.cppblog.com/yunduan5158/archive/2006/07/10/9649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>作用域</title><link>http://www.cppblog.com/yunduan5158/archive/2006/04/27/6397.html</link><dc:creator>Merlin</dc:creator><author>Merlin</author><pubDate>Thu, 27 Apr 2006 13:47:00 GMT</pubDate><guid>http://www.cppblog.com/yunduan5158/archive/2006/04/27/6397.html</guid><wfw:comment>http://www.cppblog.com/yunduan5158/comments/6397.html</wfw:comment><comments>http://www.cppblog.com/yunduan5158/archive/2006/04/27/6397.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yunduan5158/comments/commentRss/6397.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yunduan5158/services/trackbacks/6397.html</trackback:ping><description><![CDATA[
		<p>学完了C++,在学java， 会发现很多东西很像，我在这就只是记录一些不同的地方，其他的就不提了 呵呵<br /><br />这个在java中是不合法的：<br /><br /></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #008080">1</span>
				<img id="Codehighlighter1_0_26_Open_Image" onclick="this.style.display='none'; Codehighlighter1_0_26_Open_Text.style.display='none'; Codehighlighter1_0_26_Closed_Image.style.display='inline'; Codehighlighter1_0_26_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
				<img id="Codehighlighter1_0_26_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_26_Closed_Text.style.display='none'; Codehighlighter1_0_26_Open_Image.style.display='inline'; Codehighlighter1_0_26_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" />
				<span id="Codehighlighter1_0_26_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_0_26_Open_Text">
						<span style="COLOR: #000000">{<br /></span>
						<span style="COLOR: #008080">2</span>
						<span style="COLOR: #000000">
								<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
						</span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> x</span>
						<span style="COLOR: #000000">=</span>
						<span style="COLOR: #000000">12</span>
						<span style="COLOR: #000000">;<br /></span>
						<span style="COLOR: #008080">3</span>
						<span style="COLOR: #000000">
								<img id="Codehighlighter1_12_24_Open_Image" onclick="this.style.display='none'; Codehighlighter1_12_24_Open_Text.style.display='none'; Codehighlighter1_12_24_Closed_Image.style.display='inline'; Codehighlighter1_12_24_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_12_24_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_12_24_Closed_Text.style.display='none'; Codehighlighter1_12_24_Open_Image.style.display='inline'; Codehighlighter1_12_24_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />
						</span>
						<span id="Codehighlighter1_12_24_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.cppblog.com/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_12_24_Open_Text">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080">4</span>
								<span style="COLOR: #000000">
										<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
								</span>
								<span style="COLOR: #0000ff">int</span>
								<span style="COLOR: #000000"> x</span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000">23</span>
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080">5</span>
								<span style="COLOR: #000000">
										<img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span>
						</span>
						<span style="COLOR: #000000">
								<br />
						</span>
						<span style="COLOR: #008080">6</span>
						<span style="COLOR: #000000">
								<img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
		</div>编译器会说 x已经定义了，呵呵　。<img src ="http://www.cppblog.com/yunduan5158/aggbug/6397.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yunduan5158/" target="_blank">Merlin</a> 2006-04-27 21:47 <a href="http://www.cppblog.com/yunduan5158/archive/2006/04/27/6397.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>