﻿<?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>BlogJava-永远的船长-随笔分类-底层知识</title><link>http://www.blogjava.net/buaacaptain/category/11629.html</link><description>只有偏执狂才能生存</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 03:33:38 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 03:33:38 GMT</pubDate><ttl>60</ttl><item><title>小议HashMap</title><link>http://www.blogjava.net/buaacaptain/archive/2006/07/20/59178.html</link><dc:creator>船长</dc:creator><author>船长</author><pubDate>Thu, 20 Jul 2006 06:14:00 GMT</pubDate><guid>http://www.blogjava.net/buaacaptain/archive/2006/07/20/59178.html</guid><wfw:comment>http://www.blogjava.net/buaacaptain/comments/59178.html</wfw:comment><comments>http://www.blogjava.net/buaacaptain/archive/2006/07/20/59178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/buaacaptain/comments/commentRss/59178.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/buaacaptain/services/trackbacks/59178.html</trackback:ping><description><![CDATA[
		<p align="left">大家都知道，在Java里对对象的操作是基于引用的。而当我们需要对一组对象操作的时候，就需要有接收这一组引用的容器。平时我们最常用的就是数组。在Java里可以定义一个对象数组来完成许多操作。可是，数组长度是固定的，如果我们需要更加灵活的解决方案该怎么办呢？</p>
		<p align="left">Java提供了container classes来解决这一问题。container classes包括两个部分：Collection和Map。它们的结构是这样的：</p>
		<p align="left">
				<img height="492" src="http://www.frontfree.net/articles/pages/0000000695/container.gif" width="510" />
		</p>
		<p align="left">本文重点介绍HashMap。首先介绍一下什么是Map。在数组中我们是通过数组下标来对其内容索引的，而在Map中我们通过对象来对对象进行索引，用来索引的对象叫做key，其对应的对象叫做value。在下文中会有例子具体说明。</p>
		<p align="left">再来看看HashMap和TreeMap有什么区别。HashMap通过hashcode对其内容进行快速查找，而TreeMap中所有的元素都保持着某种固定的顺序，如果你需要得到一个有序的结果你就应该使用TreeMap（HashMap中元素的排列顺序是不固定的）。</p>
		<p align="left">下面就要进入本文的主题了。先举个例子说明一下怎样使用HashMap:</p>
		<table class="code" style="BORDER-COLLAPSE: collapse" bordercolor="#111111" cellspacing="0" cellpadding="4" width="100%" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td width="100%">
										<font color="#0000ff">import</font> java.util.*; 
<p><font color="#0000ff">public class</font> Exp1 {<br />     <font color="#0000ff">public static void</font> main(String[] args){<br />          HashMap h1=<font color="#0000ff">new</font> HashMap();<br />          Random r1=<font color="#0000ff">new</font> Random();    <br />          <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i=0;i&lt;1000;i++){<br />               Integer t=new Integer(r1.nextInt(20));<br />               <font color="#0000ff">if</font>(h1.containsKey(t))<br />                    ((Ctime)h1.get(t)).count++;<br />               <font color="#0000ff">else</font><br />                    h1.put(t, new Ctime());<br />          }<br />          System.out.println(h1);<br />     }<br />}</p><p><font color="#0000ff">class</font> Ctime{<br />     <font color="#0000ff">int</font> count=1;<br />     <font color="#0000ff">public</font> String toString(){<br />          <font color="#0000ff">return</font> Integer.toString(count);<br />     }<br />}</p></td>
						</tr>
				</tbody>
		</table>
		<p align="left">在HashMap中通过get()来获取value，通过put()来插入value，ContainsKey()则用来检验对象是否已经存在。可以看出，和ArrayList的操作相比，HashMap除了通过key索引其内容之外，别的方面差异并不大。</p>
		<p align="left">前面介绍了，HashMap是基于HashCode的，在所有对象的超类Object中有一个HashCode()方法，但是它和equals方法一样，并不能适用于所有的情况，这样我们就需要重写自己的HashCode()方法。下面就举这样一个例子：</p>
		<table class="code" style="BORDER-COLLAPSE: collapse" bordercolor="#111111" cellspacing="0" cellpadding="4" width="100%" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td width="100%">
										<font color="#0000ff">import</font> java.util.*; 
<p><font color="#0000ff">public</font> class Exp2 {<br />     <font color="#0000ff">public static void</font> main(String[] args){<br />          HashMap h2=<font color="#0000ff">new</font> HashMap();<br />          <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i=0;i&lt;10;i++)<br />               h2.put(<font color="#0000ff">new</font> Element(i), <font color="#0000ff">new</font> Figureout());<br />          System.out.println("h2:");<br />          System.out.println("Get the result for Element:");<br />          Element test=<font color="#0000ff">new</font> Element(5);<br />          <font color="#0000ff">if</font>(h2.containsKey(test))<br />               System.out.println((Figureout)h2.get(test));<br />          <font color="#0000ff">else</font><br />               System.out.println("Not found");<br />     }<br />}</p><p><font color="#0000ff">class</font> Element{<br />     <font color="#0000ff">int</font> number;<br />     <font color="#0000ff">public</font> Element(<font color="#0000ff">int</font> n){<br />          number=n;<br />     } <br />}</p><p><font color="#0000ff">class</font> Figureout{<br />     Random r=<font color="#0000ff">new</font> Random();<br />     <font color="#0000ff">boolean</font> possible=r.nextDouble()&gt;0.5;<br />     <font color="#0000ff">public</font> String toString(){<br />          <font color="#0000ff">if</font>(possible)<br />               <font color="#0000ff">return</font> "OK!";<br />          <font color="#0000ff">else</font><br />               <font color="#0000ff">return</font> "Impossible!";<br />     }<br />}</p></td>
						</tr>
				</tbody>
		</table>
		<p align="left">在这个例子中，Element用来索引对象Figureout,也即Element为key，Figureout为value。在Figureout中随机生成一个浮点数，如果它比0.5大，打印“OK!”，否则打印“Impossible!”。之后查看Element(3)对应的Figureout结果如何。</p>
		<p align="left">结果却发现，无论你运行多少次，得到的结果都是“Not found”。也就是说索引Element(3)并不在HashMap中。这怎么可能呢？</p>
		<p align="left">原因得慢慢来说：Element的HashCode方法继承自Object，而Object中的HashCode方法返回的HashCode对应于当前的地址，也就是说对于不同的对象，即使它们的内容完全相同，用HashCode（）返回的值也会不同。这样实际上违背了我们的意图。因为我们在使用HashMap时，希望利用相同内容的对象索引得到相同的目标对象，这就需要HashCode()在此时能够返回相同的值。在上面的例子中，我们期望new Element(i) (i=5)与 Element test=new Element(5)是相同的，而实际上这是两个不同的对象，尽管它们的内容相同，但它们在内存中的地址不同。因此很自然的，上面的程序得不到我们设想的结果。下面对Element类更改如下：</p>
		<table class="code" style="BORDER-COLLAPSE: collapse" bordercolor="#111111" cellspacing="0" cellpadding="4" width="100%" bgcolor="#e0e0e0" border="0">
				<tbody>
						<tr>
								<td width="100%">
										<font color="#0000ff">class</font> Element{<br />     <font color="#0000ff">int</font> number;<br />     <font color="#0000ff">public</font> Element(<font color="#0000ff">int</font> n){<br />          number=n;<br />     } <br />     <font color="#0000ff">public int</font> hashCode(){<br />          return number;<br />     }<br />     <font color="#0000ff">public boolean</font> equals(Object o){<br />          <font color="#0000ff">return</font> (o instanceof Element) &amp;&amp; (number==((Element)o).number);<br />     }<br />}</td>
						</tr>
				</tbody>
		</table>
		<p align="left">在这里Element覆盖了Object中的hashCode()和equals()方法。覆盖hashCode()使其以number的值作为hashcode返回，这样对于相同内容的对象来说它们的hashcode也就相同了。而覆盖equals()是为了在HashMap判断两个key是否相等时使结果有意义（有关重写equals()的内容可以参考我的另一篇文章《重新编写Object类中的方法 》）。修改后的程序运行结果如下：</p>
		<p align="left">h2:<br />Get the result for Element:<br />Impossible!</p>
		<p align="left">请记住：如果你想有效的使用HashMap，你就必须重写在其的HashCode()。</p>
		<p align="left">还有两条重写HashCode()的原则：</p>
		<ol>
				<li>不必对每个不同的对象都产生一个唯一的hashcode，只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。即“不为一原则”。 
</li>
				<li>生成hashcode的算法尽量使hashcode的值分散一些，不要很多hashcode都集中在一个范围内，这样有利于提高HashMap的性能。即“分散原则”。 </li>
		</ol>
		<p>至于第二条原则的具体原因，有兴趣者可以参考Bruce Eckel的《Thinking in Java》，在那里有对HashMap内部实现原理的介绍，这里就不赘述了。</p>
		<p>掌握了这两条原则，你就能够用好HashMap编写自己的程序了。不知道大家注意没有，java.lang.Object中提供的三个方法：clone()，equals()和hashCode()虽然很典型，但在很多情况下都不能够适用，它们只是简单的由对象的地址得出结果。这就需要我们在自己的程序中重写它们，其实java类库中也重写了千千万万个这样的方法。利用面向对象的多态性——覆盖，Java的设计者很优雅的构建了Java的结构，也更加体现了Java是一门纯OOP语言的特性。</p>
		<p>Java提供的Collection和Map的功能是十分强大的，它们能够使你的程序实现方式更为灵活，执行效率更高。希望本文能够对大家更好的使用HashMap有所帮助。 </p>
<img src ="http://www.blogjava.net/buaacaptain/aggbug/59178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/buaacaptain/" target="_blank">船长</a> 2006-07-20 14:14 <a href="http://www.blogjava.net/buaacaptain/archive/2006/07/20/59178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有关servlet的生命周期问题</title><link>http://www.blogjava.net/buaacaptain/archive/2006/06/05/50522.html</link><dc:creator>船长</dc:creator><author>船长</author><pubDate>Mon, 05 Jun 2006 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/buaacaptain/archive/2006/06/05/50522.html</guid><wfw:comment>http://www.blogjava.net/buaacaptain/comments/50522.html</wfw:comment><comments>http://www.blogjava.net/buaacaptain/archive/2006/06/05/50522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/buaacaptain/comments/commentRss/50522.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/buaacaptain/services/trackbacks/50522.html</trackback:ping><description><![CDATA[
		<span id="LblContent">servlet有良好的生存期的定义，包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。<br />1、加载和实例化<br />容器负责加载和实例化一个servlet。实例化和加载可以发生在引擎启动的时候，也可以推迟到容器需要该servlet为客户请求服务的时候。<br />首先容器必须先定位servlet类，在必要的情况下，容器使用通常的Java类加载工具加载该servlet，可能是从本机文件系统，也可以是从远程文件系统甚至其它的网络服务。容器加载servlet类以后，它会实例化该类的一个实例。需要注意的是可能会实例化多个实例，例如一个servlet类因为有不同的初始参数而有多个定义，或者servlet实现SingleThreadModel而导致容器为之生成一个实例池。<br /><br />2、初始化<br />servlet加载并实例化后，容器必须在它能够处理客户端请求前初始化它。初始化的过程主要是读取永久的配置信息，昂贵资源（例如JDBC连接）以及其它仅仅需要执行一次的任务。通过调用它的init方法并给它传递唯一的一个（每个servlet定义一个）ServletConfig对象完成这个过程。给它传递的这个配置对象允许servlet访问容器的配置信息中的名称－值对（name-value）初始化参数。这个配置对象同时给servlet提供了访问实现了ServletContext接口的具体对象的方法，该对象描述了servlet的运行环境。<br />    2.1初始化的错误处理<br />    在初始化期间，servlet实例可能通过抛出UnavailableException 或者 ServletException异常表明它不能进行有效服务。如果一个servlet抛出一个这样的异常，它将不会被置入有效服务并且应该被容器立即释放。在此情况下destroy方法不会被调用因为初始化没有成功完成。在失败的实例被释放后，容器可能在任何时候实例化一个新的实例，对这个规则的唯一例外是如果失败的servlet抛出的异常是UnavailableException并且该异常指出了最小的无效时间，那么容器就会至少等待该时间指明的时限才会重新试图创建一个新的实例。<br />    2.2、工具因素<br />    当工具（注：根据笔者的理解，这个工具可能是应用服务器的某些检查工具，通常是验证应用的合法性和完整性）加载和内省（introspect）一个web应用时，它可能加载和内省该应用中的类，这个行为将触发那些类的静态初始方法被执行，因此，开发者不能假定只要当servlet的init方法被调用后它才处于活动容器运行状态（active container runtime）。作为一个例子，这意味着servlet不能在它的静态（类）初始化方法被调用时试图建立数据库连接或者连接EJB容器。<br /><br />3、处理请求<br />在servlet被适当地初始化后，容器就可以使用它去处理请求了。每一个请求由ServletRequest类型的对象代表，而servlet使用ServletResponse回应该请求。这些对象被作为service方法的参数传递给servlet。在HTTP请求的情况下，容器必须提供代表请求和回应的HttpServletRequest和HttpServletResponse的具体实现。需要注意的是容器可能会创建一个servlet实例并将之放入等待服务的状态，但是这个实例在它的生存期中可能根本没有处理过任何请求。<br />    3.1、多线程问题<br />    容器可能同时将多个客户端的请求发送给一个实例的service方法，这也就意味着开发者必须确保编写的servlet可以处理并发问题。如果开发者想防止这种缺省的行为，那么他可以让他编写的servlet实现SingleThreadModel。实现这个类可以保证一次只会有一个线程在执行service方法并且一次性执行完。容器可以通过将请求排队或者维护一个servlet实例池满足这一点。如果servlet是分布式应用的一部分，那么，那么容器可能在该应用分布的每个JVM中都维护一个实例池。如果开发者使用synchronized关键字定义service方法(或者是doGet和doPost)，容器将排队处理请求，这是由底层的java运行时系统要求的。我们强烈推荐开发者不要同步service方法或者HTTPServlet的诸如doGet和doPost这样的服务方法。<br />    3.2、处理请求中的异常<br />    servlet在对请求进行服务的时候有可能抛出ServletException或者UnavailableException异常。ServletException表明在处理请求的过程中发生了错误容器应该使用合适的方法清除该请求。UnavailableException表明servlet不能对请求进行处理，可能是暂时的，也可能是永久的。如果UnavailableException指明是永久性的，那么容器必须将servlet从服务中移除，调用它的destroy方法并释放它的实例。如果指明是暂时的，那么容器可以选择在异常信息里面指明的这个暂时无法服务的时间段里面不向它发送任何请求。在这个时间段里面被被拒绝的请求必须使用SERVICE_UNAVAILABLE (503)返回状态进行响应并且应该携带稍后重试（Retry-After）的响应头表明不能服务只是暂时的。容器也可以选择不对暂时性和永久性的不可用进行区分而全部当作永久性的并移除抛出异常的servlet。<br />    3.3线程安全<br />    开发者应该注意容器实现的请求和响应对象（注：即容器实现的HttpServletRequest和HttpServletResponese）没有被保证是线程安全的，这就意味着他们只能在请求处理线程的范围内被使用，这些对象不能被其它执行线程所引用，因为引用的行为是不确定的。<br /><br />4、服务结束<br />容器没有被要求将一个加载的servlet保存多长时间，因此一个servlet实例可能只在容器中存活了几毫秒，当然也可能是其它更长的任意时间（但是肯定会短于容器的生存期）<br />当容器决定将之移除时（原因可能是保存内存资源或者自己被关闭），那么它必须允许servlet释放它正在使用的任何资源并保存任何永久状态（这个过程通过调用destroy方法达到）。容器在能够调用destroy方法前，它必须允许那些正在service方法中执行的线程执行完或者在服务器定义的一段时间内执行（这个时间段在容器调用destroy之前）。一旦destroy方法被调用，容器就不会再向该实例发送任何请求。如果容器需要再使用该servlet，它必须创建新的实例。destroy方法完成后，容器必须释放servlet实例以便它能够被垃圾回收。<br /><br />另参考<a href="http://tech.ccidnet.com/art/1077/20041123/180515_1.html">http://tech.ccidnet.com/art/1077/20041123/180515_1.html</a><br /><a href="http://dev2dev.bea.com.cn/techdoc/20051024674.html">http://dev2dev.bea.com.cn/techdoc/20051024674.html</a></span>
<img src ="http://www.blogjava.net/buaacaptain/aggbug/50522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/buaacaptain/" target="_blank">船长</a> 2006-06-05 16:24 <a href="http://www.blogjava.net/buaacaptain/archive/2006/06/05/50522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:什么是jvm？你很清楚地了解它吗？</title><link>http://www.blogjava.net/buaacaptain/archive/2006/05/30/48860.html</link><dc:creator>船长</dc:creator><author>船长</author><pubDate>Mon, 29 May 2006 16:51:00 GMT</pubDate><guid>http://www.blogjava.net/buaacaptain/archive/2006/05/30/48860.html</guid><wfw:comment>http://www.blogjava.net/buaacaptain/comments/48860.html</wfw:comment><comments>http://www.blogjava.net/buaacaptain/archive/2006/05/30/48860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/buaacaptain/comments/commentRss/48860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/buaacaptain/services/trackbacks/48860.html</trackback:ping><description><![CDATA[
		<br />     转自matrix:http://www.matrix.org.cn/resource/article/0/20.html<br />      在Java中引入了虚拟机的概念，即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机，生成虚拟机能够理解的代码，然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中，这种供虚拟机理解的代码叫做字节码（ByteCode），它不面向任何特定的处理器，只面向虚拟机。每一种平台的解释器是不同的，但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码，字节码由虚拟机解释执行，虚拟机将每一条要执行的字节码送给解释器，解释器将其翻译成特定机器上的机器码，然后在特定的机器上运行。<br />    可以说，Java虚拟机是Java语言的基础。它是Java技术的重要组成部分。Java虚拟机是一个抽象的计算机，和实际的计算机一样，它具有一个指令集并使用不同的存储区域。它负责执行指令，还要管理数据、内存和寄存器。Java解释器负责将字节代码翻译成特定机器的机器代码。Java是一种简单的语言。它用到的概念不多，而且多为程序员所熟悉。如果你是一名程序员，掌握Java对你来说是易如反掌的事。即使你没有学过任何编程语言，学习Java也要比学习C++要容易的多。 <br />    由于Java最初是为控制电子产品设计的，因此它必须简单明了。为了保证这种简单性，Java去掉了C++中许多复杂的、冗余的、有二义性的概念，例如操作符重载、多继承、数据类型自动转换等。为了将程序员从复杂的内存管理的负担中解脱出来，同时也是为了减少错误，Java使用了自动内存垃圾收集机制，程序员只要在需要的时候申请即可，不需要释放,而由Java自己来收集、释放内存中的无用的块。<br />    与C++相比，Java有着更强的面向对象特性，是一种比较纯粹的面向对象语言。一般我们使用的一些所谓的面向对象的编程语言，如C++，Object Pascal等，实际上都是一种混合型的语言，即在过程式的语言中加上面向对象的扩展。在Java中，几乎万物皆对象，就连一些基本数据类型，如整型、字符型、浮点型等，在Java中都可以作为对象处理。Java的面向对象特性几乎可以与Smalltalk媲美，但是其适用于分布式计算环境的特性却远远超过了Smalltalk。<br />   Java是一种支持分布式操作的程序设计语言。使用Java提供的URL类，用户可以象访问本地文件一样访问网络上的对象，使用非常方便。在客户机/服务器的模式下，Java还可以将运算从服务器端分散到客户端，提高系统的效率，避免了服务器的瓶颈制约。Java的网络类库支持分布式的编程。Socket类提供可靠的流式网络的连接，支持TCP/IP协议。通过编写协议句柄，程序员还可以扩充Java支持的协议集合。<br /><br />Java提供非常有效的安全控制。由于Java应用于网络程序的开发，因而安全性变的至关重要。因为Java小程序需要下载到客户端解释执行，所以，如果没有安全控制，就会给一些网络黑客以可乘之机，这对用户来说是非常危险的。所幸的是，Java的安全机制可以有效的防止病毒程序的产生、下载程序对本地文件系统的破坏，以及网络黑客窃取密码和入侵。<br /><br />Java是一种非常健壮的语言。因为在Java中使用了以下手段：<br /><br />不支持指针。在C++程序中，指针的错误使用通常的程序中BUG的元凶。在Java中彻底去掉了指针，杜绝了内存的非法访问，从而保证了程序的可靠性。<br />强类型语言。<br /><br />自动内存垃圾收集机制。Java自动收集无用的内存单元，进而防止了由于内存泄漏导致的动态内存分配问题。<br /><br />完善的异常处理机制，既简化了错误处理任务和恢复，也增加了程序的可读性。<br /><br />Java具有非常好的平台无关性和可移植性。因为Java最初是为对电子产品编程而设计的，所以它具有完美的平台无关性。它使用一种与平台无关的代码──字节码，而不是通常的特定机器上的机器码，由平台上的Java虚拟机中的Java解释器解释执行。Java虚拟机是免费的，在许多平台上都有。<br /><br />Java提供了良好的可移植性。使用Java作为编程语言，只要进行一次程序开发工作，所开发的程序不需要经过任何改动，便能在各种平台上运行。Java使用两种方法使Java的应用程序不依赖与具体的系统：<br /><br />采用基于国际标准的数据类型。Java的原始数据类型在任何机器上都是一样的，例如整型总是32位，长整型总是64位等。<br /><br />提供了一个用于访问底层操作系统功能的可扩展类库。<br /><br />Java是一种高性能的语言。“鱼与熊掌不可兼得”，通常，健壮性、安全性、平台无关性、可移植性等方面的提高总是要以牺牲性能为代价的。Java也不例外，Java的内存管理增加了运行时系统的复杂性，因为Java运行时系统必须内嵌一个内存管理模块；同样，Java程序的解释执行的效率也要低于直接执行编译后的源码的效率。但是Java采用了一些很好的措施来弥补这些性能上的差距：<br /><br />生成高效的字节码。Java字节码的设计充分考虑了性能的因素，字节码的格式简单，解释器可以生成高效的机器码。<br /><br />提供了即时编译和嵌入C代码的可选措施。即时编译是指在运行时把字节码编译成机器码。支持多线程。Java提供了对多线程的语言级的接口，而且Java环境本身就是多线程的。<br /><br /><br />Java对多线程有良好的支持。多线程技术可以提高程序执行的并发度，提高图形用户界面的交互性能。Java提供了语言内置的多线程控制，简化了多线程应用程序的开发，还支持线程的同步控制。<br /><br />Java是一种动态的语言。动态特性是面向对象特性的一个延伸，它使得程序能够适应不断变化的执行环境。Java的动态性主要表现在以下几个方面：<br /><br />Java的类有运行时的表示，这样，即使在运行时刻，程序也能辨别类之间的关系和类型信息，可以动态的从本地或网上把一个类链接到运行系统中去。<br /><br />后期联编。Java的类在运行过程中动态的装载，因此，Java可以在分布式的环境中动态的维护应用程序和Java类库之间的一致性。当类库升级后，应用程序无需重新编译，也一样可以利用新类库中新增的功能。<br /><br />支持动态数据类型和动态协议。通过编写协议句柄，Java可以支持新的、自定义的传输协议，编写内容句柄，可以支持新的数据类型。<br /><br />至于应用，就不必说了！<br /><img src ="http://www.blogjava.net/buaacaptain/aggbug/48860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/buaacaptain/" target="_blank">船长</a> 2006-05-30 00:51 <a href="http://www.blogjava.net/buaacaptain/archive/2006/05/30/48860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>