﻿<?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-欢迎来到小小家院-文章分类-JAVA使用技巧</title><link>http://www.blogjava.net/wangxq/category/17203.html</link><description>共同努力,共造辉煌!</description><language>zh-cn</language><lastBuildDate>Thu, 29 Mar 2007 18:48:36 GMT</lastBuildDate><pubDate>Thu, 29 Mar 2007 18:48:36 GMT</pubDate><ttl>60</ttl><item><title>（转）java实现对文件的各种操作 </title><link>http://www.blogjava.net/wangxq/articles/107127.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 29 Mar 2007 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/107127.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/107127.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/107127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/107127.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/107127.html</trackback:ping><description><![CDATA[
		<div class="postTitle" twffan="done">
				<a href="http://blog.csdn.net/jkl_123/archive/2006/10/13/1333458.aspx">
						<img height="13" src="http://blog.csdn.net/images/zhuan.gif" width="15" border="0" twffan="done" /> java实现对文件的各种操作</a>
		</div>
		<div class="postText" twffan="done">  
<div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 1</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。新建目录</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html;charset=gb2312"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%</strong><br /><strong>String filePath="c:/aaa/";</strong><br /><strong>filePath=filePath.toString();//</strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">中文转换</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>java.io.File myFilePath=new java.io.File(filePath);</strong><br /><strong>if(!myFilePath.exists())</strong><br /><strong>myFilePath.mkdir();</strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">  2</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。新建文件</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html;charset=gb2312"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.io.*" %&gt;</strong><br /><strong>&lt;%</strong><br /><strong>String filePath="c:/</strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">哈哈</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">.txt";</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>filePath=filePath.toString();</strong><br /><strong>File myFilePath=new File(filePath);</strong><br /><strong>if(!myFilePath.exists())</strong><br /><strong>myFilePath.createNewFile();</strong><br /><strong>FileWriter resultFile=new FileWriter(myFilePath);</strong><br /><strong>PrintWriter myFile=new PrintWriter(resultFile);</strong><br /><strong>String strContent = "</strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">中文测试</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">".toString();</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>myFile.println(strContent);</strong><br /><strong>resultFile.close();</strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 3</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。删除文件</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html;charset=gb2312"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%</strong><br /><strong>String filePath="c:/</strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">支出证明单</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">.xls";</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>filePath=filePath.toString();</strong><br /><strong>java.io.File myDelFile=new java.io.File(filePath);</strong><br /><strong>myDelFile.delete();</strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 4</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。文件拷贝</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html; charset=gb2312" %&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.io.*" %&gt;</strong><br /><strong>&lt;%</strong><br /><strong>int bytesum=0;</strong><br /><strong>int byteread=0; </strong><br /></span></strong><strong><u><span style="FONT-SIZE: 10.5pt; COLOR: blue; LINE-HEIGHT: 150%" twffan="done"><a href="file://读/">file://<span twffan="done">读</span></a></span></u></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">到流中</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>InputStream inStream=new FileInputStream("c:/aaa.doc");</strong><br /><strong>FileOutputStream fs=new FileOutputStream( "d:/aaa.doc");byte[]  buffer =new  byte[1444];</strong><br /><strong>int length;</strong><br /><strong>while ((byteread=inStream.read(buffer))!=-1)</strong><br /><strong> {</strong><br /><strong>   out.println("&lt;DT&gt;&lt;B&gt;"+byteread+"&lt;/B&gt;&lt;/DT&gt;");</strong><br /><strong>   bytesum+=byteread;</strong><br /><strong>   System.out.println(bytesum);</strong><br /><strong>   fs.write(buffer,0,byteread);</strong><br /><strong> } </strong><br /><strong>inStream.close(); </strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 5</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。整个文件夹拷贝</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html;charset=gb2312"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.io.*" %&gt;</strong><br /><strong>&lt;%String url1="C:/aaa";</strong><br /><strong>  String url2="d:/java/";</strong><br /><strong>  (new File(url2)).mkdirs();</strong><br /><strong> File[] file=(new File(url1)).listFiles();</strong><br /><strong> for(int i=0;i&lt;file.length;i++){</strong><br /><strong>  if(file[i].isFile()){</strong><br /><strong>   file[i].toString();</strong><br /><strong>   FileInputStream input=new FileInputStream(file[i]);</strong><br /><strong>   FileOutputStream output=new FileOutputStream(url2+"/"+(file[i].getName()).toString());</strong><br /><strong>   byte[] b=new byte[1024*5];</strong><br /><strong>    int len;</strong><br /><strong>    while((len=input.read(b))!=-1){</strong><br /><strong>    output.write(b,0,len);</strong><br /><strong>    }</strong><br /><strong>    output.flush();</strong><br /><strong>    output.close();</strong><br /><strong>    input.close();</strong><br /><strong>  }</strong><br /><strong> }</strong><br /><strong>%&gt; </strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 6</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。文件下载</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html; charset=gb2312" %&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.io.*" %&gt;</strong><br /><strong>&lt;%</strong><br /><strong>  String fileName = "zsc104.swf".toString();</strong><br /><strong><a href="file://读/">//<span twffan="done">读</span></a></strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">到流中</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>InputStream inStream=new FileInputStream("c:/zsc104.swf");</strong><br /><strong><a href="file://设/">//<span twffan="done">设</span></a></strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">置输出的格式</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>  response.reset(); </strong><br /><strong>  response.setContentType("bin");</strong><br /><strong>  response.addHeader("Content-Disposition","attachment; filename=\"" + fileName + "\"");</strong><br /><strong><a href="file://循/">//<span twffan="done">循</span></a></strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">环取出流中的数据</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>  byte[] b = new byte[100]; </strong><br /><strong>  int len; </strong><br /><strong>  while((len=inStream.read(b)) &gt;0) </strong><br /><strong>  response.getOutputStream().write(b,0,len);  </strong><br /><strong>  inStream.close(); </strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 7</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。数据库字段中的文件下载</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page contentType="text/html; charset=gb2312" %&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.sql.*"%&gt;</strong><br /><strong>&lt;%@ page import="java.lang.*" %&gt;</strong><br /><strong>&lt;%@ page import="java.io.*" %&gt;</strong><br /><strong>&lt;%@ page import="com.jspsmart.upload.*" %&gt;</strong><br /><strong>&lt;%@ page import="DBstep.iDBManager2000.*"%&gt;</strong><br /><strong>&lt;%</strong><br /><strong>int bytesum=0;</strong><br /><strong>int byteread=0;</strong><br /><strong><a href="file://打/">//<span twffan="done">打</span></a></strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">开数据库</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>ResultSet result=null;</strong><br /><strong>String Sql=null;</strong><br /><strong>PreparedStatement prestmt=null; </strong><br /><strong>DBstep.iDBManager2000 DbaObj=new DBstep.iDBManager2000();</strong><br /><strong>DbaObj.OpenConnection();</strong><br /><strong><a href="file://取/">//<span twffan="done">取</span></a></strong></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">得数据库中的数据</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>Sql="select  *  from  t_local_zhongzhuan ";</strong><br /><strong>result=DbaObj.ExecuteQuery(Sql);</strong><br /><strong>result.next();</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><a href="file://将/">file://<span twffan="done">将</span></a></span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">数据库中的数据读到流中</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>InputStream inStream=result.getBinaryStream("content"); </strong><br /><strong>FileOutputStream fs=new FileOutputStream( "c:/dffdsafd.doc");</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">byte[]  buffer =new  byte[1444];</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>int length;</strong><br /><strong>while ((byteread=inStream.read(buffer))!=-1)</strong><br /><strong>  {</strong><br /><strong>     out.println("&lt;DT&gt;&lt;B&gt;"+byteread+"&lt;/B&gt;&lt;/DT&gt;");</strong><br /><strong>     bytesum+=byteread;</strong><br /><strong>     System.out.println(bytesum);</strong><br /><strong>     fs.write(buffer,0,byteread);</strong><br /><strong>     }</strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 8</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。把网页保存成文件</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page import="java.text.*"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.util.*"%&gt;</strong><br /><strong>&lt;%@ page import="java.io.*"%&gt;</strong><br /><strong>&lt;%@ page import="java.net.*"%&gt;</strong><br /><strong>&lt;%</strong><br /><strong> URL stdURL = null;</strong><br /><strong> BufferedReader stdIn = null;</strong><br /><strong> PrintWriter stdOut = null;</strong><br /><strong> try {</strong><br /><strong>  stdURL = new URL("http://www.163.com");</strong><br /><strong> }</strong><br /><strong> catch (MalformedURLException e) {</strong><br /><strong>   throw e;</strong><br /><strong> }</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">try {</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>   stdIn = new BufferedReader(new InputStreamReader(stdURL.openStream()));</strong><br /><strong>   stdOut = new PrintWriter(new BufferedWriter(new FileWriter("c:/163.html")));</strong><br /><strong> }</strong><br /><strong> catch (IOException e) {</strong><br /><strong> }</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> /***</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">把</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">URL</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">指定的页面以流的形式读出，写成指定的文件</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">***/</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong> try {</strong><br /><strong>   String strHtml = "";</strong><br /><strong>   while((strHtml = stdIn.readLine())!=null) {</strong><br /><strong>   stdOut.println(strHtml);</strong><br /><strong>   }</strong><br /><strong> }</strong><br /><strong> catch (IOException e) {</strong><br /><strong>   throw e;</strong><br /><strong> }</strong><br /><strong> finally {</strong><br /><strong>   try {</strong><br /><strong>     if(stdIn != null)</strong><br /><strong>       stdIn.close();</strong><br /><strong>     if(stdOut != null)</strong><br /><strong>       stdOut.close();</strong><br /><strong>   }</strong><br /><strong>   catch (Exception e) {</strong><br /><strong>     System.out.println(e);</strong><br /><strong>   }</strong><br /><strong> }</strong><br /><strong>%&gt;</strong></span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"> 9</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">。直接下载网上的文件</span></strong></div><div style="BACKGROUND: white; LINE-HEIGHT: 150%" twffan="done"><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done">&lt;%@ page import="java.io.*"%&gt;</span></strong><strong><span style="FONT-SIZE: 10.5pt; COLOR: #333333; LINE-HEIGHT: 150%" twffan="done"><br /><strong>&lt;%@ page import="java.net.*"%&amp;</strong></span></strong></div></div>
<img src ="http://www.blogjava.net/wangxq/aggbug/107127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2007-03-29 09:42 <a href="http://www.blogjava.net/wangxq/articles/107127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>File的加锁</title><link>http://www.blogjava.net/wangxq/articles/47569.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Tue, 23 May 2006 00:54:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/47569.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/47569.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/47569.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/47569.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/47569.html</trackback:ping><description><![CDATA[有时候，我们需要以独占的方式访问某个文件，因此，需要在打开文件时，对文件上锁，以防其他人或进程也访问该文件。Java本身提供了俩种锁文件的方式：<br />方式一：用RandomAccessFile类操作文件<br />RandomAccessFile的open方法，提供了参数，实现以独占的方式打开文件：<br />new RandomAccessFile(file, "rws")<br />其中的“rws”参数中，rw代表读写方式，s代表同步方式，也就是锁。这种方式打开的文件，就是独占方式。<br /><br />方式二：用文件通道（FileChannel）的锁功能<br /><br />如：<br /><br />RandomAccessFile raf = new RandomAccessFile(new File("c:\\test.txt"), "rw");<br /><br />FileChannel fc = raf.getChannel();<br />FileLock fl = fc.tryLock();<br /><br />if (fl.isValid()) {<br />System.out.println("get the lock!");<br /><br />但这俩种方式，都只能通过RandomAccessFile访问文件，如果只能通过InputStream来访问文件，如用DOM分析XML文件，怎么办呢？<br />其实，FileInputStream对象，也提供了getChannel方法，只是缺省的getChannel方法，不能锁住文件，所以，如果需要，就必须自己重写一个getChannel方法，如：<br />public FileChannel getChannel(FileInputStream fileIn, FileDescriptor fd) {<br />FileChannel channel = null;<br />synchronized (fileIn) {<br />channel = FileChannelImpl.open(fd, true, true, fileIn);<br />return channel;<br />}<br />}<br /><br />其实，主要是打开文件的第三个参数控制了对文件的操作模式，如果设置为false，就不能锁住文件，缺省的getChannel方法，就是false，因此，不能锁住文件。<br /><img src ="http://www.blogjava.net/wangxq/aggbug/47569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-05-23 08:54 <a href="http://www.blogjava.net/wangxq/articles/47569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse技巧</title><link>http://www.blogjava.net/wangxq/articles/47057.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Fri, 19 May 2006 06:43:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/47057.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/47057.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/47057.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/47057.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/47057.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<b>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">from：<a href="http://www.99college.com/ReadNews.asp?NewsID=6628&amp;BigClassName=JAVA&amp;SmallClassName=%E5%B7%A5%E5%85%B7%E6%8C%87%E5%8D%97&amp;SpecialID=22">http://www.99college.com/ReadNews.asp?NewsID=6628&amp;BigClassName=JAVA&amp;SmallClassName=%E5%B7%A5%E5%85%B7%E6%8C%87%E5%8D%97&amp;SpecialID=22</a><br />热键篇：<span lang="EN-US" twffan="done"><br /></span></span>
				</b>
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">Template</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">：<span lang="EN-US" twffan="done">Alt + /<br /></span>修改处：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;</span>工作台<span lang="EN-US" twffan="done">-&gt;</span>按键<span lang="EN-US" twffan="done">-&gt;</span>编辑<span lang="EN-US" twffan="done">-&gt;</span>内容辅助。<span lang="EN-US" twffan="done"><br /></span>个人习惯：<span lang="EN-US" twffan="done">Shift+SPACE(</span>空白<span lang="EN-US" twffan="done">)</span>。<span lang="EN-US" twffan="done"><br /></span>简易说明：编辑程序代码时，打<span lang="EN-US" twffan="done">sysout +Template</span>启动键，就<span lang="EN-US" twffan="done"><br /></span>会自动出现：<span lang="EN-US" twffan="done">System.out.println(); </span>。<span lang="EN-US" twffan="done"><br /></span><b>设定<span lang="EN-US" twffan="done">Template</span>的格式：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;Java-&gt;</span>编辑器<span lang="EN-US" twffan="done">-&gt;</span>模板。</b><span lang="EN-US" twffan="done"><br /><br /></span>程序代码自动排版：<span lang="EN-US" twffan="done">Ctrl+Shift+F<br /></span>修改处：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;</span>工作台<span lang="EN-US" twffan="done">-&gt;</span>按键<span lang="EN-US" twffan="done">-&gt;</span>程序代码<span lang="EN-US" twffan="done">-&gt;</span>格式。<span lang="EN-US" twffan="done"><br /></span>个人习惯：<span lang="EN-US" twffan="done">Alt+Z</span>。<span lang="EN-US" twffan="done"><br /></span>自动排版设定：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;Java-&gt;</span>程序代码格式制作程序。<span lang="EN-US" twffan="done"><br /></span>样式页面<span lang="EN-US" twffan="done">-&gt;</span>将插入<span lang="EN-US" twffan="done">tab(</span>而非空格键<span lang="EN-US" twffan="done">)</span>以内缩，该选项取消勾选<span lang="EN-US" twffan="done"><br /></span>，下面空格数目填<span lang="EN-US" twffan="done">4</span>，这样在自动编排时会以空格<span lang="EN-US" twffan="done">4</span>作缩排。<span lang="EN-US" twffan="done"><br /><br /></span>快速执行程序：<span lang="EN-US" twffan="done">Ctrl + F11<br /></span>个人习惯：<span lang="EN-US" twffan="done">ALT+X<br /></span>修改处：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;</span>工作台<span lang="EN-US" twffan="done">-&gt;</span>按键<span lang="EN-US" twffan="done">-&gt;</span>执行<span lang="EN-US" twffan="done">-&gt;</span>启动前一次的启动作业。<span lang="EN-US" twffan="done"><br /></span>简易说明：第一次执行时，它会询问您执行模式，<span lang="EN-US" twffan="done"><br /></span>设置好后，以后只要按这个热键，它就会快速执行。<span lang="EN-US" twffan="done"><br /><alt+z(>&lt; SPAN&gt;排版完<span lang="EN-US" twffan="done">)</span>、<span lang="EN-US" twffan="done">ATL+X(</span>执行<span lang="EN-US" twffan="done">)&gt;..</span>我觉得很顺手<span lang="EN-US" twffan="done">^___^<br /><br /></span>自动汇入所需要的类别：<span lang="EN-US" twffan="done">Ctrl+Shift+O<br /></span>简易说明：<span lang="EN-US" twffan="done"><br /></span>假设我们没有<span lang="EN-US" twffan="done">Import</span>任何类别时，当我们在程序里打入：</alt+z(></span><span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left">
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">BufferedReader buf =<br />new BufferedReader(new InputStreamReader(System.in));</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">此时<span lang="EN-US" twffan="done">Eclipse</span>会警示说没有汇入类别，这时我们只要按下<span lang="EN-US" twffan="done">Ctrl+Shift+O<br /></span>，它就会自动帮我们<span lang="EN-US" twffan="done">Import</span>类别。<span lang="EN-US" twffan="done"><br /><br /></span>查看使用类别的原始码：<span lang="EN-US" twffan="done">Ctrl+</span>鼠标左键点击<span lang="EN-US" twffan="done"><br /></span>简易说明：可以看到您所使用类别的原始码。<span lang="EN-US" twffan="done"><br /><br /></span>将选取的文字批注起来：<span lang="EN-US" twffan="done">Ctrl+/<br /></span>简易说明：<span lang="EN-US" twffan="done">Debug</span>时很方便。<span lang="EN-US" twffan="done"><br /></span>修改处：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;</span>工作台<span lang="EN-US" twffan="done">-&gt;</span>按键<span lang="EN-US" twffan="done">-&gt;</span>程序代码<span lang="EN-US" twffan="done">-&gt;</span>批注<span lang="EN-US" twffan="done"><br /><br /></span>视景切换：<span lang="EN-US" twffan="done">Ctrl+F8<br /></span>个人习惯：<span lang="EN-US" twffan="done">Alt+S</span>。<span lang="EN-US" twffan="done"><br /></span>修改处：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;</span>工作台<span lang="EN-US" twffan="done">-&gt;</span>按键<span lang="EN-US" twffan="done">-&gt;</span>窗口<span lang="EN-US" twffan="done">-&gt;</span>下一个视景。<span lang="EN-US" twffan="done"><br /></span>简易说明：可以方便我们快速切换编辑、除错等视景。<span lang="EN-US" twffan="done"><br /><br /></span><b>密技篇：</b><span lang="EN-US" twffan="done"><br /></span>一套<span lang="EN-US" twffan="done">Eclipse</span>可同时切换，英文、繁体、简体显示：<span lang="EN-US" twffan="done"><br />1.</span>首先要先安装完中文化包。<span lang="EN-US" twffan="done"><br />2.</span>在桌面的快捷方式后面加上参数即可，<span lang="EN-US" twffan="done"><br /></span>英文<span lang="EN-US" twffan="done">-&gt; -nl "zh_US"<br /></span>繁体<span lang="EN-US" twffan="done">-&gt; -nl "zh_TW"<br /></span>简体<span lang="EN-US" twffan="done">-&gt; -nl "zh_CN"</span>。<span lang="EN-US" twffan="done"><br />(</span>其它语系以此类推<span lang="EN-US" twffan="done">)<br /></span>像我<span lang="EN-US" twffan="done">2.1.2</span>中文化后，我在我桌面的<span lang="EN-US" twffan="done">Eclipse</span>快捷方式加入参数<span lang="EN-US" twffan="done">-n1 "zh_US"</span>。<span lang="EN-US" twffan="done"><br />"C:\Program Files\eclipse\eclipse.exe" -n "zh_US"<br /></span>接口就会变回英文语系噜。<span lang="EN-US" twffan="done"><br /><br /></span>利用<span lang="EN-US" twffan="done">Eclipse</span>，在<span lang="EN-US" twffan="done">Word</span>编辑文书时可不必将程序代码重新编排：<span lang="EN-US" twffan="done"><br /></span>将<span lang="EN-US" twffan="done">Eclipse</span>程序编辑区的程序代码整个复制下来<span lang="EN-US" twffan="done">(Ctrl+C)</span>，直接贴<span lang="EN-US" twffan="done">(Ctrl+V)</span>到<span lang="EN-US" twffan="done"><br />Word</span>或<span lang="EN-US" twffan="done">WordPad</span>上，您将会发现在<span lang="EN-US" twffan="done">Word</span>里的程序代码格式，跟<span lang="EN-US" twffan="done">Eclipse<br /></span>所设定的完全一样，包括字型、缩排、关键词颜色。我曾试过<span lang="EN-US" twffan="done">JBuilder<br /></span>、<span lang="EN-US" twffan="done">GEL</span>、<span lang="EN-US" twffan="done">NetBeans...</span>使用复制贴上时，只有缩排格式一样，字型、颜<span lang="EN-US" twffan="done"><br /></span>色等都不会改变。<span lang="EN-US" twffan="done"><br /><br /></span><b>外挂篇：</b><span lang="EN-US" twffan="done"><br /></span>外挂安装：将外挂包下载回来后，将其解压缩后，您会发现<span lang="EN-US" twffan="done">features</span>、<span lang="EN-US" twffan="done"><br />plugins</span>这<span lang="EN-US" twffan="done">2</span>个数据夹，将里面的东西都复制或移动到<span lang="EN-US" twffan="done">Eclipse</span>的<span lang="EN-US" twffan="done">features<br /></span>、<span lang="EN-US" twffan="done">plugins</span>数据夹内后，重新启动<span lang="EN-US" twffan="done">Eclipse</span>即可。<span lang="EN-US" twffan="done"><br /><br /></span>让<span lang="EN-US" twffan="done">Eclipse</span>可以像<span lang="EN-US" twffan="done">JBuilderX</span>一样使用拖拉方式建构<span lang="EN-US" twffan="done">GUI</span>的外挂：<span lang="EN-US" twffan="done"><br />1.Jigloo SWT/Swing GUI Builder </span>：<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://cloudgarden.com/jigloo/index.html" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://cloudgarden.com/jigloo/index.html</span>
						</a>
						<br />
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">下载此版本：<span lang="EN-US" twffan="done">Jigloo plugin for Eclipse (using Java 1.4 or 1.5)<br /></span>安装后即可由档案<span lang="EN-US" twffan="done">-&gt;</span>新建<span lang="EN-US" twffan="done">-&gt;</span>其它<span lang="EN-US" twffan="done">-&gt;GUI Form</span>选取要建构的<span lang="EN-US" twffan="done">GUI</span>类型。<span lang="EN-US" twffan="done"><br /><br />2.Eclipse Visual Editor Project</span>：<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://www.eclipse.org/vep/" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://www.eclipse.org/vep/</span>
						</a>
						<br />
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">点选下方<span lang="EN-US" twffan="done">Download Page</span>，再点选<span lang="EN-US" twffan="done">Latest Release 0.5.0</span>进入下载。<span lang="EN-US" twffan="done"><br /></span>除了<span lang="EN-US" twffan="done">VE-runtime-0.5.0.zip</span>要下载外，以下这<span lang="EN-US" twffan="done">2</span>个也要：<span lang="EN-US" twffan="done"><br />EMF build 1.1.1: (build page) (download zip) <br />GEF Build 2.1.2: (build page) (download zip) <br /><br />3.0 M8</span>版本，请下载：<span lang="EN-US" twffan="done"><br />EMF build I200403250631<br />GEF Build I20040330<br />VE-runtime-1.0M1<br /><br /></span>安装成功后，便可由<span lang="EN-US" twffan="done">File-&gt;New-&gt;Visual Class</span>开始<span lang="EN-US" twffan="done">UI</span>设计。<span lang="EN-US" twffan="done"><br /></span>安装成功后，即可由新建<span lang="EN-US" twffan="done">-&gt;Java-&gt;AWT</span>与<span lang="EN-US" twffan="done">Swing</span>里选择<span lang="EN-US" twffan="done"><br /></span>所要建构的<span lang="EN-US" twffan="done">GUI</span>类型开始进行设计。<span lang="EN-US" twffan="done">VE</span>必须配合着对应<span lang="EN-US" twffan="done"><br /></span>版本，才能正常使用，否则即使安装成功，使用上仍会<span lang="EN-US" twffan="done"><br /></span>有问题。<span lang="EN-US" twffan="done"><br /><br /></span>使用<span lang="EN-US" twffan="done">Eclipse</span>来开发<span lang="EN-US" twffan="done">JSP</span>程序：<span lang="EN-US" twffan="done"><br /></span>外挂名称：<span lang="EN-US" twffan="done">lomboz(</span>下载页面<span lang="EN-US" twffan="done">)<br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://forge.objectweb.org/project/showfiles.php?group_id=97" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://forge.objectweb.org/project/showfiles.php?group_id=97</span>
						</a>
						<br />
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">请选择适合自己版本的<span lang="EN-US" twffan="done">lomboz</span>下载，<span lang="EN-US" twffan="done">lomboz.212.p1.zip</span>表示<span lang="EN-US" twffan="done">2.1.2</span>版，<span lang="EN-US" twffan="done"><br />lomboz.3m7.zip</span>表示<span lang="EN-US" twffan="done">M7</span>版本<span lang="EN-US" twffan="done">....</span>以此类推。<span lang="EN-US" twffan="done"><br />lomboz</span>安装以及设置教学：<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040213.html" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">Eclipse</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发JSP-</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">教学文件</span>
								</span>
						</a>
						<br />
						<br />
						<b>
								<span style="COLOR: black" twffan="done">Java</span>
						</b>
				</span>
				<b>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">转<span lang="EN-US" twffan="done">exe</span>篇：</span>
				</b>
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<br />
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">实现方式：<span lang="EN-US" twffan="done">Eclipse</span>搭配<span lang="EN-US" twffan="done">JSmooth(</span>免费<span lang="EN-US" twffan="done">)</span>。<span lang="EN-US" twffan="done"><br />1.</span>先由<span lang="EN-US" twffan="done">Eclipse</span>制作包含<span lang="EN-US" twffan="done">Manifest</span>的<span lang="EN-US" twffan="done">JAR</span>。<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://www.javaworld.com.tw/jute/post/view?bid=10&amp;id=38974&amp;sty=3&amp;keywords=%BD%D0%B0%DDEcilpse+IDE%A6%B3%BB%73%A7%40JAR%C0%C9%AA%BA%A5%5C%AF%E0%B6%DC%A1%48" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">制作教学</span>
								</span>
						</a>
						<br />
						<span style="COLOR: black" twffan="done">2.</span>
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">使用<span lang="EN-US" twffan="done">JSmooth</span>将做好的<span lang="EN-US" twffan="done">JAR</span>包装成<span lang="EN-US" twffan="done">EXE</span>。<span lang="EN-US" twffan="done"><br />JSmooth</span>下载页面：<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://jsmooth.sourceforge.net/index.php" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://jsmooth.sourceforge.net/index.php</span>
						</a>
						<br />
						<span style="COLOR: black" twffan="done">3.</span>
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">制作完成的<span lang="EN-US" twffan="done">exe</span>文件，可在有装置<span lang="EN-US" twffan="done">JRE</span>的<span lang="EN-US" twffan="done">Windows</span>上执行。<span lang="EN-US" twffan="done"><br /><br /><b>Eclipse-Java</b></span><b>编辑器最佳设定：</b><span lang="EN-US" twffan="done"><br /></span>编辑器字型设定：工作台<span lang="EN-US" twffan="done">-&gt;</span>字型<span lang="EN-US" twffan="done">-&gt;Java</span>编辑器文字字型。<span lang="EN-US" twffan="done"><br />(</span>建议设定<span lang="EN-US" twffan="done">Courier New -regular 10)<br /><br /></span>编辑器相关设定：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;Java-&gt;</span>编辑器<span lang="EN-US" twffan="done"><br /><br /></span>外观：显示行号、强调对称显示的方括号、强调显示现行行、<span lang="EN-US" twffan="done"><br /></span>显示打印边距，将其勾选，<span lang="EN-US" twffan="done">Tab</span>宽度设<span lang="EN-US" twffan="done">4</span>，打印编距字段设<span lang="EN-US" twffan="done">80</span>。<span lang="EN-US" twffan="done"><br /></span>程序代码协助：采预设即可。<span lang="EN-US" twffan="done"><br /></span>语法：可设定关键词、字符串等等的显示颜色。<span lang="EN-US" twffan="done"><br /></span>附注：采预设即可。<span lang="EN-US" twffan="done"><br /></span>输入：全部字段都勾选。<span lang="EN-US" twffan="done"><br /></span>浮动说明：采预设即可。<span lang="EN-US" twffan="done"><br /></span>导览：采预设即可。<span lang="EN-US" twffan="done"><br /><br /></span><b>使自动排版排出来的效果，最符合<span lang="EN-US" twffan="done">Java</span>设计惯例的设定：</b><span lang="EN-US" twffan="done"><br /></span>自动排版设定：窗口<span lang="EN-US" twffan="done">-&gt;</span>喜好设定<span lang="EN-US" twffan="done">-&gt;Java-&gt;</span>程序代码制作格式。<span lang="EN-US" twffan="done"><br /><br /></span>换行：全部不勾选。<span lang="EN-US" twffan="done"><br /></span>分行：行长度上限设：<span lang="EN-US" twffan="done">80</span>。<span lang="EN-US" twffan="done"><br /></span>样式：只将强制转型后插入空白勾选。<span lang="EN-US" twffan="done"><br /></span>内缩空格数目：设为<span lang="EN-US" twffan="done">4</span>。<span lang="EN-US" twffan="done"><br /><br /><b>Eclipse</b></span><b>的教学文件：</b><span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://www.javaworld.com.tw/jute/post/view?bid=10&amp;id=53905&amp;sty=2" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">Eclipse 3.0</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">系列热键表 - </span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中英对照解说版 (by sungo)</span>
								</span>
						</a>
						<span style="COLOR: black" twffan="done">~New~<br /></span>
						<a href="http://www.javaworld.com.tw/jute/post/view?bid=10&amp;id=53262&amp;sty=1&amp;tpg=1&amp;age=0" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">Window+GCC+CDT</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">用Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发C</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">、C++ (by sungo)</span>
								</span>
						</a>
						<span style="COLOR: black" twffan="done">~New~<br /><br /></span>
				</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">其它：<span lang="EN-US" twffan="done"><br /></span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040303.html" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">扩充Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">的Java </span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发工具(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中文)</span>
								</span>
						</a>
						<br />
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040319.html" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">使用Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发J2EE </span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">应用程序(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中文)</span>
								</span>
						</a>
						<br />
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040305.html" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">使用Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">平台进行除错(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中文)</span>
								</span>
						</a>
						<br />
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040227.html" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">用Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">进行XML </span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中文)</span>
								</span>
						</a>
						<br />
						<a href="http://www2.tw.ibm.com/developerWorks/tutorial/content/web/20040207.html" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">开发Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">外挂程序(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">中文)</span>
								</span>
						</a>
						<br />
						<a href="http://www-106.ibm.com/developerworks/linux/library/os-i18n/?dwzone=linux" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">国际化您的Eclipse</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">外挂程序(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">英文)</span>
								</span>
						</a>
						<br />
						<a href="http://www-106.ibm.com/developerworks/java/library/os-swing/" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">将Swing</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">编辑器加入Eclipse(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">英文)</span>
								</span>
						</a>
						<br />
						<a href="http://www-106.ibm.com/developerworks/opensource/library/os-i18n2/?dwzone=opensource" target="_blank">
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">如何测试你的Eclipse plug-in</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">符合国际市场需求(</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">英文)</span>
								</span>
						</a>
						<br />
						<br />
						<b>
								<span style="COLOR: black" twffan="done">Eclipse</span>
						</b>
				</span>
				<b>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">的相关网站：</span>
				</b>
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<br />
				</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt" twffan="done">
						<a href="http://eclipse-plugins.2y.net/eclipse/index.jsp" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://eclipse-plugins.2y.net/eclipse/index.jsp</span>
						</a>
						<br />
						<a href="http://www.eclipseplugincentral.com/" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">http://www.eclipseplugincentral.com/</span>
						</a>
						<br />
						<a href="http://www-900.ibm.com/developerWorks/cn/cnpapers.nsf/java-papers-bytopic?OpenView&amp;Start=20&amp;Count=20&amp;Expand=20#20" target="_blank">
								<span style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">Eclipse</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">相关教学[</span>
								</span>
								<span lang="EN-US" style="COLOR: black; TEXT-DECORATION: none; text-underline: none" twffan="done">
										<span lang="EN-US" twffan="done">简体]</span>
								</span>
						</a>
						<span style="COLOR: black" twffan="done">
						</span>
						<o:p>
						</o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/wangxq/aggbug/47057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-05-19 14:43 <a href="http://www.blogjava.net/wangxq/articles/47057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用POI中的HSSF创建Excel文件</title><link>http://www.blogjava.net/wangxq/articles/46648.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Wed, 17 May 2006 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/46648.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/46648.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/46648.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/46648.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/46648.html</trackback:ping><description><![CDATA[
		<p>
				<font face="宋体,Arial, Helvetica, sans-serif" color="#000000" size="2">
				</font>
				<font face="黑体,Arial, Helvetica, sans-serif" color="#000000" size="4">使用POI中的HSSF创建Excel文件<br />from: <a href="http://www.cn-java.com/target/news.php?news_id=2510">http://www.cn-java.com/target/news.php?news_id=2510</a></font>
		</p>
		<p align="right">出处 CN-JAVA翻译： 孤魂一笑     </p>
		<p>
		</p>
		<hr noshade="" />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td valign="top" width="86%">作者:孤魂一笑(bingo_ge@hotmail.com) 日期：2003-05-05<br /><br />介绍:<br />Jakarta_POI 使用Java读写Excel(97-2002)文件，可以满足大部分的需要。<br />因为刚好有一个项目使用到了这个工具，花了点时间顺便翻译了一下POI本身<br />带的一个Guide.有一些节减和修改，希望给使用这个项目的人一些入门帮助。<br />POI 下面有几个自项目:HSSF用来实现Excel 的读写.以下是HSSF的主页<br />http://jakarta.apache.org/poi/hssf/index.html<br />下面的介绍是基于以下地址的翻译：<br />http://jakarta.apache.org/poi/hssf/quick-guide.html<br />目前的版本为1.51应该是很长时间之内的一个稳定版，但HSSF提供的Sample不是基于<br />1.51所写，所以使用的时候需要适当的注意.<br />其实POI下面的几个子项目侧重不同读写 Word 的HDF正在开发当中.<br />XML下的FOP(http://xml.apache.org/fop/index.html)<br />可以输出pdf文件，也是比较好的一个工具<br />目录:<br />创建一个workbook<br />创建一个sheet<br />创建cells<br />创建日期cells<br />设定单元格格式<br /><br />说明：<br />以下可能需要使用到如下的类<br />import org.apache.poi.hssf.usermodel.HSSFCell;<br />import org.apache.poi.hssf.usermodel.HSSFCellStyle;<br />import org.apache.poi.hssf.usermodel.HSSFDataFormat;<br />import org.apache.poi.hssf.usermodel.HSSFFont;<br />import org.apache.poi.hssf.usermodel.HSSFRow;<br />import org.apache.poi.hssf.usermodel.HSSFSheet;<br />import org.apache.poi.hssf.usermodel.HSSFWorkbook;<br />import org.apache.poi.hssf.util.HSSFColor;<br /><br />创建workbook<br /><br />HSSFWorkbook wb = new HSSFWorkbook();<br />//使用默认的构造方法创建workbook<br />FileOutputStream fileOut = new FileOutputStream("workbook.xls");<br />//指定文件名<br />wb.write(fileOut);<br />//输出到文件<br />fileOut.close();<br /><br />创建一个sheet<br /><br />HSSFWorkbook wb = new HSSFWorkbook();<br />HSSFSheet sheet1 = wb.createSheet("new sheet");<br />//workbook创建sheet<br />HSSFSheet sheet2 = wb.createSheet("second sheet");<br />//workbook创建另外的sheet<br />FileOutputStream fileOut = new FileOutputStream("workbook.xls");<br />wb.write(fileOut);<br />fileOut.close();<br /><br />创建cells<br />HSSFWorkbook wb = new HSSFWorkbook();<br />HSSFSheet sheet = wb.createSheet("new sheet");<br />//注意以下的代码很多方法的参数是short 而不是int 所以需要做一次类型转换<br />HSSFRow row = sheet.createRow((short)0);<br />//sheet 创建一行<br />HSSFCell cell = row.createCell((short)0);<br />//行创建一个单元格<br />cell.setCellValue(1);<br />//设定单元格的值<br />//值的类型参数有多中double ,String ,boolean,<br />row.createCell((short)1).setCellValue(1.2);<br />row.createCell((short)2).setCellValue("This is a string");<br />row.createCell((short)3).setCellValue(true);<br /><br />// Write the output to a file<br />FileOutputStream fileOut = new FileOutputStream("workbook.xls");<br />wb.write(fileOut);<br />fileOut.close();<br /><br />创建日期cells<br />HSSFWorkbook wb = new HSSFWorkbook();<br />HSSFSheet sheet = wb.createSheet("new sheet");<br /><br />HSSFRow row = sheet.createRow((short)0);<br /><br />HSSFCell cell = row.createCell((short)0);<br />//设定值为日期<br />cell.setCellValue(new Date());<br /><br />HSSFCellStyle cellStyle = wb.createCellStyle();<br />//指定日期显示格式<br />cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));<br />cell = row.createCell((short)1);<br />cell.setCellValue(new Date());<br />//设定单元格日期显示格式<br />cell.setCellStyle(cellStyle);<br /><br />FileOutputStream fileOut = new FileOutputStream("workbook.xls");<br />wb.write(fileOut);<br />fileOut.close();<br /><br /><br />设定单元格格式<br />单元格格式的设定有很多形式包括单元格的对齐方式，内容的字体设置，<br />单元格的背景色等，因为形式比较多，只举一些例子.以下的例子在<br />POI1.5中可能会有所改变具体查看API.<br />..........<br />// Aqua background<br />HSSFCellStyle style = wb.createCellStyle();<br />//创建一个样式<br />style.setFillBackgroundColor(HSSFCellStyle.AQUA);<br />//设定此样式的的背景颜色填充<br />style.setFillPattern(HSSFCellStyle.BIG_SPOTS);<br /><br />//样式的填充类型。<br />//有多种式样如:<br />//HSSFCellStyle.BIG_SPOTS<br />//HSSFCellStyle.FINE_DOTS<br />//HSSFCellStyle.SPARSE_DOTS等<br />style.setAlignment(HSSFCellStyle.ALIGN_CENTER );<br />//居中对齐<br />style.setFillBackgroundColor(HSSFColor.GREEN.index);<br />//设定单元个背景颜色<br />style.setFillForegroundColor(HSSFColor.RED.index);<br />//设置单元格显示颜色<br />HSSFCell cell = row.createCell((short) 1);<br />cell.setCellValue("X");<br />cell.setCellStyle(style);<br /></td>
						</tr>
				</tbody>
		</table>参考：<a href="http://jakarta.apache.org/poi/hssf/quick-guide.html">http://jakarta.apache.org/poi/hssf/quick-guide.html</a><br /><br /><a href="http://spaces.msn.com/qiqiboy/blog/">http://spaces.msn.com/qiqiboy/blog/</a><img src ="http://www.blogjava.net/wangxq/aggbug/46648.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-05-17 16:46 <a href="http://www.blogjava.net/wangxq/articles/46648.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精品文章</title><link>http://www.blogjava.net/wangxq/articles/39384.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Wed, 05 Apr 2006 06:59:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/39384.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/39384.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/39384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/39384.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/39384.html</trackback:ping><description><![CDATA[
		<h1 class="ContentTitle">
				<strong>
						<font size="3">IBATIS—方便的Java开源持久层框架(O/R Mapping解决方案)</font>
				</strong>
				<a href="http://www.sman.cn/netfetch/article.asp?id=407">
						<br />
						<font size="3">http://www.sman.cn/netfetch/article.asp?id=407</font>
				</a>
				<strong>
				</strong>
		</h1>
		<h1 class="ContentTitle">
				<strong>
						<font size="3">什么是持久化和对象关系映射ORM技术</font>
				</strong>
		</h1>
		<p class="ContentTitle">
				<a href="http://www.volitation.net/Article/print.asp?SelectID=7">http://www.volitation.net/Article/print.asp?SelectID=7</a>
				<br />
				<font color="#0000ff">Hibernate技术主题</font>
				<br />
				<a href="http://www.csdn.net/subject/hibernate/">http://www.csdn.net/subject/hibernate/</a>
				<br />电子书<br /><a href="http://www.00083.com/Soft/ShowElite.asp?page=3">http://www.00083.com/Soft/ShowElite.asp?page=3</a><br /><font size="2"><strong>值得关注的持久化技术： hibernate <br /></strong><a href="http://www.huihoo.com/java/hibernate/index.htm"><strong>http://www.huihoo.com/java/hibernate/index.htm</strong></a><br /><br /><a class="postTitle2" id="viewpost1_TitleUrl" href="/anders0913/archive/2005/11/17/20185.html"><font size="3">java中的reflect机制!!!</font></a></font><font size="3"><br /><a href="/anders0913/archive/2005/11/17/20185.html">http://www.blogjava.net/anders0913/archive/2005/11/17/20185.html</a><br /><br />Java中的类反射机制<br /><a href="http://www.daima.com.cn/Info/121/Info36999/">http://www.daima.com.cn/Info/121/Info36999/</a><br /><br />Spring Framework 开发参考手册<br /><a href="http://www.jactiongroup.net/reference/html/index.html">http://www.jactiongroup.net/reference/html/index.html</a><br /><br /><strong>java.util包（二）</strong><br /><a href="http://teach.yuxinhuayuan.com/A200507/2005-07-24/165807.html">http://teach.yuxinhuayuan.com/A200507/2005-07-24/165807.html</a><br /><table cellspacing="0" cellpadding="0" width="740" border="0"><tbody><tr><td height="21">【JDK核心API】</td></tr></tbody></table><br /><a href="http://teach.yuxinhuayuan.com/Dev/Programme/Java/api/">http://teach.yuxinhuayuan.com/Dev/Programme/Java/api/</a><br />一个中年职场老油子对应届生谈招聘<br /><a href="http://blog.chinaitlab.com/user1/170241/archives/2006/50082.html">http://blog.chinaitlab.com/user1/170241/archives/2006/50082.html</a><br /><br /><strong>String类、StringBuffer类、Math类</strong><br /><a href="http://teach.yuxinhuayuan.com/A200507/2005-07-24/165769.html">http://teach.yuxinhuayuan.com/A200507/2005-07-24/165769.html</a><br /><strong>深入理解Collections API</strong><br /><a href="http://teach.yuxinhuayuan.com/A200507/2005-07-24/165747.html">http://teach.yuxinhuayuan.com/A200507/2005-07-24/165747.html</a><br /><strong>使用java.util.Timer</strong><br /><a href="http://teach.yuxinhuayuan.com/A200507/2005-07-24/165745.html">http://teach.yuxinhuayuan.com/A200507/2005-07-24/165745.html</a><br />初识Java内部类<br /><a href="http://www.frontfree.net/view/article_704.html">http://www.frontfree.net/view/article_704.html</a><br /><a class="singleposttitle" id="viewpost1_TitleUrl" href="/justinlei/articles/19873.html">JAVA内部类的基本特征</a><br /><a href="/justinlei/articles/19873.html">http://www.blogjava.net/justinlei/articles/19873.html</a><br /><strong>static内部类</strong><br /><a href="http://www.koyoyo8.com/phpcms/data/2006/0222/article_1118.htm">http://www.koyoyo8.com/phpcms/data/2006/0222/article_1118.htm</a><br /><a href="http://www.chinaspx.com/archive/java/15304.htm">http://www.chinaspx.com/archive/java/15304.htm</a><br /><br /><span id="ArticleTitle1_ArticleTitle1_lblTitle"><strong>正确使用ArrayList和LinkedList—性能的改进</strong></span> <br /><a href="http://dev.csdn.net/article/19/19387.shtm">http://dev.csdn.net/article/19/19387.shtm</a><br /><br />简述：<strong>ArrayList的查找速度明显优于LinkedList，但是LinkedList的插入，删除等操作的速度明显优于ArrayList；<br /></strong><font face="Verdana">HashMap 的查找速度高于</font><font face="Times New Roman"><strong>ArrayList；<br /><br /></strong><a href="http://www.jwit.edu.tw/~imitclub/javatech-2/JavaGossip-V2/JavaGossip-V2/JavaGossip2.htm"><strong>Java Gossip: LinkedList</strong></a><br /><a href="http://www.jwit.edu.tw/~imitclub/javatech-2/JavaGossip-V2/JavaGossip-V2/LinkedList.htm"><strong>http://www.jwit.edu.tw/~imitclub/javatech-2/JavaGossip-V2/JavaGossip-V2/LinkedList.htm</strong></a><br /><br />JAVA面试题-COREJAVA部分<br /><a href="http://www.513pc.net/vc/java/200603/182.html"><strong>http://www.513pc.net/vc/java/200603/182.html</strong></a><br /><a href="http://blog.tomxp.com/view/453.html#">全面接触Java集合框架[转] </a><br /><a href="http://blog.tomxp.com/view/453.html">http://blog.tomxp.com/view/453.html</a><br /></font></font></p>
		<h2 class="diaryTitle">java性能<br /><a href="http://bingchen2005.blogchina.com/3461257.html">http://bingchen2005.blogchina.com/3461257.html</a></h2>
		<p class="diaryTitle">
				<strong>
						<font color="#003399" size="5">Java线程总结</font>
				</strong>
				<br />
				<a href="http://java.chinaitlab.com/line/373702.html">http://java.chinaitlab.com/line/373702.html</a>
				<br />
		</p>
		<h1>
				<a href="http://feng5534.blog.my5q.com/index.php">JAVA学习</a>
				<br />
				<a href="http://feng5534.blog.my5q.com/">http://feng5534.blog.my5q.com/</a>
		</h1>
<img src ="http://www.blogjava.net/wangxq/aggbug/39384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-04-05 14:59 <a href="http://www.blogjava.net/wangxq/articles/39384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse及其插件介绍和下载- -</title><link>http://www.blogjava.net/wangxq/articles/38250.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 30 Mar 2006 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/38250.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/38250.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/38250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/38250.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/38250.html</trackback:ping><description><![CDATA[
		<h2 class="diaryTitle">
				<font size="3">from:http://tonng.blogchina.com/2453816.html</font>
		</h2>
		<b>Tag</b>： <a href="http://tag.bokee.com/SearchTag.b?span=1&amp;wd=Eclipse" target="_blank">Eclipse</a>    <a href="http://tag.bokee.com/SearchTag.b?span=1&amp;wd=%B2%E5%BC%FE" target="_blank">插件</a>                                           
<p>0.Eclipse下载<br />EMF,GEF - Graphical Editor Framework,UML2,VE - Visual Editor都在这里下载<br /><a href="http://www.eclipse.org/downloads/index.php">http://www.eclipse.org/downloads/index.php</a><br /> <br />0.5.lomboz J2EE插件,开发JSP,EJB<br /><a href="http://forge.objectweb.org/projects/lomboz">http://forge.objectweb.org/projects/lomboz</a><br />1.MyEclipse J2EE开发插件，支持SERVLET/JSP/EJB/数据库操纵等 <br /><a href="http://www.myeclipseide.com/">http://www.myeclipseide.com</a><br /> <br />2.Properties Editor  编辑java的属性文件，并可以自动存盘为Unicode格式 <br /><a href="http://propedit.sourceforge.jp/index_en.html">http://propedit.sourceforge.jp/index_en.html</a><br />  <br />3.Colorer Take  为上百种类型的文件按语法着色 <br /><a href="http://colorer.sourceforge.net/">http://colorer.sourceforge.net/</a><br />  <br />4.XMLBuddy 编辑xml文件<br /><a href="http://www.xmlbuddy.com/">http://www.xmlbuddy.com</a><br />  <br />5.Code Folding  加入多种代码折叠功能（比eclipse自带的更多） <br /><a href="http://www.coffee-bytes.com/servlet/PlatformSupport">http://www.coffee-bytes.com/servlet/PlatformSupport</a><br />  <br />6.Easy Explorer  从eclipse中访问选定文件、目录所在的文件夹 <br /><a href="http://easystruts.sourceforge.net/">http://easystruts.sourceforge.net/</a><br />  <br />7.Fat Jar 打包插件，可以方便的完成各种打包任务，可以包含外部的包等 <br /><a href="http://fjep.sourceforge.net/">http://fjep.sourceforge.net/</a><br />  <br />8.RegEx Test 测试正则表达式 <br /><a href="http://brosinski.com/stephan/archives/000028.php">http://brosinski.com/stephan/archives/000028.php</a><br />  <br />9.JasperAssistant 报表插件（强，要钱的） <br /><a href="http://www.jasperassistant.com/">http://www.jasperassistant.com/</a><br />  <br />10.Jigloo GUI Builder ＪＡＶＡ的ＧＵＩ编辑插件 <br /><a href="http://cloudgarden.com/jigloo/">http://cloudgarden.com/jigloo/</a><br />  <br />11.Profiler 性能跟踪、测量工具，能跟踪、测量ＢＳ程序 <br /><a href="http://sourceforge.net/projects/eclipsecolorer/">http://sourceforge.net/projects/eclipsecolorer/</a><br />  <br />12.AdvanQas 提供对if/else等条件语句的提示和快捷帮助（自动更改结构等） <br /><a href="http://eclipsecolorer.sourceforge.net/advanqas/index.html">http://eclipsecolorer.sourceforge.net/advanqas/index.html</a><br />  <br />13.Log4E Log4j插件，提供各种和Log4j相关的任务，如为方法、类添加一个logger等 <br /><a href="http://log4e.jayefem.de/index.php/Main_Page">http://log4e.jayefem.de/index.php/Main_Page</a><br />  <br />14.VSSPlugin VSS插件 <br /><a href="http://sourceforge.net/projects/vssplugin">http://sourceforge.net/projects/vssplugin</a><br />  <br />15.Implementors 提供跳转到一个方法的实现类，而不是接中的功能（实用!） <br /><a href="http://eclipse-tools.sourceforge.net/implementors/">http://eclipse-tools.sourceforge.net/implementors/</a><br />  <br />16.Call Hierarchy 显示一个方法的调用层次（被哪些方法调，调了哪些方法） <br /><a href="http://eclipse-tools.sourceforge.net/call-hierarchy/index.html">http://eclipse-tools.sourceforge.net/call-hierarchy/index.html</a><br />  <br />17.EclipseTidy 检查和格式化HTML/XML文件 <br /><a href="http://eclipsetidy.sourceforge.net/">http://eclipsetidy.sourceforge.net/</a><br />  <br />18.Checkclipse 检查代码的风格、写法是否符合规范 <br /><a href="http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm">http://www.mvmsoft.de/content/plugins/checkclipse/checkclipse.htm</a><br />  <br />19.Hibernate Synchronizer Hibernate插件，自动映射等 <br /><a href="http://www.binamics.com/hibernatesync/">http://www.binamics.com/hibernatesync/</a><br />  <br />20.VeloEclipse  Velocity插件 <br /><a href="http://propsorter.sourceforge.net/">http://propsorter.sourceforge.net/</a><br />  <br />21.EditorList 方便的列出所有打开的Editor <br /><a href="http://editorlist.sourceforge.net/">http://editorlist.sourceforge.net/</a><br />  <br />22.MemoryManager 内存占用率的监视 <br /><a href="http://cloudgarden.com/memorymanager/">http://cloudgarden.com/memorymanager/</a><br /> <br />23.swt-designer java的GUI插件<br /><a href="http://www.swt-designer.com/">http://www.swt-designer.com/</a><br /> <br />24.TomcatPlugin 支持Tomcat插件 <br /><a href="http://www.sysdeo.com/eclipse/tomcatPlugin.html">http://www.sysdeo.com/eclipse/tomcatPlugin.html</a><br /> <br />25.XML Viewer <br /><a href="http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html">http://tabaquismo.freehosting.net/ignacio/eclipse/xmlview/index.html</a><br /> <br />26.quantum 数据库插件<br /><a href="http://quantum.sourceforge.net/">http://quantum.sourceforge.net/</a><br /> <br />27.Dbedit 数据库插件<br /><a href="http://sourceforge.net/projects/dbedit">http://sourceforge.net/projects/dbedit</a><br /> <br />28.clay.core 可视化的数据库插件 <br /><a href="http://www.azzurri.jp/en/software/index.jsp">http://www.azzurri.jp/en/software/index.jsp</a><br /><a href="http://www.azzurri.jp/eclipse/plugins">http://www.azzurri.jp/eclipse/plugins</a><br /> <br />29.hiberclipse hibernate插件 <br /><a href="http://hiberclipse.sourceforge.net/">http://hiberclipse.sourceforge.net</a><br /><a href="http://www.binamics.com/hibernatesync">http://www.binamics.com/hibernatesync</a><br /> <br />30.struts-console Struts插件<br /><a href="http://www.jamesholmes.com/struts/console/">http://www.jamesholmes.com/struts/console/</a><br /> <br />31.easystruts Struts插件<br /><a href="http://easystruts.sourceforge.net/">http://easystruts.sourceforge.net</a><br /> <br />32.veloedit Velocity插件<br /><a href="http://veloedit.sourceforge.net/">http://veloedit.sourceforge.net/</a><br /> <br />33.jalopy 代码整理插件<br /><a href="http://jalopy.sourceforge.net/">http://jalopy.sourceforge.net/</a><br /> <br />34.JDepend 包关系分析<br /><a href="http://andrei.gmxhome.de/jdepend4eclipse/links.html">http://andrei.gmxhome.de/jdepend4eclipse/links.html</a><br /> <br />35.Spring IDE Spring插件<br /><a href="http://springide-eclip.sourceforge.net/updatesite/">http://springide-eclip.sourceforge.net/updatesite/</a><br /> <br />36.doclipse 可以产生xdoclet 的代码提示<br /><a href="http://beust.com/doclipse/">http://beust.com/doclipse/</a></p><img src ="http://www.blogjava.net/wangxq/aggbug/38250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-30 14:13 <a href="http://www.blogjava.net/wangxq/articles/38250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]清除windows系统垃圾文件</title><link>http://www.blogjava.net/wangxq/articles/35618.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 16 Mar 2006 04:34:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/35618.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/35618.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/35618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/35618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/35618.html</trackback:ping><description><![CDATA[<TABLE style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all" cellSpacing=0 cellPadding=0 width="96%" border=0>
<TBODY>
<TR>
<TD bgColor=#e8f0f1>自：<A href="http://www.tzblog.cn/user1/1144/archives/2006/13387.html">http://www.tzblog.cn/user1/1144/archives/2006/13387.html</A></TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV align=right>&nbsp;</DIV></TD></TR></TBODY></TABLE><SPAN class=oblog_text>&nbsp; 为你的电脑系统清除淤塞的垃圾！轻松流畅上网你是否注意到你的电脑系统磁盘的可用空间正在一天天在减少呢？是不是像老去的猴王一样动作一天比一天迟缓呢？没错！在Windows在安装和使用过程中都会产生相当多的垃圾文件，包括临时文件（如：*.tmp、*._mp）日志文件（*.log）、临时帮助文件（*.gid）、磁盘检查文件（*.chk）、临时备份文件（如：*.old、*.bak）以及其他临时文件。 
<P>　　特别是如果一段时间不清理IE的临时文件夹“Temporary Internet Files”，其中的缓存文件有时会占用上百MB的磁盘空间。这些垃圾文件不仅仅浪费了宝贵的磁盘空间，严重时还会使系统运行慢如蜗牛。这点相信你肯定忍受不了吧！所以应及时清理系统的垃圾文件的淤塞，保持系统的“苗条”身材，轻松流畅上网！朋友来吧，现在就让我们一起来快速清除系统垃圾吧！！</P>
<P>　　新建一个记事本并输入以下的内容：</P>
<P>　　@echo off<BR>　　echo 正在清除系统垃圾文件，请稍等......<BR>　　del /f /s /q %systemdrive%\*.tmp<BR>　　del /f /s /q %systemdrive%\*._mp<BR>　　del /f /s /q %systemdrive%\*.log<BR>　　del /f /s /q %systemdrive%\*.gid<BR>　　del /f /s /q %systemdrive%\*.chk<BR>　　del /f /s /q %systemdrive%\*.old<BR>　　del /f /s /q %systemdrive%\recycled\*.*<BR>　　del /f /s /q %windir%\*.bak<BR>　　del /f /s /q %windir%\prefetch\*.*<BR>　　rd /s /q %windir%\temp &amp; md %windir%\temp<BR>　　del /f /q %userprofile%\cookies\*.*<BR>　　del /f /q %userprofile%\recent\*.*<BR>　　del /f /s /q "%userprofile%\Local Settings\Temporary Internet Files\*.*"<BR>　　del /f /s /q "%userprofile%\Local Settings\Temp\*.*"<BR>　　del /f /s /q "%userprofile%\recent\*.*"<BR>　　echo 清除系统垃圾完成！<BR>　　echo. &amp; pause </P>
<P>　　最后将它保存，然后更名为“清除系统垃圾.bat”！ok！你的垃圾清除器就这样制作成功了！</P>
<P>　　以后只要双击运行该文件，当屏幕提示“清除系统垃圾完成！就还你一个“苗条”的系统了！！到时候再看看你的电脑，是不是急速如飞呢？</P></SPAN></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/wangxq/aggbug/35618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-16 12:34 <a href="http://www.blogjava.net/wangxq/articles/35618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]synchronized详解</title><link>http://www.blogjava.net/wangxq/articles/35341.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Wed, 15 Mar 2006 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/35341.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/35341.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/35341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/35341.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/35341.html</trackback:ping><description><![CDATA[源自：<A href="http://erichcn.blogdriver.com/erichcn/847568.html">http://erichcn.blogdriver.com/erichcn/847568.html</A><BR>
<P><SPAN class=postbody>不要重新分配被锁定对象的对象引用 <BR><BR>synchronized 关键字锁定对象。对象是在 synchronized 代码内部被锁定的，这一点对此对象以及您对其对象引用所作的更改意味着什么呢？对一个对象作同步处理只锁定该对象。但是，必须注意不要重新分配被锁定对象的对象引用。那么如果这样做会发生什么情况呢？请考虑下面这段代码，它实现了一个 Stack： <BR><BR>class Stack <BR>{ <BR>private int StackSize = 10; <BR>private int[] intArr = new int[stackSize]; <BR>private int index; //Stack 中的下一个可用位置。 <BR><BR>public void push(int val) <BR>{ <BR>synchronized(intArr) { <BR>//如果已满，则重新分配整数数组（即我们的 Stack）。 <BR>if (index == intArr.length) <BR>{ <BR>stackSize *= 2; <BR>int[] newintArr == new int[stackSize]; <BR>System.arraycopy(intArr, 0, newintArr, 0, intArr.length); <BR>intArr = newintArr; <BR>} <BR>intArr[index] == val; <BR>index++; <BR>} <BR>} <BR><BR>public int pop() <BR>{ <BR>int retval; <BR>synchronized(intArr) { <BR>if (index &gt; 0) <BR>{ <BR>retval = intArr[index-1]; //检索值， <BR>index--; //并使 Stack 减少 1 个值。 <BR>return retval; <BR>} <BR>} <BR>throw new EmptyStackException(); <BR>} <BR>//... <BR>} <BR><BR><BR>这段代码用数组实现了一个 Stack。创建了一个初始大小为 10 的数组来容纳整数值。此类实现了 push 和 pop 方法来模拟 Stack 的使用。在 push 方法中，如果数组中没有更多的空间来容纳压入的值，则数组被重新分配以创建更多的存储空间。（故意没有用 Vector 来实现这个类。Vector 中不能储存基本类型。） <BR><BR>请注意，这段代码是要由多个线程进行访问的。push 和 pop 方法每次对该类的共享实例数据的访问都是在 synchronized 块内完成的。这样就保证了多个线程不能并发访问此数组而生成不正确的结果。 <BR><BR>这段代码有一个主要的缺点。它对整数数组对象作了同步处理，而这个数组被 Stack 类的 intArr 所引用。当 push 方法重新分配此整数数组时，这个缺点就会显露出来。当这种情况发生时，对象引用 intArr 被重新指定为引用一个新的、更大的整数数组对象。请注意，这是在 push 方法的 synchronized 块执行期间发生的。此块针对 intArr 变量引用的对象进行了同步处理。因此，在这段代码内锁定的对象不再被使用。请考虑以下的事件序列： <BR><BR>线程 1 调用 push 方法并获得 intArr 对象的锁。 <BR><BR><BR>线程 1 被线程 2 抢先。 <BR><BR><BR>线程 2 调用 pop 方法。此方法因试图获取当前线程 1 在 push 方法中持有的同一个锁而阻塞。 <BR><BR><BR>线程 1 重新获得控制并重新分配数组。intArr 变量现在引用一个不同的变量。 <BR><BR><BR>push 方法退出并释放它对原来的 intArr 对象的锁。 <BR><BR><BR>线程 1 再次调用 push 方法并获得新 intArr 对象的锁。 <BR><BR><BR>线程 1 被线程 2 抢先。 <BR><BR><BR>线程 2 获得旧 intArr 对象的对象锁并试图访问其内存。 <BR><BR><BR>现在线程 1 持有由 intArr 引用的新对象的锁，线程 2 持有由 intArr 引用的旧对象的锁。因为两个线程持有不同的锁，所以它们可以并发执行 synchronized push 和 pop 方法，从而导致错误。很明显，这不是所希望的结果。 <BR><BR>这个问题是因 push 方法重新分配被锁定对象的对象引用而造成的。当某个对象被锁定时，其他线程可能在同一个对象锁上被阻塞。如果将被锁定对象的对象引用重新分配给另一个对象，其他线程的挂起锁则是针对代码中已不再相关的对象的。 <BR><BR>您可以这样修正这段代码，去掉对 intArr 变量的同步，而对 push 和 pop 方法进行同步。通过将 synchronized 关键字添加为方法修饰符即可实现这一点。正确的代码如下所示： <BR><BR>class Stack <BR>{ <BR>//与前面相同... <BR>public synchronized void push(int val) <BR>{ <BR>//如果为空，则重新分配整数数组（即我们的 Stack）。 <BR>if (index == intArr.length) <BR>{ <BR>stackSize *= 2; <BR>int[] newintArr = new int[stackSize]; <BR>System.arraycopy(intArr, 0, newintArr, 0, intArr.length); <BR>intArr = newintArr; <BR>} <BR>intArr[index]= val; <BR>index++; <BR>} <BR><BR>public synchronized int pop() <BR>{ <BR>int retval; <BR>if (index &gt; 0) <BR>{ <BR>retval = intArr[index-1]; <BR>index--; <BR>return retval; <BR>} <BR>throw new EmptyStackException(); <BR>} <BR>} <BR><BR><BR>这个修改更改了实际上获取的锁。获取的锁是针对为其调用方法的对象的，而不是锁定 intArr 变量所引用的对象。因为获取的锁不再针对 intArr 所引用的对象，所以允许代码重新指定 intArr 对象引用。</SPAN><SPAN class=postbody><BR><SPAN class=postbody>Maximizing concurrency in Java programming <BR><A href="http://www-106.ibm.com/developerworks/ibm/library/it-haggar_concurrency/" target=_blank>http://www-106.ibm.com/developerworks/ibm/library/it-haggar_concurrency/</A> <BR>Contents: <BR>Avoid unnecessary synchronization <BR>Use volatile to increase concurrency <BR>Summary <BR>Resources <BR>About the author <BR>Rate this article <BR>Subscriptions: <BR>dW newsletters <BR>dW Subscription <BR>(CDs and downloads) <BR><BR>Peter Haggar (haggar@us.ibm.com) <BR>Senior Software Engineer , IBM <BR>1 July 2001 <BR><BR>When discussing concurrency, programmers typically look for ways to avoid its common problems. Concurrent access to data via multiple threads of execution, can cause stale, or invalid, reads and writes. In the Java programming language, the solution is to synchronize access to this data via the language's built-in synchronization mechanisms. The synchronized keyword is used to control access to shared data. However, synchronization ensures valid reads and writes of data at the cost of reduced concurrency. Because the Java language's synchronization mechanisms are not very granular, usage of it reduces the concurrency of your programs more than is sometimes needed. Less concurrency can result in poorly behaved and inefficient programs. This article outlines techniques to increase the concurrency of your code while maintaining its correctness. The first step to increasing concurrency is to avoid unnecessary synchronization. <BR><BR>Avoid unnecessary synchronization <BR>The Java language provides synchronization to allow multiple threads of execution to access the same objects safely. Adding unneeded synchronization is as bad as omitting necessary synchronization. Sometimes programmers, in search of thread-safe code, synchronize too many methods. Excess synchronization can lead to code that deadlocks or code that runs slowly. (For more information on the cost of synchronization, see Praxis 34 of Practical Java Programming Language Guide and my last column on bytecode.) One goal of your software is to run efficiently, without deadlocks. <BR><BR>Because of the way the synchronized keyword is implemented, the result is often unnecessary synchronization and less concurrency. For example, consider the following class: <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>代码:</B></SPAN></TD></TR>
<TR>
<TD class=code><BR>class Test <BR>{ <BR>&nbsp; private int[] ia1; <BR>&nbsp; private int[] ia2; <BR>&nbsp; private double[] da1; <BR>&nbsp; private double[] da2; <BR><BR>&nbsp; public synchronized void method1() <BR>&nbsp; { <BR>&nbsp; &nbsp; //Access ia1 and ia2 <BR>&nbsp; } <BR>&nbsp; public synchronized void method2() <BR>&nbsp; { <BR>&nbsp; &nbsp; //Access ia1 and ia2 <BR>&nbsp; } <BR>&nbsp; public synchronized void method3() <BR>&nbsp; { <BR>&nbsp; &nbsp; //Access da1 and da2 <BR>&nbsp; } <BR>&nbsp; public synchronized void method4() <BR>&nbsp; { <BR>&nbsp; &nbsp; //Access da1 and da2 <BR>&nbsp; } <BR>&nbsp; //... <BR>} <BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR>This class is certainly thread safe. Each method must be declared synchronized in order to ensure the arrays are not corrupted by multiple threads accessing this object concurrently. For example, because method1 and method2 both access and potentially alter the arrays, ia1 and ia2 , access to them must be synchronized. The same is true of method3 and method4 . <BR><BR>Notice, however, that although method1 and method2 must be synchronized with each other, they do not need to be synchronized with either method3 or method4 . This is because method1 and method2 do not operate on data that method3 and method4 operate. This is also true for method3 and method4 with regard to method1 and method2 . <BR><BR>Unfortunately, this is how instance methods are sometimes synchronized in classes. Synchronization in the Java language is not very granular. Synchronization provides you with only one lock per object. In the previous code, if you create an object of class Test and call method1 on the main thread and method3 on a secondary thread, you pay an unnecessary performance penalty. These methods synchronize with one another even though there is no need for them to do so. Remember that when a method is declared synchronized , the lock obtained is the lock for the object on which the method is invoked. Therefore, both methods attempt to get the same lock. <BR><BR>To fix the problem in the previous code you need multiple locks per object. Because the Java language does not provide this, you must furnish your own mechanism. One way to accomplish this is to create objects as instance data that serve only to provide locks. The previous code is modified using this technique and looks like this: <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>代码:</B></SPAN></TD></TR>
<TR>
<TD class=code><BR>class Test <BR>{ <BR>&nbsp; private int[] ia1; <BR>&nbsp; private int[] ia2; <BR>&nbsp; private double[] da1; <BR>&nbsp; private double[] da2; <BR>&nbsp; private byte[] lock1 = new byte[0]; <BR>&nbsp; private byte[] lock2 = new byte[0]; <BR><BR>&nbsp; public void method1() <BR>&nbsp; { <BR>&nbsp; &nbsp;synchronized(lock1) { <BR>&nbsp; &nbsp; &nbsp; //Access ia1 and ia2 <BR>&nbsp; &nbsp; } <BR>&nbsp; } <BR>&nbsp; public void method2() <BR>&nbsp; { <BR>&nbsp; &nbsp; synchronized(lock1) { <BR>&nbsp; &nbsp; &nbsp; //Access ia1 and ia2 <BR>&nbsp; &nbsp; } <BR>&nbsp; } <BR>&nbsp; public void method3() <BR>&nbsp; { <BR>&nbsp; &nbsp; synchronized(lock2) { <BR>&nbsp; &nbsp; &nbsp; //Access da1 and da2 <BR>&nbsp; &nbsp; } <BR>&nbsp; } <BR>&nbsp; public void method4() <BR>&nbsp; { <BR>&nbsp; &nbsp; synchronized(lock2) { <BR>&nbsp; &nbsp; &nbsp; //Access da1 and da2 <BR>&nbsp; &nbsp; } <BR>&nbsp; } <BR>&nbsp; //... <BR>} <BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR>Notice that this code no longer has synchronized methods. They are removed and replaced with synchronized blocks. This allows the synchronization to occur on different objects and allows the methods that can safely run concurrently to do so. For example, method1 is able to execute concurrently with method3 or method4 because they access different object locks. <BR><BR>A zero element array is used as the lock objects because such an array is cheaper to create than any other object. Creating a zero element array does not require a constructor call like the creation of Object does. Therefore, it executes faster. In addition, a byte array is used because it is often represented more compactly than an int array. <BR><BR>Care must be taken when using this technique. You must be sure that the methods you think can operate without synchronization are able to do so without causing errors. Debugging multithreaded code can be very time consuming, so it is important not to use this technique casually. <BR><BR>You might wonder why method1 and method2 do not lock both ia1 and ia2 instead of the lock1 object. This could be done, but it is more error prone. When you lock multiple objects, you must make sure to lock them in the same order throughout your code. Failure to do this can result in deadlock. For more on this problem and how to avoid it, see Praxis 52 of Practical Java Programming Language Guide. <BR><BR>Use volatile to increase concurrency <BR>When variables are shared between threads, they must always be accessed properly to ensure that correct and valid values are manipulated. The JVM is guaranteed to treat reads and writes of data of 32 bits or less as atomic. This might lead some programmers to believe that access to shared variables does not need to be synchronized or the variables declared volatile. Consider this code: <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>代码:</B></SPAN></TD></TR>
<TR>
<TD class=code><BR>class RealTimeClock <BR>{ <BR>&nbsp; private int clkID; <BR>&nbsp; private long clockTime; <BR><BR>&nbsp; public int clockID() <BR>&nbsp; { <BR>&nbsp; &nbsp; return clkID; <BR>&nbsp; } <BR>&nbsp; public void setClockID(int id) <BR>&nbsp; { <BR>&nbsp; &nbsp; clkID = id; <BR>&nbsp; } <BR><BR>&nbsp; public long time() <BR>&nbsp; { <BR>&nbsp; &nbsp; return clockTime; <BR>&nbsp; } <BR>&nbsp; public void setTime(long t) <BR>&nbsp; { <BR>&nbsp; &nbsp; clockTime = t; <BR>&nbsp; } <BR>&nbsp; //... <BR>} <BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR>Now contemplate an implementation that uses the previous code. It might create an object of the RealTimeClock class and two threads. It could then call the methods of this class from the two threads. <BR><BR>The variables clkID and clockTime are stored in main memory. However, the Java language allows threads to keep private working copies of these variables. This enables a more efficient execution of the two threads. For example, when each thread reads and writes these variables, they can do so on the private working copies instead of accessing the variables from main memory. The private working copies are reconciled with main memory only at specific synchronization points. <BR><BR>The clockID and setClockID methods perform only a read and a write, respectively, on data of type int . Therefore, the operation of these methods is automatically atomic. However, given that the clkID variable could be stored in private working memory for each thread, consider the following possible sequence of events: <BR><BR>1. Thread 1 calls the setClockID method, passing a value of 5. <BR>2. Thread 2 calls the setClockID method, passing a value of 10. <BR>3. Thread 1 calls the clockID method, which returns the value 5. <BR><BR>This sequence of events is possible because the clkID variable is not guaranteed to be reconciled with main memory. During step 1, thread 1 places the value 5 in its working memory. When step 2 executes, thread 2 places the value 10 in its working memory. When step 3 executes, thread 1 reads the value from its working memory and returns 5. At no point are the values reconciled with main memory. <BR><BR>There are two ways to fix this problem. <BR><BR>1. Access the clkID variable from a synchronized method or block. <BR>2. Declare the clkID variable volatile. <BR><BR>Either solution requires the clkID variable to be reconciled with main memory. Accessing the clkID variable from a synchronized method or block does not allow that code to execute concurrently, but it does guarantee that the clkID variable in main memory is updated appropriately. Main memory is updated when the object lock is obtained before the protected code executes and when the lock is released after the protected code executes. <BR><BR>Declaring the clkID variable volatile allows the code to execute concurrently and also guarantees that the private working copy of the clkID variable is reconciled with main memory. This reconciliation, however, occurs each time the variable is accessed. <BR><BR>Also consider the time and setTime methods that operate on a variable of type long. These methods can exhibit the same problem described previously. They also have an additional problem. Data of type long is typically represented by bits spread across two 32-bit words. An implementation of the JVM might treat the operation on a -bit value as atomic, but most JVM implementations today do not. Instead, it treats such operations as two distinct 32-bit operations. Consider the following possible sequence of events with the clockTime instance variable: <BR><BR>1. Thread 1 calls the time method. <BR>2. Thread 1 begins to read the clockTime instance variable and reads the first 32 bits. <BR>3. Thread 1 is preempted by thread 2. <BR>4. Thread 2 calls the setTime method. The setTime method performs two writes of 32 bits each to the clockTime instance variable, replacing both 32-bit values with different values. <BR>5. Thread 2 is preempted by thread 1. <BR>6. Thread 1 reads the second 32 bits of the clockTime instance variable and returns the result. <BR><BR>Note: Implementations of JVMs are encouraged to treat -bit operations as atomic but are not required to do so. This is because some popular microprocessors currently do not provide efficient atomic memory transactions on -bit values. <BR><BR>According to this sequence of events, the value returned by the time method is made up of the first 32 bits of the old value of the clockTime instance variable and the second 32 bits of the new value of the same instance variable. The value returned is not correct. This is because of the multiple reads and writes necessary for -bit data in the JVM. The private working memory and main memory issue discussed earlier are also problematic. You have the same two options to fix this problem: Synchronize access to the clockTime variable, or declare it volatile. <BR><BR>It is important to understand that atomic operations do not automatically mean thread-safe operations. In addition, whenever multiple threads share variables, it is important that they are accessed in a synchronized method or block, or that they are declared with the volatile keyword. This ensures that the variables are properly reconciled with main memory, thereby guaranteeing correct values at all times. <BR><BR>Whether you use volatile or synchronized depends on several factors. If concurrency is important and you are not updating many variables, consider using volatile. If you are updating many variables, however, using volatile might be slower than using synchronization. Remember that when variables are declared volatile, they are reconciled with main memory on every access. By contrast, when synchronized is used, the variables are reconciled with main memory only when the lock is obtained and when the lock is released. Consider using synchronized if you are updating many variables and do not want the cost of reconciling each of them with main memory on every access, or you want to eliminate concurrency for another reason. <BR><BR>The following table summarizes the differences between the synchronized and volatile keywords. <BR><BR>volatile and synchronized <BR><BR>synchronized <BR>Advantages: Private working memory is reconciled with main memory when the lock is obtained and when the lock is released. <BR>Disadvantages : Eliminates concurrency. <BR><BR>volatile <BR>Advantages: Allows concurrency. <BR>Disadvantages: Private working memory is reconciled with main memory on each variable access. <BR><BR>Summary <BR>This article demonstrates two techniques for increasing the concurrency of your program while maintaining its accuracy. The volatile keyword and distinct lock objects are used to increase concurrency while maintaining correctness. These techniques should be considered when designing and writing multithreaded code. The more concurrency in your program, the more likely it is to behave as the user expects it to. <BR><BR>Resources <BR><BR>* Practical Java Programming Language Guide, Peter Haggar, Addison-Wesley, 2000, ISBN 0-201-616-7. <BR><BR>* The Java Virtual Machine Specification, Second Edition, Tim Lindholm and Frank Yellin, Addison-Wesley, 1999, ISBN 0-201-43294-3. <BR><BR>About the author <BR>Peter Haggar is a Senior Software Engineer with IBM in Research Triangle Park, North Carolina and the author of the book, Practical Java Programming Language Guide, published by Addison-Wesley. He has a broad range of programming experience, having worked on development tools, class libraries, and operating systems. At IBM, Peter works on emerging Java technology and is currently focused on embedded and real-time Java. Peter is a frequent technical speaker on Java technology at numerous industry conferences. He has worked for IBM for more than 12 years and received a B.S. in Computer Science from Clarkson University in New York. He can be contacted at <A href="mailto:haggar@us.ibm.com">haggar@us.ibm.com</A>.</SPAN><SPAN class=postbody><BR><SPAN class=postbody>Synchronization and the Java Memory Model <BR><A href="http://gee.cs.oswego.edu/dl/cpj/jmm.html" target=_blank>http://gee.cs.oswego.edu/dl/cpj/jmm.html</A> <BR>This set of excerpts from section 2.2 includes the main discussions on how the Java Memory Model impacts concurrent programming. <BR><BR>For information about ongoing work on the memory model, see Bill Pugh's Java Memory Model pages. <BR><BR>Consider the tiny class, defined without any synchronization: <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>代码:</B></SPAN></TD></TR>
<TR>
<TD class=code><BR>final class SetCheck { <BR>&nbsp; private int&nbsp; a = 0; <BR>&nbsp; private long b = 0; <BR><BR>&nbsp; void set() { <BR>&nbsp; &nbsp; a =&nbsp; 1; <BR>&nbsp; &nbsp; b = -1; <BR>&nbsp; } <BR><BR>&nbsp; boolean check() { <BR>&nbsp; &nbsp; return ((b ==&nbsp; 0) || <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (b == -1 &amp;&amp; a == 1)); <BR>&nbsp; } <BR>} <BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR>In a purely sequential language, the method check could never return false. This holds even though compilers, run-time systems, and hardware might process this code in a way that you might not intuitively expect. For example, any of the following might apply to the execution of method set: <BR><BR>* The compiler may rearrange the order of the statements, so b may be assigned before a. If the method is inlined, the compiler may further rearrange the orders with respect to yet other statements. <BR>* The processor may rearrange the execution order of machine instructions corresponding to the statements, or even execute them at the same time. <BR><BR>* The memory system (as governed by cache control units) may rearrange the order in which writes are committed to memory cells corresponding to the variables. These writes may overlap with other computations and memory actions. <BR><BR>* The compiler, processor, and/or memory system may interleave the machine-level effects of the two statements. For example on a 32-bit machine, the high-order word of b may be written first, followed by the write to a, followed by the write to the low-order word of b. <BR><BR>* The compiler, processor, and/or memory system may cause the memory cells representing the variables not to be updated until sometime after (if ever) a subsequent check is called, but instead to maintain the corresponding values (for example in CPU registers) in such a way that the code still has the intended effect. <BR><BR>In a sequential language, none of this can matter so long as program execution obeys as-if-serial semantics. Sequential programs cannot depend on the internal processing details of statements within simple code blocks, so they are free to be manipulated in all these ways. This provides essential flexibility for compilers and machines. Exploitation of such opportunities (via pipelined superscalar CPUs, multilevel caches, load/store balancing, interprocedural register allocation, and so on) is responsible for a significant amount of the massive improvements in execution speed seen in computing over the past decade. The as-if-serial property of these manipulations shields sequential programmers from needing to know if or how they take place. Programmers who never create their own threads are almost never impacted by these issues. <BR><BR>Things are different in concurrent programming. Here, it is entirely possible for check to be called in one thread while set is being executed in another, in which case the check might be "spying" on the optimized execution of set. And if any of the above manipulations occur, it is possible for check to return false. For example, as detailed below, check could read a value for the long b that is neither 0 nor -1, but instead a half-written in-between value. Also, out-of-order execution of the statements in set may cause check to read b as -1 but then read a as still 0. <BR><BR>In other words, not only may concurrent executions be interleaved, but they may also be reordered and otherwise manipulated in an optimized form that bears little resemblance to their source code. As compiler and run-time technology matures and multiprocessors become more prevalent, such phenomena become more common. They can lead to surprising results for programmers with backgrounds in sequential programming (in other words, just about all programmers) who have never been exposed to the underlying execution properties of allegedly sequential code. This can be the source of subtle concurrent programming errors. <BR><BR>In almost all cases, there is an obvious, simple way to avoid contemplation of all the complexities arising in concurrent programs due to optimized execution mechanics: Use synchronization. For example, if both methods in class SetCheck are declared as synchronized, then you can be sure that no internal processing details can affect the intended outcome of this code. <BR><BR>But sometimes you cannot or do not want to use synchronization. Or perhaps you must reason about someone else's code that does not use it. In these cases you must rely on the minimal guarantees about resulting semantics spelled out by the Java Memory Model. This model allows the kinds of manipulations listed above, but bounds their potential effects on execution semantics and additionally points to some techniques programmers can use to control some aspects of these semantics (most of which are discussed in §2.4). <BR><BR>The Java Memory Model is part of The JavaTM Language Specification, described primarily in JLS chapter 17. Here, we discuss only the basic motivation, properties, and programming consequences of the model. The treatment here reflects a few clarifications and updates that are missing from the first edition of JLS. <BR><BR>The assumptions underlying the model can be viewed as an idealization of a standard SMP machine of the sort described in §1.2.4: <BR><IMG src="http://gee.cs.oswego.edu/dl/cpj/mm-1.gif" border=0> <BR>For purposes of the model, every thread can be thought of as running on a different CPU from any other thread. Even on multiprocessors, this is infrequent in practice, but the fact that this CPU-per-thread mapping is among the legal ways to implement threads accounts for some of the model's initially surprising properties. For example, because CPUs hold registers that cannot be directly accessed by other CPUs, the model must allow for cases in which one thread does not know about values being manipulated by another thread. However, the impact of the model is by no means restricted to multiprocessors. The actions of compilers and processors can lead to identical concerns even on single-CPU systems. <BR><BR>The model does not specifically address whether the kinds of execution tactics discussed above are performed by compilers, CPUs, cache controllers, or any other mechanism. It does not even discuss them in terms of classes, objects, and methods familiar to programmers. Instead, the model defines an abstract relation between threads and main memory. Every thread is defined to have a working memory (an abstraction of caches and registers) in which to store values. The model guarantees a few properties surrounding the interactions of instruction sequences corresponding to methods and memory cells corresponding to fields. Most rules are phrased in terms of when values must be transferred between the main memory and per-thread working memory. The rules address three intertwined issues: <BR><BR>Atomicity <BR>Which instructions must have indivisible effects. For purposes of the model, these rules need to be stated only for simple reads and writes of memory cells representing fields - instance and static variables, also including array elements, but not including local variables inside methods. <BR>Visibility <BR>Under what conditions the effects of one thread are visible to another. The effects of interest here are writes to fields, as seen via reads of those fields. <BR>Ordering <BR>Under what conditions the effects of operations can appear out of order to any given thread. The main ordering issues surround reads and writes associated with sequences of assignment statements. <BR><BR>When synchronization is used consistently, each of these properties has a simple characterization: All changes made in one synchronized method or block are atomic and visible with respect to other synchronized methods and blocks employing the same lock, and processing of synchronized methods or blocks within any given thread is in program-specified order. Even though processing of statements within blocks may be out of order, this cannot matter to other threads employing synchronization. <BR><BR>When synchronization is not used or is used inconsistently, answers become more complex. The guarantees made by the memory model are weaker than most programmers intuitively expect, and are also weaker than those typically provided on any given JVM implementation. This imposes additional obligations on programmers attempting to ensure the object consistency relations that lie at the heart of exclusion practices: Objects must maintain invariants as seen by all threads that rely on them, not just by the thread performing any given state modification. <BR><BR>The most important rules and properties specified by the model are discussed below. <BR><BR>Atomicity <BR>Accesses and updates to the memory cells corresponding to fields of any type except long or double are guaranteed to be atomic. This includes fields serving as references to other objects. Additionally, atomicity extends to volatile long and double. (Even though non-volatile longs and doubles are not guaranteed atomic, they are of course allowed to be.) <BR><BR>Atomicity guarantees ensure that when a non-long/double field is used in an expression, you will obtain either its initial value or some value that was written by some thread, but not some jumble of bits resulting from two or more threads both trying to write values at the same time. However, as seen below, atomicity alone does not guarantee that you will get the value most recently written by any thread. For this reason, atomicity guarantees per se normally have little impact on concurrent program design. <BR><BR>Visibility <BR>Changes to fields made by one thread are guaranteed to be visible to other threads only under the following conditions: <BR><BR>* A writing thread releases a synchronization lock and a reading thread subsequently acquires that same synchronization lock. <BR><BR>In essence, releasing a lock forces a flush of all writes from working memory employed by the thread, and acquiring a lock forces a (re)load of the values of accessible fields. While lock actions provide exclusion only for the operations performed within a synchronized method or block, these memory effects are defined to cover all fields used by the thread performing the action. <BR><BR>Note the double meaning of synchronized: it deals with locks that permit higher-level synchronization protocols, while at the same time dealing with the memory system (sometimes via low-level memory barrier machine instructions) to keep value representations in synch across threads. This reflects one way in which concurrent programming bears more similarity to distributed programming than to sequential programming. The latter sense of synchronized may be viewed as a mechanism by which a method running in one thread indicates that it is willing to send and/or receive changes to variables to and from methods running in other threads. From this point of view, using locks and passing messages might be seen merely as syntactic variants of each other. <BR><BR>* If a field is declared as volatile, any value written to it is flushed and made visible by the writer thread before the writer thread performs any further memory operation (i.e., for the purposes at hand it is flushed immediately). Reader threads must reload the values of volatile fields upon each access. <BR><BR>* The first time a thread accesses a field of an object, it sees either the initial value of the field or a value since written by some other thread. <BR><BR>Among other consequences, it is bad practice to make available the reference to an incompletely constructed object (see §2.1.2). It can also be risky to start new threads inside a constructor, especially in a class that may be subclassed. Thread.start has the same memory effects as a lock release by the thread calling start, followed by a lock acquire by the started thread. If a Runnable superclass invokes new Thread(this).start() before subclass constructors execute, then the object might not be fully initialized when the run method executes. Similarly, if you create and start a new thread T and then create an object X used by thread T, you cannot be sure that the fields of X will be visible to T unless you employ synchronization surrounding all references to object X. Or, when applicable, you can create X before starting T. <BR><BR>* As a thread terminates, all written variables are flushed to main memory. For example, if one thread synchronizes on the termination of another thread using Thread.join, then it is guaranteed to see the effects made by that thread (see §4.3.2). <BR><BR>Note that visibility problems never arise when passing references to objects across methods in the same thread. <BR><BR>The memory model guarantees that, given the eventual occurrence of the above operations, a particular update to a particular field made by one thread will eventually be visible to another. But eventually can be an arbitrarily long time. Long stretches of code in threads that use no synchronization can be hopelessly out of synch with other threads with respect to values of fields. In particular, it is always wrong to write loops waiting for values written by other threads unless the fields are volatile or accessed via synchronization (see §3.2.6). <BR><BR>The model also allows inconsistent visibility in the absence of synchronization. For example, it is possible to obtain a fresh value for one field of an object, but a stale value for another. Similarly, it is possible to read a fresh, updated value of a reference variable, but a stale value of one of the fields of the object now being referenced. <BR><BR>However, the rules do not require visibility failures across threads, they merely allow these failures to occur. This is one aspect of the fact that not using synchronization in multithreaded code doesn't guarantee safety violations, it just allows them. On most current JVM implementations and platforms, even those employing multiple processors, detectable visibility failures rarely occur. The use of common caches across threads sharing a CPU, the lack of aggressive compiler-based optimizations, and the presence of strong cache consistency hardware often cause values to act as if they propagate immediately among threads. This makes testing for freedom from visibility-based errors impractical, since such errors might occur extremely rarely, or only on platforms you do not have access to, or only on those that have not even been built yet. These same comments apply to multithreaded safety failures more generally. Concurrent programs that do not use synchronization fail for many reasons, including memory consistency problems. <BR><BR>Ordering <BR>Ordering rules fall under two cases, within-thread and between-thread: <BR><BR>* From the point of view of the thread performing the actions in a method, instructions proceed in the normal as-if-serial manner that applies in sequential programming languages. <BR><BR>* From the point of view of other threads that might be "spying" on this thread by concurrently running unsynchronized methods, almost anything can happen. The only useful constraint is that the relative orderings of synchronized methods and blocks, as well as operations on volatile fields, are always preserved. <BR><BR>Again, these are only the minimal guaranteed properties. In any given program or platform, you may find stricter orderings. But you cannot rely on them, and you may find it difficult to test for code that would fail on JVM implementations that have different properties but still conform to the rules. <BR><BR>Note that the within-thread point of view is implicitly adopted in all other discussions of semantics in JLS. For example, arithmetic expression evaluation is performed in left-to-right order (JLS section 15.6) as viewed by the thread performing the operations, but not necessarily as viewed by other threads. <BR><BR>The within-thread as-if-serial property is helpful only when only one thread at a time is manipulating variables, due to synchronization, structural exclusion, or pure chance. When multiple threads are all running unsynchronized code that reads and writes common fields, then arbitrary interleavings, atomicity failures, race conditions, and visibility failures may result in execution patterns that make the notion of as-if-serial just about meaningless with respect to any given thread. <BR><BR>Even though JLS addresses some particular legal and illegal reorderings that can occur, interactions with these other issues reduce practical guarantees to saying that the results may reflect just about any possible interleaving of just about any possible reordering. So there is no point in trying to reason about the ordering properties of such code. <BR><BR>Volatile <BR>In terms of atomicity, visibility, and ordering, declaring a field as volatile is nearly identical in effect to using a little fully synchronized class protecting only that field via get/set methods, as in: <BR></SPAN>
<TABLE cellSpacing=1 cellPadding=3 width="90%" align=center border=0>
<TBODY>
<TR>
<TD><SPAN class=genmed><B>代码:</B></SPAN></TD></TR>
<TR>
<TD class=code><BR>final class VFloat { <BR>&nbsp; private float value; <BR><BR>&nbsp; final synchronized void&nbsp; set(float f) { value = f; } <BR>&nbsp; final synchronized float get()&nbsp; &nbsp; &nbsp; &nbsp; { return value; } <BR>} <BR></TD></TR></TBODY></TABLE><SPAN class=postbody><BR><BR>Declaring a field as volatile differs only in that no locking is involved. In particular, composite read/write operations such as the "++'' operation on volatile variables are not performed atomically. <BR><BR>Also, ordering and visibility effects surround only the single access or update to the volatile field itself. Declaring a reference field as volatile does not ensure visibility of non-volatile fields that are accessed via this reference. Similarly, declaring an array field as volatile does not ensure visibility of its elements. Volatility cannot be manually propagated for arrays because array elements themselves cannot be declared as volatile. <BR><BR>Because no locking is involved, declaring fields as volatile is likely to be cheaper than using synchronization, or at least no more expensive. However, if volatile fields are accessed frequently inside methods, their use is likely to lead to slower performance than would locking the entire methods. <BR><BR>Declaring fields as volatile can be useful when you do not need locking for any other reason, yet values must be accurately accessible across multiple threads. This may occur when: <BR><BR>* The field need not obey any invariants with respect to others. <BR><BR>* Writes to the field do not depend on its current value. <BR><BR>* No thread ever writes an illegal value with respect to intended semantics. <BR>* The actions of readers do not depend on values of other non-volatile fields. <BR><BR>Using volatile fields can make sense when it is somehow known that only one thread can change a field, but many other threads are allowed to read it at any time. For example, a Thermometer class might declare its temperature field as volatile. As discussed in §3.4.2, a volatile can be useful as a completion flag. Additional examples are illustrated in §4.4, where the use of lightweight executable frameworks automates some aspects of synchronization, but volatile declarations are needed to ensure that result field values are visible across tasks.</SPAN><SPAN class=postbody><BR></SPAN></SPAN></SPAN></P><img src ="http://www.blogjava.net/wangxq/aggbug/35341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-15 09:09 <a href="http://www.blogjava.net/wangxq/articles/35341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java开源 Java测试工具</title><link>http://www.blogjava.net/wangxq/articles/35056.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Mon, 13 Mar 2006 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/35056.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/35056.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/35056.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/35056.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/35056.html</trackback:ping><description><![CDATA[from: <a href="http://kb.csdn.net/java/Articles/200601/471cb3e7-12d4-41cf-ac06-4835d0674866.html">http://kb.csdn.net/java/Articles/200601/471cb3e7-12d4-41cf-ac06-4835d0674866.html</a><br /><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30543.htm?="" /><font size="5">JUnit</font></font><font size="5">  </font><p><strong>JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架（regression testing framework）。Junit测试是程序员测试，即所谓白盒测试，因为程序员知道被测试的软件如何（How）完成功能和完成什么样（What）的功能。Junit是一套框架，继承TestCase类，就可以用Junit进行自动测试了。</strong></p><p><a href="http://www.junit.org/"><font color="#003366">http://www.junit.org/</font></a></p><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30543.htm?="" /><font color="#003366">Cactus </font> </font></h2><p><strong>Cactus是一个基于JUnit框架的简单测试框架，用来单元测试服务端Java代码。Cactus框架的主要目标是能够单元测试服务端的使用Servlet对象的Java方法如HttpServletRequest,HttpServletResponse,HttpSession等</strong></p><p><a href="http://jakarta.apache.org/cactus/"><font color="#003366">http://jakarta.apache.org/cactus/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30643.htm?="" /><font color="#003366">Abbot</font>  </font></h2><p><strong>Abbot是一个用来测试Java GUIs的框架。用简单的基于XML的脚本或者Java代码，你就可以开始一个GUI。</strong></p><p><a href="http://abbot.sourceforge.net/"><font color="#003366">http://abbot.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30743.htm?="" /><font color="#003366">JUnitPerf</font>  </font></h2><p><strong>Junitperf实际是junit的一个decorator，通过编写用于junitperf的单元测试，我们也可使测试过程自动化。</strong></p><p><a href="http://www.clarkware.com/software/JUnitPerf.html"><font color="#003366">http://www.clarkware.com/software/JUnitPerf.html</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30843.htm?="" /><font color="#003366">DbUnit</font>  </font></h2><p><strong>DbUnit是为数据库驱动的项目提供的一个对JUnit 的扩展，除了提供一些常用功能，它可以将你的数据库置于一个测试轮回之间的状态。 </strong></p><p><a href="http://dbunit.sourceforge.net/"><font color="#003366">http://dbunit.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open30943.htm?="" /><font color="#003366">Mockrunner</font>  </font></h2><p><strong>Mockrunner用在J2EE环境中进行应用程序的单元测试。它不仅支持Struts actions, servlets，过滤器和标签类还包括一个JDBC和一个JMS测试框架，可以用于测试基于EJB的应用程序。</strong></p><p><a href="http://mockrunner.sourceforge.net/index.html"><font color="#003366">http://mockrunner.sourceforge.net/index.html</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31043.htm?="" /><font color="#003366">DBMonster</font>  </font></h2><p><strong>DBMonster是一个用生成随机数据来测试SQL数据库的压力测试工具。</strong></p><p><a href="http://dbmonster.kernelpanic.pl/"><font color="#003366">http://dbmonster.kernelpanic.pl/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31143.htm?="" /><font color="#003366">MockEJB</font>  </font></h2><p><strong>MockEJB是一个不需要EJB容器就能运行EJB并进行测试的轻量级框架。</strong></p><p><a href="http://mockejb.sourceforge.net/"><font color="#003366">http://mockejb.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31243.htm?="" /><font color="#003366">StrutsTestCase</font>  </font></h2><p><strong>StrutsTestCase 是Junit TestCase类的扩展，提供基于Struts框架的代码测试。StrutsTestCase同时提供Mock 对象方法和Cactus方法用来实际运行Struts ActionServlet，你可以通过运行servlet引擎来测试。因为StrutsTestCase使用ActionServlet控制器来测试你的代码，因此你不仅可以测试Action对象的实现，而且可以测试mappings，from beans以及forwards声明。StrutsTestCase不启动servlet容器来测试struts应用程序（容器外测试）也属于Mock对象测试，但是与EasyMock不同的是，EasyMock是提供了创建Mock对象的API，而StrutsTest则是专门负责测试Struts应用程序的Mock对象测试框架。 </strong></p><p><a href="http://strutstestcase.sourceforge.net/"><font color="#003366">http://strutstestcase.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31343.htm?="" /><font color="#003366">JFCUnit</font>  </font></h2><p><strong>JFCUnit使得你能够为Java偏移应用程序编写测试例子。它为从用代码打开的窗口上获得句柄提供了支持；为在一个部件层次定位部件提供支持；为在部件中发起事件（例如按一个按钮）以及以线程安全方式处理部件测试提供支持。</strong></p><p><a href="http://jfcunit.sourceforge.net/"><font color="#003366">http://jfcunit.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31443.htm?="" /><font color="#003366">JTestCase</font>  </font></h2><p><strong>JTestCase 使用XML文件来组织多测试案例数据，声明条件（操作和期望的结果），提供了一套易于使用的方法来检索XML中的测试案例，按照数据文件的定义来声明结果。</strong></p><p><a href="http://jtestcase.sourceforge.net/"><font color="#003366">http://jtestcase.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open31543.htm?="" /><font color="#003366">SQLUnit</font>  </font></h2><p><strong>SQLUnit是一个单元测试框架，用于对数据库存储过程进行回归测试。用 Java/JUnit/XML开发。 </strong></p><p><a href="http://sqlunit.sourceforge.net/"><font color="#003366">http://sqlunit.sourceforge.net</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open59643.htm?="" /><font color="#003366">JTR</font>  </font></h2><p><strong>JTR (Java Test Runner)是一个开源的基于反转控制(IOC)的J2EE测试框架。它允许你构建复杂的J2EE测试套件(Test Suites)并连到应用服务器执行测试,可以包括多个测试实例。JTR的licensed是GPL协议。</strong></p><p><a href="http://jtrunner.sourceforge.net/"><font color="#003366">http://jtrunner.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64143.htm?="" /><font color="#003366">Marathon</font>  </font></h2><p><strong>Marathon是一个针对使用Java/Swing开发GUI应用程序的测试框架，它由recorder, runner 和 editor组成，测试脚本是python代码。Marathon的焦点是放在最终用户的测试上。</strong></p><p><a href="http://marathonman.sourceforge.net/"><font color="#003366">http://marathonman.sourceforge.net</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64243.htm?="" /><font color="#003366">TestNG</font>  </font></h2><p><strong>TestNG是根据JUnit 和 NUnit思想而构建的一个测试框架，但是TestNG增加了许多新的功能使得它变得更加强大与容易使用比如：<br />*支持JSR 175注释（JDK 1.4利用JavaDoc注释同样也支持）<br />*灵活的Test配置<br />*支持默认的runtime和logging JDK功能<br />*强大的执行模型（不再TestSuite）<br />*支持独立的测试方法。</strong></p><p><a href="http://testng.org/"><font color="#003366">http://testng.org/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64343.htm?="" /><font color="#003366">Surrogate Test framework</font>  </font></h2><h2><font size="3">Surrogate Test framework是一个值得称赞单元测试框架，特别适合于大型，复杂Java系统的单元测试。这个框架能与JUnit,MockEJB和各种支持模拟对象（mock object ）的测试工具无缝给合。这个框架基于AspectJ技术。</font></h2><p><a href="http://surrogate.sourceforge.net/"><font color="#003366">http://surrogate.sourceforge.net</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64443.htm?="" /><font color="#003366">MockCreator</font>  </font></h2><p><strong>MockCreator可以为给定的interface或class生成模拟对象（Mock object）的源码。</strong></p><p><a href="http://mockcreator.sourceforge.net/"><font color="#003366">http://mockcreator.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64543.htm?="" /><font color="#003366">jMock</font>  </font></h2><p><strong>jMock利用mock objects思想来对Java code进行测试。jMock具有以下特点:容易扩展，让你快速简单地定义mock objects,因此不必打破程序间的关联，让你定义灵活的超越对象之间交互作用而带来测试局限，减少你测试地脆弱性。</strong></p><p><a href="http://www.jmock.org/"><font color="#003366">http://www.jmock.org/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64643.htm?="" /><font color="#003366">EasyMock</font>  </font></h2><p><strong>EasyMock为Mock Objects提供接口并在JUnit测试中利用Java的proxy设计模式生成它们的实例。EasyMock最适合于测试驱动开发。</strong></p><p><a href="http://www.easymock.org/"><font color="#003366">http://www.easymock.org/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64743.htm?="" /><font color="#003366">The Grinder</font>  </font></h2><p><strong>The Grinder是一个负载测试框架。在BSD开源协议下免费使用。</strong></p><p><a href="http://grinder.sourceforge.net/"><font color="#003366">http://grinder.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64843.htm?="" /><font color="#003366">XMLUnit</font>  </font></h2><p><strong>XMLUnit不仅有Java版本的还有.Net版本的。Java开发的XMLUnit提供了两个JUnit 扩展类XMLAssert和XMLTestCase,和一组支持的类。这些类可以用来比较两张XML之间的不同之处，展示XML利用XSLT来,校验XML,求得XPath表达式在XML中的值,遍历XML中的某一节点利DOM展开,</strong></p><p><a href="http://xmlunit.sourceforge.net/"><font color="#003366">http://xmlunit.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open64943.htm?="" /><font color="#003366">Jameleon</font>  </font></h2><p><strong>Jameleon一个自动化测试工具。它被用来测试各种各样的应用程序，所以它被设计成插件模式。为了使整个测试过程变得简单Jameleon提供了一个GUI,因此Jameleon实现了一个Swing 插件。</strong></p><p><a href="http://jameleon.sourceforge.net/index.html"><font color="#003366">http://jameleon.sourceforge.net/index.html</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open79343.htm?="" /><font color="#003366">J2MEUnit</font>  </font></h2><p><strong>J2MEUnit是应用在J2ME应用程序的一个单元测试框架。它基于JUnit.</strong></p><p><a href="http://j2meunit.sourceforge.net/"><font color="#003366">http://j2meunit.sourceforge.net/</font></a></p></div><div class="story"><h2><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;A href=" o&shy;nmousewheel="return bbimg(this)" open83943.htm?="" /><font color="#003366">Jetif</font>  </font></h2><h2><font size="3">Jetif是一个用纯Java实现的回归测试框架。它为Java程序单元测试以及功能测试提供了一个简单而且可 伸缩的架构，可以用于个人开发或企业级开发的测试。它容易使用，功能强大，而且拥有一些企业级测试的重要功能。Jetif来源于JUnit, JTestCase以及TestNG的启发，有几个基本的概念直接来自于JUnit， 比如说断言机制，Test Listener的概念，因此从JUnit转到Jetif是非常容易的。</font></h2><p><a href="http://jetif.sourceforge.net/"><font color="#003366">http://jetif.sourceforge.net/</font></a></p></div><div class="story"><h2><font size="2"><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;/FONT&gt;&lt;A href=" o&shy;nmousewheel="return bbimg(this)" open84043.htm?="" /><font size="5"><font color="#003366">GroboUtils</font>  </font></font></font></h2><h2><font size="3">GroboUtils使得扩展Java测试变得可能。它包括用在Java不同方面测试的多个子项目。在GroboUtils中最常被到的工具是:多线程测试(multi-threaded tests),整体单元测试(hierarchial unit tests),代码覆盖工具(code coverage tool)。</font></h2><p><a href="http://groboutils.sourceforge.net/"><font color="#003366">http://groboutils.sourceforge.net/</font></a></p></div><div class="story"><h2><font size="2"><font color="#003366"><img title="点击新窗口查看大图" height="14" alt="" src="http://www.open-open.com/image/item.gif" width="13" www.open-open.com="" http:="" o&shy;nload="java_script_:if(this.width&gt;600)this.width=600&quot; border=0&gt;&lt;/FONT&gt; &lt;/FONT&gt;&lt;A href=" o&shy;nmousewheel="return bbimg(this)" open85343.htm?="" /><font size="5"><font color="#003366">Testare</font>  </font></font></font></h2><h2><font size="3">TESTARE是用来简化分布式应用程序(比如:在SERVLETS,JMS listeners, CORBA ORBs或RMI环境下)测试开发过程的一个测试框架.</font></h2><p><a href="https://testare.dev.java.net/"><font color="#003366">https://testare.dev.java.net/</font></a></p></div><img src ="http://www.blogjava.net/wangxq/aggbug/35056.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-13 16:03 <a href="http://www.blogjava.net/wangxq/articles/35056.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【源译】JUnitPerf 使用手册</title><link>http://www.blogjava.net/wangxq/articles/33231.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 02 Mar 2006 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/33231.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/33231.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/33231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/33231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/33231.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: From:http://www.itcomputer.com.cn/Programs/Java/java/200512/2439.html												【源译】														JUnitPerf 														使用手册																																									...&nbsp;&nbsp;<a href='http://www.blogjava.net/wangxq/articles/33231.html'>阅读全文</a><img src ="http://www.blogjava.net/wangxq/aggbug/33231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-02 15:49 <a href="http://www.blogjava.net/wangxq/articles/33231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【Java开源 Java测试工具】</title><link>http://www.blogjava.net/wangxq/articles/33219.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 02 Mar 2006 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/33219.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/33219.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/33219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/33219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/33219.html</trackback:ping><description><![CDATA[<DIV class=postText>
<P align=center><SPAN class=style7><SPAN class=style7><STRONG><FONT face=宋体 color=#ff0000 size=4>【Java开源&nbsp;Java测试工具】</FONT></STRONG></SPAN></SPAN></P><SPAN class=style7><SPAN class=style7>
<DIV class=story>
<H2><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0>&nbsp;<A href="http://www.open-open.com/open30443.htm"><FONT color=#003366>JUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架（regression testing framework）。Junit测试是程序员测试，即所谓白盒测试，因为程序员知道被测试的软件如何（How）完成功能和完成什么样（What）的功能。Junit是一套框架，继承TestCase类，就可以用Junit进行自动测试了。</STRONG> </P>
<P><A href="http://www.junit.org/"><FONT color=#003366>http://www.junit.org/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open30543.htm"><FONT color=#003366>Cactus&nbsp;</FONT></A>&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Cactus是一个基于JUnit框架的简单测试框架，用来单元测试服务端Java代码。Cactus框架的主要目标是能够单元测试服务端的使用Servlet对象的Java方法如HttpServletRequest,HttpServletResponse,HttpSession等</STRONG></P>
<P><A href="http://jakarta.apache.org/cactus/"><FONT color=#003366>http://jakarta.apache.org/cactus/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open30643.htm"><FONT color=#003366>Abbot</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Abbot是一个用来测试Java GUIs的框架。用简单的基于XML的脚本或者Java代码，你就可以开始一个GUI。</STRONG></P>
<P><A href="http://abbot.sourceforge.net/"><FONT color=#003366>http://abbot.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open30743.htm"><FONT color=#003366>JUnitPerf</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Junitperf实际是junit的一个decorator，通过编写用于junitperf的单元测试，我们也可使测试过程自动化。</STRONG></P>
<P><A href="http://www.clarkware.com/software/JUnitPerf.html"><FONT color=#003366>http://www.clarkware.com/software/JUnitPerf.html</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open30843.htm"><FONT color=#003366>DbUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>DbUnit是为数据库驱动的项目提供的一个对JUnit 的扩展，除了提供一些常用功能，它可以将你的数据库置于一个测试轮回之间的状态。 </STRONG></P>
<P><A href="http://dbunit.sourceforge.net/"><FONT color=#003366>http://dbunit.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open30943.htm"><FONT color=#003366>Mockrunner</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Mockrunner用在J2EE环境中进行应用程序的单元测试。它不仅支持Struts actions, servlets，过滤器和标签类还包括一个JDBC和一个JMS测试框架，可以用于测试基于EJB的应用程序。</STRONG></P>
<P><A href="http://mockrunner.sourceforge.net/index.html"><FONT color=#003366>http://mockrunner.sourceforge.net/index.html</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31043.htm"><FONT color=#003366>DBMonster</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>DBMonster是一个用生成随机数据来测试SQL数据库的压力测试工具。</STRONG></P>
<P><A href="http://dbmonster.kernelpanic.pl/"><FONT color=#003366>http://dbmonster.kernelpanic.pl/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31143.htm"><FONT color=#003366>MockEJB</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>MockEJB是一个不需要EJB容器就能运行EJB并进行测试的轻量级框架。</STRONG></P>
<P><A href="http://mockejb.sourceforge.net/"><FONT color=#003366>http://mockejb.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31243.htm"><FONT color=#003366>StrutsTestCase</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>StrutsTestCase 是Junit TestCase类的扩展，提供基于Struts框架的代码测试。StrutsTestCase同时提供Mock 对象方法和Cactus方法用来实际运行Struts ActionServlet，你可以通过运行servlet引擎来测试。因为StrutsTestCase使用ActionServlet控制器来测试你的代码，因此你不仅可以测试Action对象的实现，而且可以测试mappings，from beans以及forwards声明。StrutsTestCase不启动servlet容器来测试struts应用程序（容器外测试）也属于Mock对象测试，但是与EasyMock不同的是，EasyMock是提供了创建Mock对象的API，而StrutsTest则是专门负责测试Struts应用程序的Mock对象测试框架。 </STRONG></P>
<P><A href="http://strutstestcase.sourceforge.net/"><FONT color=#003366>http://strutstestcase.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31343.htm"><FONT color=#003366>JFCUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>JFCUnit使得你能够为Java偏移应用程序编写测试例子。它为从用代码打开的窗口上获得句柄提供了支持；为在一个部件层次定位部件提供支持；为在部件中发起事件（例如按一个按钮）以及以线程安全方式处理部件测试提供支持。</STRONG></P>
<P><A href="http://jfcunit.sourceforge.net/"><FONT color=#003366>http://jfcunit.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31443.htm"><FONT color=#003366>JTestCase</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>JTestCase 使用XML文件来组织多测试案例数据，声明条件（操作和期望的结果），提供了一套易于使用的方法来检索XML中的测试案例，按照数据文件的定义来声明结果。</STRONG></P>
<P><A href="http://jtestcase.sourceforge.net/"><FONT color=#003366>http://jtestcase.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open31543.htm"><FONT color=#003366>SQLUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>SQLUnit是一个单元测试框架，用于对数据库存储过程进行回归测试。用 Java/JUnit/XML开发。 </STRONG></P>
<P><A href="http://sqlunit.sourceforge.net/"><FONT color=#003366>http://sqlunit.sourceforge.net</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open59643.htm"><FONT color=#003366>JTR</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>JTR (Java Test Runner)是一个开源的基于反转控制(IOC)的J2EE测试框架。它允许你构建复杂的J2EE测试套件(Test Suites)并连到应用服务器执行测试,可以包括多个测试实例。JTR的licensed是GPL协议。</STRONG></P>
<P><A href="http://jtrunner.sourceforge.net/"><FONT color=#003366>http://jtrunner.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64143.htm"><FONT color=#003366>Marathon</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Marathon是一个针对使用Java/Swing开发GUI应用程序的测试框架，它由recorder, runner 和 editor组成，测试脚本是python代码。Marathon的焦点是放在最终用户的测试上。</STRONG></P>
<P><A href="http://marathonman.sourceforge.net/"><FONT color=#003366>http://marathonman.sourceforge.net</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64243.htm"><FONT color=#003366>TestNG</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>TestNG是根据JUnit 和 NUnit思想而构建的一个测试框架，但是TestNG增加了许多新的功能使得它变得更加强大与容易使用比如：<BR>*支持JSR 175注释（JDK 1.4利用JavaDoc注释同样也支持）<BR>*灵活的Test配置<BR>*支持默认的runtime和logging JDK功能<BR>*强大的执行模型（不再TestSuite）<BR>*支持独立的测试方法。</STRONG></P>
<P><A href="http://testng.org/"><FONT color=#003366>http://testng.org/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64343.htm"><FONT color=#003366>Surrogate Test framework</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<H2><SPAN class=NavigationColor></SPAN><FONT size=3>Surrogate Test framework是一个值得称赞单元测试框架，特别适合于大型，复杂Java系统的单元测试。这个框架能与JUnit,MockEJB和各种支持模拟对象（mock object ）的测试工具无缝给合。这个框架基于AspectJ技术。</FONT></H2>
<P><A href="http://surrogate.sourceforge.net/"><FONT color=#003366>http://surrogate.sourceforge.net</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64443.htm"><FONT color=#003366>MockCreator</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>MockCreator可以为给定的interface或class生成模拟对象（Mock object）的源码。</STRONG></P>
<P><A href="http://mockcreator.sourceforge.net/"><FONT color=#003366>http://mockcreator.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64543.htm"><FONT color=#003366>jMock</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>jMock利用mock objects思想来对Java code进行测试。jMock具有以下特点:容易扩展，让你快速简单地定义mock objects,因此不必打破程序间的关联，让你定义灵活的超越对象之间交互作用而带来测试局限，减少你测试地脆弱性。</STRONG></P>
<P><A href="http://www.jmock.org/"><FONT color=#003366>http://www.jmock.org/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64643.htm"><FONT color=#003366>EasyMock</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>EasyMock为Mock Objects提供接口并在JUnit测试中利用Java的proxy设计模式生成它们的实例。EasyMock最适合于测试驱动开发。</STRONG></P>
<P><A href="http://www.easymock.org/"><FONT color=#003366>http://www.easymock.org/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64743.htm"><FONT color=#003366>The Grinder</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>The Grinder是一个负载测试框架。在BSD开源协议下免费使用。</STRONG></P>
<P><A href="http://grinder.sourceforge.net/"><FONT color=#003366>http://grinder.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64843.htm"><FONT color=#003366>XMLUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>XMLUnit不仅有Java版本的还有.Net版本的。Java开发的XMLUnit提供了两个JUnit 扩展类XMLAssert和XMLTestCase,和一组支持的类。这些类可以用来比较两张XML之间的不同之处，展示XML利用XSLT来,校验XML,求得XPath表达式在XML中的值,遍历XML中的某一节点利DOM展开,</STRONG></P>
<P><A href="http://xmlunit.sourceforge.net/"><FONT color=#003366>http://xmlunit.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open64943.htm"><FONT color=#003366>Jameleon</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>Jameleon一个自动化测试工具。它被用来测试各种各样的应用程序，所以它被设计成插件模式。为了使整个测试过程变得简单Jameleon提供了一个GUI,因此Jameleon实现了一个Swing 插件。</STRONG></P>
<P><A href="http://jameleon.sourceforge.net/index.html"><FONT color=#003366>http://jameleon.sourceforge.net/index.html</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open79343.htm"><FONT color=#003366>J2MEUnit</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<P><STRONG>J2MEUnit是应用在J2ME应用程序的一个单元测试框架。它基于JUnit.</STRONG></P>
<P><A href="http://j2meunit.sourceforge.net/"><FONT color=#003366>http://j2meunit.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;<A href="http://www.open-open.com/open83943.htm"><FONT color=#003366>Jetif</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<H2><SPAN class=NavigationColor></SPAN><FONT size=3>Jetif是一个用纯Java实现的回归测试框架。它为Java程序单元测试以及功能测试提供了一个简单而且可 伸缩的架构，可以用于个人开发或企业级开发的测试。它容易使用，功能强大，而且拥有一些企业级测试的重要功能。Jetif来源于JUnit, JTestCase以及TestNG的启发，有几个基本的概念直接来自于JUnit， 比如说断言机制，Test Listener的概念，因此从JUnit转到Jetif是非常容易的。</FONT></H2>
<P><A href="http://jetif.sourceforge.net/"><FONT color=#003366>http://jetif.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT size=2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT>&nbsp;</FONT><A href="http://www.open-open.com/open84043.htm"><FONT color=#003366>GroboUtils</FONT></A>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></H2>
<H2><SPAN class=NavigationColor></SPAN><FONT size=3>GroboUtils使得扩展Java测试变得可能。它包括用在Java不同方面测试的多个子项目。在GroboUtils中最常被到的工具是:多线程测试(multi-threaded tests),整体单元测试(hierarchial unit tests),代码覆盖工具(code coverage tool)。</FONT></H2>
<P><A href="http://groboutils.sourceforge.net/"><FONT color=#003366>http://groboutils.sourceforge.net/</FONT></A></P></DIV>
<DIV class=story>
<H2><FONT size=2><FONT color=#003366><IMG onmousewheel="return bbimg(this)" title=点击新窗口查看大图 height=14 alt="" src="http://www.open-open.com/image/item.gif" width=13 onload="java_script_:if(this.width>600)this.width=600" border=0></FONT></FONT>&nbsp;<A href="http://www.open-open.com/open85343.htm"><FONT color=#003366>Testare</FONT></A><FONT size=2>&nbsp;&nbsp;<SPAN class=NavigationColor>&nbsp;</SPAN></FONT></H2>
<H2><SPAN class=NavigationColor></SPAN><FONT size=3>TESTARE是用来简化分布式应用程序(比如:在SERVLETS,JMS listeners, CORBA ORBs或RMI环境下)测试开发过程的一个测试框架.</FONT></H2>
<P><A href="https://testare.dev.java.net/"><FONT color=#003366>https://testare.dev.java.net/</FONT></A></P></DIV></SPAN></SPAN><BR><BR>
<P id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=568616</P></DIV><img src ="http://www.blogjava.net/wangxq/aggbug/33219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-02 15:07 <a href="http://www.blogjava.net/wangxq/articles/33219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第一个 Cactus + Jetty 测试[转]</title><link>http://www.blogjava.net/wangxq/articles/33117.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 02 Mar 2006 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/33117.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/33117.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/33117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/33117.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/33117.html</trackback:ping><description><![CDATA[转自：<a href="http://www.cntesting.com/pic/study/JUnitGossip/FirstCactusWithJetty.htm">http://www.cntesting.com/pic/study/JUnitGossip/FirstCactusWithJetty.htm</a><br />在Tomcat或您的目标Container上直接执行测试的好处是，您即完成了单元测试，也测试了您的单元与 Container的交互，然而比较麻烦的是，您必须在每一次的修改之後，重新布署相关的资源、启动Container、运行测试等等，测试时较为耗时耗力。<br /><br />对於简单的In-Container单元测试，您可以使用stub的方式，stub即将真实系统的一部份引入您的程式之中，让您的程式可以与这一个部份进行交互，而不一定要将整个程式置於系统之中。<br /><br />stub的好处是，有时您并不是要测试程式与整个系统的行为，并且您也不是每次都可以将程式丢到系统之上运行，试想，您不能为了测试您的单元，而要求真正在服务客户的系统不断的重启。<br /><br />对於In-Container测试采取stub的方式，自然就是实现Container的部份功能，并将测试置於其中，在这边您可以使用 Jetty [http://jetty.mortbay.org/jetty/index.html]，它是个Java撰写的HTTP伺服器，本身也是个 Container，Cactus集成了Jetty，并提供与测试相关的简便类别。<br /><br />使用Cactus+Jetty执行测试，在更大的程度上隐藏了测试运行过程的细节，您不必关心Redirector Proxy，更不一定要关心TestCase在客户端与伺服端的行为，运行起来就如同在运作一个JUnit测试。<br /><br />使用Cactus+Jetty进行测试时，Jetty会在测试开始前完成启动，接著进行相关测试，然後Jetty会自动关闭，这很方便，另一方面，启动 Jetty会快的多了。<br /><br />要使用Cactus+Jetty，请将Cactus下载後的lib目录中的commons-logging-xxx.jar、 aspectjrt-xxx.jar、cactus-xxx.jar、commons-httpclient-xxx.jar、junit- xxx.jar以及org.mortbay.jetty-xxx.jar设定至CLASSPATH。<br /><br />接著撰写测试案例：<br /><br /><br /><ul><li>LoginServletTest.java </li></ul><pre>package onlyfun.caterpillar.test;<br /><br />import junit.framework.Test;<br />import junit.framework.TestSuite;<br /><br />import org.apache.cactus.ServletTestCase;<br />import org.apache.cactus.WebRequest;<br />import org.apache.cactus.extension.jetty.JettyTestSetup;<br /><br />import onlyfun.caterpillar.LoginServlet;<br /><br />public class LoginServletTest extends ServletTestCase {<br />    public static Test suite() {<br />        System.setProperty("cactus.contextURL", <br />                      "http://localhost:8080/cactusDemo");<br />        TestSuite suite = new TestSuite();<br />        suite.addTestSuite(LoginServletTest.class);<br />        return new JettyTestSetup(suite);<br />    }<br /><br />    public void beginValidUser(WebRequest webRequest) {<br />        webRequest.addParameter("username", "justin");<br />        webRequest.addParameter("password", "123456");<br />    }<br /><br />    public void testValidUser() {<br />        LoginServlet loginServlet = new LoginServlet();<br />        assertTrue(loginServlet.isValidUser(request));<br />    }<br /><br />    public void beginInValidUser(WebRequest webRequest) {<br />        webRequest.addParameter("username", "guest");<br />        webRequest.addParameter("password", "123456");<br />    }<br /><br />    public void testInValidUser() {<br />        LoginServlet loginServlet = new LoginServlet();<br />        assertFalse(loginServlet.isValidUser(request));<br />    }<br /><br />    public static void main(String[] args) { <br />        junit.textui.TestRunner.run(<br />                   LoginServletTest.suite()); <br />    } <br />}</pre><br />在这边要特别注意的是suite()方法，传回了一个JettyTestSetup实例，如您所想的，这个实例除了运行TestSuite之外，它还会启动Jetty。接下来依测试案例来完成程式：<br /><ul><li>LoginServlet.java </li></ul><pre>package onlyfun.caterpillar;<br /><br />import javax.servlet.http.*;<br /><br />public class LoginServlet extends HttpServlet {<br />    public boolean isValidUser(HttpServletRequest request) {<br />        String username = request.getParameter("username");<br />        String password = request.getParameter("password");<br /><br />       if(username == null || <br />          password == null ||<br />          !username.equals("justin") || <br />          !password.equals("123456")) {<br />            return false;<br />        }<br />        else {<br />            return true;<br />        }<br />    }<br />}</pre><br />然後就可以运行测试了，以下是测试的结果：<br /><table style="WIDTH: 100%; TEXT-ALIGN: left" cellspacing="2" cellpadding="2" border="0"><tbody><tr><td style="BACKGROUND-COLOR: rgb(0,0,0)"><small><span style="COLOR: rgb(255,255,255)">09:26:10.625 EVENT  Starting Jetty/4.2.17<br />09:26:10.843 EVENT  Started ServletHttpContext[/cactusDemo]<br />09:26:39.203 EVENT  Started SocketListener on 0.0.0.0:8080<br />09:26:39.203 EVENT  Started org.mortbay.jetty.Server@758fc9<br />..09:26:40.296 EVENT  Stopping Acceptor  <br />ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8080]<br />09:26:40.296 EVENT  Stopped SocketListener on 0.0.0.0:8080<br />09:26:40.296 EVENT  Stopped ServletHttpContext[/cactusDemo]<br />09:26:40.296 EVENT  Stopped org.mortbay.jetty.Server@758fc9<br /><br />Time: 31.453<br /><br />OK (2 tests)</span></small><span style="COLOR: rgb(255,255,255)"><br /></span></td></tr></tbody></table><br /><br />还可以参考<a href="http://kb.csdn.net/java/Articles/200312/2a86aa04-cbf1-4eda-98a4-902b1c974cc7.html">http://kb.csdn.net/java/Articles/200312/2a86aa04-cbf1-4eda-98a4-902b1c974cc7.html</a><br /><a href="http://www.51testing.com/html/6/23.html">http://www.51testing.com/html/6/23.html</a><img src ="http://www.blogjava.net/wangxq/aggbug/33117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-03-02 09:09 <a href="http://www.blogjava.net/wangxq/articles/33117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转—使用模仿对象Mock object进行单元测试</title><link>http://www.blogjava.net/wangxq/articles/31126.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Fri, 17 Feb 2006 01:18:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/31126.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/31126.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/31126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/31126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/31126.html</trackback:ping><description><![CDATA[<H2>使用模仿对象Mock object进行单元测试</H2>
<HR width="95%" color=red SIZE=1>
<FONT size=2>NetReptile推荐&nbsp;[2005-2-12]</FONT><BR><FONT size=2>出处：IBM DW中国</FONT><BR><FONT size=2>作者：Alexander Day Chaffe</FONT><BR><FONT size=2>&nbsp;<FONT size=+0><BR><BR>
<P>
<P>模仿对象（Mock object）是为起中介者作用的对象编写单元测试的有用方法。测试对象调用模仿域对象（它只断言以正确的次序用期望的参数调用了正确的方法），而不是调用实际域对象。然而，当测试对象必须创建域对象时，我们面临一个问题。测试对象如何知道创建模仿域对象，而不是创建实际域对象呢？在本文中，软件顾问 Alexander Day Chaffee 和 William Pietri 将演示一种重构技术，该技术根据工厂方法设计模式来创建模仿对象。</P>
<P>单元测试已作为软件开发的“最佳实践”被普遍接受。当编写对象时，还必须提供一个自动化测试类，该类包含测试该对象性能的方法、用各种参数调用其各种公用（public）方法并确保返回值是正确的。 <BR><BR>当您正在处理简单数据或服务对象时，编写单元测试很简单。然而，许多对象依赖基础结构的其它对象或层。当开始测试这些对象时，实例化这些合作者（collaborator）通常是昂贵的、不切实际的或效率低的。 <BR><BR>例如，要单元测试一个使用数据库的对象，安装、配置和发送本地数据库副本、运行测试然后再卸装本地数据库可能很麻烦。模仿对象提供了解决这一困难的方法。模仿对象符合实际对象的接口，但只要有足够的代码来“欺骗”测试对象并跟踪其行为。例如，虽然某一特定单元测试的数据库连接始终返回相同的硬连接结果，但可能会记录查询。只要正在被测试的类的行为如所期望的那样，它将不会注意到差异，而单元测试会检查是否发出了正确的查询。 <BR><BR></P>
<CENTER><FONT color=#000099><STRONG>夹在中间的模仿</STRONG></FONT></CENTER><BR><BR>使用模仿对象进行测试的常用编码样式是： <BR><BR>· 创建模仿对象的实例 <BR><BR>· 设置模仿对象中的状态和期望值 <BR><BR>· 将模仿对象作为参数来调用域代码 <BR><BR>· 验证模仿对象中的一致性 <BR><BR>虽然这种模式对于许多情况都非常有效，但模仿对象有时不能被传递到正在测试的对象。而设计该对象是为了创建、查找或获得其合作者。 <BR><BR>例如，测试对象可能需要获得对Enterprise JavaBean（EJB）组件或远程对象的引用。或者，测试对象会使用具有副作用的对象，如删除文件的File对象，而在单元测试中不希望有这些副作用。 <BR><BR>根据常识，我们知道这种情形下可以尝试重构对象，使之更便于测试。例如，可以更改方法签名，以便传入合作者对象。 <BR><BR>在 Nicholas Lesiecki 的文章“Test flexibly with AspectJ and mock objects”中，他指出重构不一定总是合意的，也不一定总是产生更清晰或更容易理解的代码。在许多情况下，更改方法签名以使合作者成为参数将会在方法的原始调用者内部产生混淆的、未经试验的代码混乱。 <BR><BR>问题的关键是该对象“在里面”获得这些对象。任何解决方案都必须应用于这个创建代码的所有出现。为了解决这个问题，Lesiecki 使用了查找方式或创建方式。在这个解决方案中，执行查找的代码被返回模仿对象的代码自动替换。 <BR><BR>因为 AspectJ 对于某些情况不是选项，所以我们在本文中提供了一个替代方法。因为在根本上这是重构，所以我们将遵循 Martin Fowler 在他创新的书籍“Refactoring: Improving the Design of Existing Code”（请参阅参考资料）中建立的表达约定。（我们的代码基于 JUnit — Java 编程的最流行的单元测试框架，尽管它决不是 JUnit 特定的。） <BR><BR>
<CENTER><FONT color=#000099><STRONG>重构：抽取和覆盖工厂方法</STRONG></FONT></CENTER><BR><BR>重构是一种代码更改，它使原始功能保持不变，但更改代码设计，使它变得更清晰、更有效且更易于测试。本节将循序渐进地描述“抽取”和“覆盖”工厂方法重构。 <BR><BR>问题：正在测试的对象创建了合作者对象。必须用模仿对象替换这个合作者。 <BR><BR>重构之前的代码： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>class Application {
...
  public void run() {
    View v = new View();
    v.display();
...</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>解决方案：将创建代码抽取到工厂方法，在测试子类中覆盖该工厂方法，然后使被覆盖的方法返回模仿对象。最后，如果可以的话，添加需要原始对象的工厂方法的单元测试，以返回正确类型的对象： <BR><BR>重构之后的代码： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>class Application {
...
  public void run() {
    View v = createView();
    v.display();
...
  protected View createView() {
    return new View();
  }
...
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>该重构启用清单1中所示的单元测试代码： <BR><BR>清单 1. 单元测试代码 <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>class ApplicationTest extends TestCase {
  MockView mockView = new MockView();
  public void testApplication {
    Application a = new Application() {
      protected View createView() {
        return mockView;
      }
    };
    a.run();
    mockView.validate();
  }
  private class MockView extends View
  {
    boolean isDisplayed = false;
    public void display() {
      isDisplayed = true;
    }
    public void validate() {
      assertTrue(isDisplayed);
    }
  }
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR><B>角色</B> <BR><BR>该设计引入了由系统中的对象扮演的下列角色： <BR><BR>· 目标对象：正在测试的对象 <BR><BR>· 合作者对象：由目标对象创建或获取的对象 <BR><BR>· 模仿对象：遵循模仿对象模式的合作者的子类（或实现） <BR><BR>· 特殊化对象：覆盖创建方法以返回模仿对象而不是合作者的目标的子类 <BR><BR><B>技巧</B> <BR><BR>重构由许多小的技术性步骤组成。这些步骤统称为技巧。如果您象按照食谱那样严格遵循这些技术，那么您在学习重构时应该没有太大的麻烦。 <BR><BR>标识创建或获取合作者的代码的所有出现。 <BR><BR>将抽取方法重构应用于这个创建代码，创建工厂方法（在Fowler书籍的第110页中讨论；有关更多信息，请参阅参考资料一节）。 <BR><BR>确保目标对象及其子类可以访问工厂方法。（在 Java 语言中，使用 protected 关键字）。 <BR><BR>在测试代码中，创建模仿对象且实现与合作者相同的接口。 <BR><BR>在测试代码中，创建扩展（专用于）目标对象的特殊化对象。 <BR><BR>在特殊化对象中，覆盖创建方法以返回为测试提供的模仿对象。 <BR><BR>可选的：创建单元测试以确保原始目标对象的工厂方法仍返回正确的非模仿对象。 <BR><BR>示例：ATM <BR><BR>设想您正在编写用于银行自动柜员机（Automatic Teller Machine）的测试。其中一个测试可能类似于清单 2： <BR><BR>清单 2. 初始单元测试，在模仿对象引入之前： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>public void testCheckingWithdrawal() {
    float startingBalance = balanceForTestCheckingAccount();
    AtmGui atm = new AtmGui();
    insertCardAndInputPin(atm);
    atm.pressButton("Withdraw");
    atm.pressButton("Checking");
    atm.pressButtons("1", "0", "0", "0", "0");
    assertContains("$100.00", atm.getDisplayContents());
    atm.pressButton("Continue");
    assertEquals(startingBalance - 100,
balanceForTestCheckingAccount());
  }</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>另外，AtmGui 类内部的匹配代码可能类似于清单 3： <BR><BR>清单 3. 产品代码，在重构之前： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>private Status doWithdrawal(Account account, float amount) {
    Transaction transaction = new Transaction();
    transaction.setSourceAccount(account);
    transaction.setDestAccount(myCashAccount());
    transaction.setAmount(amount);
    transaction.process();
    if (transaction.successful()) {
      dispense(amount);
    }
    return transaction.getStatus();
  }</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>该方法将起作用，遗憾的是，它有一个副作用：支票帐户余额比测试开始时少，这使得其它测试变得更困难。有一些解决这种困难的方法，但它们都会增加测试的复杂性。更糟的是，该方法还需要对管理货币的系统进行三次往返。 <BR><BR>要修正这个问题，第一步是重构 AtmGui 以允许我们用模仿事务替换实际事务，如清单 4 中所示（比较粗体的源代码以查看我们正在更改什么）： <BR><BR>清单 4. 重构 <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>AtmGui  private Status doWithdrawal(Account account, float amount) {
    Transaction transaction = createTransaction();
    transaction.setSourceAccount(account);
    transaction.setDestAccount(myCashAccount());
    transaction.setAmount(amount);
    transaction.process();
    if (transaction.successful()) {
      dispense(amount);
    }
    return transaction.getStatus();
  }
   protected Transaction createTransaction() {
    return new Transaction();
  }</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>后退到测试类内部，我们将 MockTransaction 类定义为成员类，如清单 5 中所示： <BR><BR>清单 5. 将 MockTransaction 定义为成员类： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>private MockTransaction extends Transaction {
    private boolean processCalled = false;
    // override process method so that no real work is done
    public void process() {
      processCalled = true;
      setStatus(Status.SUCCESS);
    }
    public void validate() {
      assertTrue(processCalled);
    }
  }</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>最后，我们可以重写测试，以便被测试的对象使用 MockTransaction 类，而不是使用实际类，如清单 6 中所示： <BR><BR>清单 6. 使用 MockTransaction 类 <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>MockTransaction mockTransaction;
  public void testCheckingWithdrawal() {
    mockTransaction = new MockTransaction();
    AtmGui atm = new AtmGui() {
        protected Transaction createTransaction() {
          return mockTransaction;
        }
    };
    insertCardAndInputPin(atm);
    atm.pressButton("Withdraw");
    atm.pressButton("Checking");
    atm.pressButtons("1", "0", "0", "0", "0");
    assertContains("$100.00", atm.getDisplayContents());
    atm.pressButton("Continue");
    assertEquals(100.00, mockTransaction.getAmount());
    assertEquals(TEST_CHECKING_ACCOUNT,
mockTransaction.getSourceAccount());
    assertEquals(TEST_CASH_ACCOUNT,
mockTransaction.getDestAccount());
    mockTransaction.validate();
}</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>该解决方案产生了一个稍长的测试，但该测试只关注正在测试的类的直接行为，而不是 ATM 接口之外整个系统的行为。也就是说，我们不再检查测试帐户的最终余额是否正确；我们将在对 Transaction 对象的单元测试中检查该函数，而不是在对 AtmGui 对象的单元测试中。 <BR><BR>注：根据模仿对象的创造者所说，它应该在其 validate() 方法内部执行自己的所有验证。在本示例中，为了清晰起见，我们将验证的某些部分放在了测试方法内部。随着您更加熟练地使用模仿对象，对于将多少验证职责代理给模仿对象，您将会深有体会。 <BR><BR><B>内部类魔法</B> <BR><BR>在清单 6 中，我们使用了 AtmGui 的匿名内部子类来覆盖 createTransaction 方法。因为我们只需要覆盖一个简单的方法，所以这是实现我们目标的简明方法。如果我们覆盖多个方法或在许多测试之间共享 AtmGui 子类，那么创建一个完整的（非匿名）成员类是值得的。 <BR><BR>我们还使用了实例变量来存储对模仿对象的引用。这是在测试方法和特殊化类之间共享数据的最简单方法。这是可以接受的，因为我们的测试框架不是多线程的或可重入的。（如果它是多线程的或可重入的，则必须用 synchronized 块保护我们自己。） <BR><BR>最后，我们将模仿对象本身定义为测试类的专用内部类 — 这通常是一种便利的方法，因为将模仿对象就放在使用它的测试代码旁边会更加清楚，又因为内部类有权访问包含它们的类的实例变量。 <BR><BR><B>小心不出大错</B> <BR><BR>因为我们覆盖了工厂方法来编写这个测试，所以其结果是：我们的测试不再包括任何原始创建代码（现在它在基类的工厂方法内部）。添加确实包括该代码的测试也许是有益的。这与调用基类的工厂方法并断言返回对象具有正确类型一样简单。例如： <BR><BR><CCID_NOBR>
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=black border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE>AtmGui atm = new AtmGui();
    Transaction t = atm.createTransaction();
    assertTrue(!(t instanceof MockTransaction));</CCID_CODE></PRE></TD></TR></TBODY></TABLE></CCID_NOBR><BR><BR>注：相反，assertTrue(t instanceof Transaction) 不能满足，因为 MockTransaction 也是 Transaction。 <BR><BR>
<CENTER><FONT color=#000099><STRONG>从工厂方法到抽象工厂</STRONG></FONT></CENTER><BR><BR>此时，您可能很想更进一步并用成熟的抽象工厂对象替换工厂方法，如 Erich Gamma 等人在设计模式中详细描述的那样。（请参阅参考资料）。实际上，许多人已经用工厂对象来着手这种方法，而不是用工厂方法 — 我们以前是这样做的，但很快就放弃了。 <BR><BR>将第三种对象类型（角色）引入系统会有一些潜在的缺点： <BR><BR>它增加了复杂性，而没有相应地增加功能。 <BR><BR>它会迫使您更改目标对象的公用接口。如果必须传入抽象工厂对象，那么您必须添加一个新的公用构造函数或赋值（mutator）方法。 <BR><BR>许多语言对于“工厂”这一概念都附有一些约定，它们会使您误入歧途。例如，在 Java 语言中，工厂通常作为静态方法实现；在这种情况下，这是不合适的。 <BR><BR>请记住，本练习的宗旨是使对象更易于测试。通常，用于可测性的设计可以将对象的 API 推向一种更清晰更模块化的状态。但它会走得太远。测试驱动的设计更改不应该污染原始对象的公用接口。 <BR><BR>在 ATM 示例中，对于产品代码，AtmGui 对象始终只产生一种类型的 Transaction 对象（实际类型）。测试代码希望它产生另一种类型的对象（模仿对象）。但强迫公用 API 适应工厂对象或抽象工厂（只因为测试代码要求它这样）是错误的设计。如果产品代码无需实例化该合作者的多个类型，那么添加该功能将使最终的设计不必要地变得难于理解。 <BR></FONT></FONT><img src ="http://www.blogjava.net/wangxq/aggbug/31126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2006-02-17 09:18 <a href="http://www.blogjava.net/wangxq/articles/31126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转----Java语言中的面向对象特性</title><link>http://www.blogjava.net/wangxq/articles/13086.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 15 Sep 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/13086.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/13086.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/13086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/13086.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/13086.html</trackback:ping><description><![CDATA[<TABLE class=showinfo style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all" cellSpacing=0 cellPadding=3 width="100%" align=center border=0>
<TBODY>
<TR>
<TD class=showTitle align=middle>第三讲　Java语言中的面向对象特性</TD></TR>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 align=left border=0>
<TBODY>
<TR>
<TD>
<SCRIPT language=javascript src="/ad/js/edu_left_300-300.js"></SCRIPT>
</TD></TR></TBODY></TABLE>【课前思考】 <BR>　　1． 什么是对象？什么是类？什么是包？什么是接口？什么是内部类？ <BR>　　2． 面向对象编程的特性有哪三个？它们各自又有哪些特性？ <BR>　　3． 你知道java语言在面向对象编程方面有何独特的特点吗？ <BR><BR>难点： <BR>　　1． 理解方法重载和方法重写，不要混淆了两者的使用。 <BR>　　2． 类变量和类方法的使用。 <BR>　　3． 接口的使用。 <BR>3．1 面向对象技术基础 <BR><BR>3．1．1 面向对象的基本概念 <BR>　　面向对象的基本思想 <BR>　　面向对象是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物（即对象）出发来构造软件系统，并且在系统构造中尽可能运用人类的自然思维方式。开发一个软件是为了解决某些问题，这些问题所涉及的业务范围称作该软件的问题域。其应用领域不仅仅是软件，还有计算机体系结构和人工智能等。 <BR><BR>1． 对象的基本概念 <BR>　　对象是系统中用来描述客观事物的一个实体，它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。 <BR><BR>主动对象是一组属性和一组服务的封装体，其中至少有一个服务不需要接收消息就能主动执行（称作主动服务）。 <BR>2． 类的基本概念 <BR>类是具有相同属性和服务的一组对象的集合，它为属于该类的所有对象提供了统一的抽象描述，其内部包括属性和服务两个主要部分。在面向对象的编程语言中，类是一个独立的程序单位，它应该有一个类名并包括属性说明和服务说明两个主要部分。 <BR><BR>3． 消息 <BR><BR>消息就是向对象发出的服务请求，它应该包含下述信息：提供服务的对象标识、服务标识、输入信息和回答信息。服务通常被称为方法或函数。 <BR><BR>3．1．2 面向对象的基本特征 <BR><BR>1．封装性 <BR>　　封装性就是把对象的属性和服务结合成一个独立的相同单位，并尽可能隐蔽对象的内部细节，包含两个含义： <BR>　　◇ 把对象的全部属性和全部服务结合在一起，形成一个不可分割的独立单位（即对象）。 <BR>　　◇ 信息隐蔽，即尽可能隐蔽对象的内部细节，对外形成一个边界〔或者说形成一道屏障〕，只保留有限的对外接口使之与外部发生联系。 <BR>　　封装的原则在软件上的反映是：要求使对象以外的部分不能随意存取对象的内部数据（属性），从而有效的避免了外部错误对它的"交叉感染"，使软件错误能够局部化，大大减少查错和排错的难度。 <BR><BR>2．继承性 <BR>　　特殊类的对象拥有其一般类的全部属性与服务，称作特殊类对一般类的继承。 <BR><BR>一个类可以是多个一般类的特殊类，它从多个一般类中继承了属性与服务，这称为多继承。 <BR><BR>在java语言中，通常我们称一般类为父类（superclass,超类），特殊类为子类(subclass)。 <BR><BR>3．多态性 <BR>　　对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后，可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或服务在一般类及其各个特殊类中具有不同的语义。例如："几何图形"的"绘图"方法，"椭圆"和"多边形"都是"几何图"的子类，其"绘图"方法功能不同。 <BR>3．1．3 面向对象程序设计方法 <BR>　　OOA－Object Oriented Analysis 　　　　面向对象的分析 <BR>　　OOD－Object Oriented Design 　　　　　面向对象的设计 <BR>　　OOI－Object Oriented Implementation 　面向对象的实现 <BR>3．2 Java语言的面向对象特性 <BR><BR>3．2．1 类 <BR>　　类是java中的一种重要的复合数据类型，是组成java程序的基本要素。它封装了一类对象的状态和方法，是这一类对象的原形。一个类的实现包括两个部分：类声明和类体 <BR><BR>1．类声明： <BR>　　[public][abstract|final] class className [extends superclassName] [implements interfaceNameList] <BR>　　{……} <BR>　　其中，修饰符public,abstract,final 说明了类的属性，className为类名，superclassName为类的父类的名字，interfaceNameList为类所实现的接口列表。 <BR>　2．类体 <BR>　　类体定义如下： <BR>　　class className <BR>　　{[public | protected | private ] [static] <BR>　　[final] [transient] [volatile] type <BR>　　variableName;　　　　　　　　　　　　　　　　　//成员变量 <BR>　　[public | protected | private ] [static] <BR>　　[final | abstract] [native] [synchronized] <BR>　　returnType methodName([paramList]) [throws exceptionList] <BR>　　　{statements} 　　　　　　　　　　　　　　　 //成员方法 <BR>　　} <BR>　3．成员变量 <BR>　　成员变量的声明方式如下： <BR>　　[public | protected | private ] [static] <BR>　　[final] [transient] [volatile] type <BR>　　variableName; 　　　　　　　　　　　　　　　　//成员变量 <BR>　　其中， <BR>　　static: 静态变量（类变量）；相对于实例变量 <BR>　　final: 常量 <BR>　　transient: 暂时性变量，用于对象存档，用于对象的串行化，见对象的串行化一节 <BR>　　volatile: 贡献变量，用于并发线程的共享 <BR>　4．成员方法 <BR>　　方法的实现包括两部分内容：方法声明和方法体。 <BR>　　[public | protected | private ] [static] <BR>　　[final　| abstract] [native] [synchronized] <BR>　　returnType methodName([paramList]) <BR>　　[throws exceptionList] 　　　　　　　　　　　//方法声明 <BR>　　　{statements} 　　　　　　　　　　　　　　　//方法体 <BR>　　方法声明中的限定词的含义： <BR>　　static: 类方法，可通过类名直接调用 <BR>　　abstract: 抽象方法，没有方法体 <BR>　　final: 方法不能被重写 <BR>　　native: 集成其它语言的代码 <BR>　　synchronized: 控制多个并发线程的访问 <BR>　　◇ 方法声明 <BR>　　方法声明包括方法名、返回类型和外部参数。其中参数的类型可以是简单数据类型，也可以是复合数据类型（又称引用数据类型）。 <BR>　　对于简单数据类型来说，java实现的是值传递，方法接收参数的值，但不能改变这些参数的值。如果要改变参数的值，则用引用数据类型，因为引用数据类型传递给方法的是数据在内存中的地址，方法中对数据的操作可以改变数据的值。 <BR>　　例3-1说明了简单数据类型与引用数据的区别。 <BR>【例3-1】 <BR>　　import java.io.*; <BR>　　public class PassTest{ <BR>　　float ptValue; <BR>　　public static void main(String args[]) { <BR>　　int val; <BR>　　PassTest pt=new PassTest(); <BR>　　val=11; <BR>　　System.out.println("Original Int Value is:"+val); <BR>　　pt.changeInt(val); 　　　　　　　　　　　　　　　　　　//值参数 <BR>　　System.out.println("Int Value after Change is:" +val); /*值参数 <BR>　　　　　　　　　　　　　　　　　　　 值的修改，没有影响值参数的值*/ <BR>　　pt.ptValue=101f; <BR>　　System.out.println("Original ptValue is:"+pt.ptValue); <BR>　　pt.changeObjValue(pt); //引用类型的参数 <BR>　　System.out.println("ptValue after Change is:"+pt.ptValue);/* 引用参数值的修改，改变了引用参数的值*/ <BR>　　} <BR>　　public void changeInt(int value){ <BR>　　value=55; 　　　　　　　　　　　//在方法内部对值参数进行了修改 <BR>　　} <BR>　　public void changeObjValue(PassTest ref){ <BR>　　ref.ptValue=99f; 　　　　　　 //在方法内部对引用参数进行了修改 <BR>　　　　} <BR>　　} <BR><BR>◇ 方法体 <BR>　　方法体是对方法的实现，它包括局部变量的声明以及所有合法的Java指令。方法体中声明的局部变量的作用域在该方法内部。若局部变量与类的成员变量同名，则类的成员变量被隐藏。 <BR>为了区别参数和类的成员变量，我们必须使用this。this-----用在一个方法中引用当前对象，它的值是调用该方法的对象。返回值须与返回类型一致，或者完全相同，或是其子类。当返回类型是接口时，返回值必须实现该接口。 <BR>5．方法重载 <BR>　方法重载是指多个方法享有相同的名字，但是这些方法的参数必须不同，或者是参数的个数不同，或者是参数类型不同。返回类型不能用来区分重载的方法。 <BR>　　参数类型的区分度一定要足够，例如不能是同一简单类型的参数，如int与long。编译器会根据参数的个数和类型来决定当前所使用的方法。 <BR><BR>6． 构造方法 <BR>　　◇ 构造方法是一个特殊的方法。Java 中的每个类都有构造方法，用来初始化该类的一个对象。 <BR>　　◇ 构造方法具有和类名相同的名称，而且不返回任何数据类型。 <BR>　　◇ 重载经常用于构造方法。 <BR>　　◇ 构造方法只能由new运算符调用 <BR><BR>3．2．2 对象 <BR>　　类实例化可生成对象，对象通过消息传递来进行交互。消息传递即激活指定的某个对象的方法以改变其状态或让它产生一定的行为。一个对象的生命周期包括三个阶段：生成、使用和消除。 <BR><BR>对象的清除 <BR>　　当不存在对一个对象的引用时，该对象成为一个无用对象。Java的垃圾收集器自动扫描对象的动态内存区，把没有引用的对象作为垃圾收集起来并释放。 <BR>　　System.gc( );　　System.exit();//terminate the current JVM <BR>　　当系统内存用尽或调用System.gc( )要求垃圾回收时，垃圾回收线程与系统同步运行。 <BR>3．2．3 面向对象特性 <BR>　　java语言中有三个典型的面向对象的特性：封装性、继承性和多态性。 <BR><BR>1． 封装性 <BR>　　java语言中，对象就是对一组变量和相关方法的封装，其中变量表明了对象的状态，方法表明了对象具有的行为。通过对象的封装，实现了模块化和信息隐藏。通过对类的成员施以一定的访问权限，实现了类中成员的信息隐藏。 <BR>◇ java类中的限定词 <BR>　　java语言中有四种不同的限定词，提供了四种不同的访问权限。 <BR>　　1） private <BR>　　类中限定为private的成员，只能被这个类本身访问。 <BR>　　如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。 <BR>　　2） default <BR>　　类中不加任何访问权限限定的成员属于缺省的（default）访问状态：friend，可以被这个类本身和同一个包中的类所访问。 <BR>3） protected <BR>　　类中限定为protected的成员，可以被这个类本身、它的子类（包括同一个包中以及不同包中的子类）和同一个包中的所有其他的类访问。 <BR>4） public <BR>　　类中限定为public的成员，可以被所有的类访问。 <BR>【表3-1】　java中类的限定词的作用范围比较 <BR><BR><BR>同一个类 <BR>同一个包 <BR>不同包的子类 <BR>不同包非子类 <BR><BR>private <BR>* <BR><BR><BR><BR><BR>default <BR>* <BR>* <BR><BR><BR><BR>protected <BR>* <BR>* <BR>* <BR><BR><BR>public <BR>* <BR>* <BR>* <BR>* <BR><BR><BR><BR><BR>2． 继承性 <BR>　　通过继承实现代码复用。Java中所有的类都是通过直接或间接地继承java.lang.Object类得到的。继承而得到的类称为子类，被继承的类称为父类。子类不能继承父类中访问权限为private的成员变量和方法。子类可以重写父类的方法，及命名与父类同名的成员变量。但Java不支持多重继承，即一个类从多个超类派生的能力。 <BR>◇ 成员变量的隐藏和方法的重写 <BR>　　子类通过隐藏父类的成员变量和重写父类的方法，可以把父类的状态和行为改变为自身的状态和行为。 <BR>例如： <BR>　　class SuperClass{ <BR>　　　　int x; … <BR>　　　　void setX( ){ x=0; } … <BR>　　} <BR>　　class SubClass extends SuperClass{ <BR>　　　　int x; 　　//隐藏了父类的变量x <BR>　　　　… <BR>　　　　void setX( ) { //重写了父类的方法 setX() <BR>　　　　x=5; } …. <BR>　　} <BR>　　注意：子类中重写的方法和父类中被重写的方法要具有相同的名字，相同的参数表和相同的返回类型，只是函数体不同。 <BR>　　◇ super <BR>　　java中通过super来实现对父类成员的访问，super用来引用当前对象的父类。Super 的使用有三种情况： <BR>　　1）访问父类被隐藏的成员变量，如： <BR>　　　　super.variable; <BR>　　2）调用父类中被重写的方法，如： <BR>　　　　super.Method([paramlist]); <BR>　　3）调用父类的构造函数，如： <BR>　　　　super([paramlist]); <BR><BR>【例3-5】 <BR>　　import java.io.*; <BR>　　class SuperClass{ <BR>　　　　int x; <BR>　　　　SuperClass( ) { <BR>　　　　　x=3; <BR>　　　　　System.out.println("in SuperClass : x=" +x); <BR>　　　　} <BR>　　　　　void doSomething( ) { <BR>　　　　　System.out.println("in SuperClass.doSomething()"); <BR>　　　　} <BR>　　} <BR>　　class SubClass extends SuperClass { <BR>　　　　int x; <BR>　　　　SubClass( ) { <BR>　　　　　super( ); 　　　//调用父类的构造方法 <BR>　　　　　x=5;　　　　　　//super( ) 要放在方法中的第一句 <BR>　　　　　System.out.println("in SubClass :x="+x); <BR>　　　　} <BR>　　　　　void doSomething( ) { <BR>　　　　　super.doSomething( ); //调用父类的方法 <BR>　　　　　System.out.println("in SubClass.doSomething()"); <BR>　　　　　System.out.println("super.x="+super.x+" sub.x="+x); <BR>　　　　} <BR>　　} <BR>　　public class Inheritance { <BR>　　　　　public static void main(String args[]) { <BR>　　　　　SubClass subC=new SubClass(); <BR>　　　　　subC.doSomething(); <BR>　　　　} <BR>　　} <BR><BR>3． 多态性 <BR>　　在java语言中，多态性体现在两个方面：由方法重载实现的静态多态性（编译时多态）和方法重写实现的动态多态性（运行时多态）。 <BR>　　1） 编译时多态 <BR>　　在编译阶段，具体调用哪个被重载的方法，编译器会根据参数的不同来静态确定调用相应的方法。 <BR>　　2） 运行时多态 <BR>　　由于子类继承了父类所有的属性（私有的除外），所以子类对象可以作为父类对象使用。程序中凡是使用父类对象的地方，都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法。 <BR>　　◇ 重写方法的调用原则：java运行时系统根据调用该方法的实例，来决定调用哪个方法。对子类的一个实例，如果子类重写了父类的方法，则运行时系统调用子类的方法；如果子类继承了父类的方法（未重写），则运行时系统调用父类的方法。 <BR>在例3-6中，父类对象a引用的是子类的实例，所以，java运行时调用子类B的callme方法。 <BR><BR>【例3-6】 <BR>　　import java.io.*; <BR>　　class A{ <BR>　　　　　void callme( ) { <BR>　　　　　　System.out.println("Inside A''s callme()method"); <BR>　　　　　} <BR>　　} <BR>　　class B extends A{ <BR>　　　　　void callme( ) { <BR>　　　　　　System.out.println("Inside B''s callme() Method"); <BR>　　　　　} <BR>　　} <BR>　　public class Dispatch{ <BR>　　　　　public static void main(String args[]) { <BR>　　　　　　A a=new B(); <BR>　　　　　　a.callme( ); <BR>　　　　　} <BR>　　} <BR>◇ 方法重写时应遵循的原则： <BR>　　1）改写后的方法不能比被重写的方法有更严格的访问权限（可以相同）。 <BR>　　2）改写后的方法不能比重写的方法产生更多的例外。 <BR>4． 其它 <BR>　　◇ final 关键字 <BR>　　final 关键字可以修饰类、类的成员变量和成员方法，但final 的作用不同。 <BR>　　1） final 修饰成员变量： <BR>　　final修饰变量,则成为常量，例如 <BR>　　final type variableName; <BR>　　修饰成员变量时，定义时同时给出初始值，且以后不能被修改，而修饰局部变量时不做要求。 <BR>　　2） final 修饰成员方法： <BR>　　final修饰方法，则该方法不能被子类重写 <BR>　　final returnType methodName(paramList){ <BR>　　… <BR>　　} <BR><BR>　　3） final 类： <BR>　　final修饰类，则类不能被继承 <BR>　　final class finalClassName{ <BR>　　… <BR>　　} <BR>　　◇ 实例成员和类成员 <BR>　　用static 关键字可以声明类变量和类方法，其格式如下： <BR>　　static type classVar; <BR>　　static returnType classMethod({paramlist}) { <BR>　　… <BR>　　} <BR>　如果在声明时不用static 关键字修饰，则声明为实例变量和实例方法。 <BR>　　1） 实例变量和类变量 <BR>　　每个对象的实例变量都分配内存，通过该对象来访问这些实例变量，不同的实例变量是不同的。 <BR>　　类变量仅在生成第一个对象时分配内存，所有实例对象共享同一个类变量，每个实例对象对类变量的改变都会影响到其它的实例对象。类变量可通过类名直接访问，无需先生成一个实例对象，也可以通过实例对象访问类变量。 <BR>　　2） 实例方法和类方法 <BR>　　实例方法可以对当前对象的实例变量进行操作，也可以对类变量进行操作，实例方法由实例对象调用。 <BR>　　但类方法不能访问实例变量，只能访问类变量。类方法可以由类名直接调用，也可由实例对象进行调用。类方法中不能使用this或super关键字。 <BR>　　例3-7 是关于实例成员和类成员的例子。 <BR>【例3-7】 <BR>　　class Member { <BR>　　　　static int classVar; <BR>　　　　int instanceVar; <BR>　　　　static void setClassVar(int i) { <BR>　　　　　classVar=i; <BR>　　　　　// instanceVar=i; // 类方法不能访问实例变量 <BR>　　　　} <BR>　　　　static int getClassVar() <BR>　　　　　{ return classVar; } <BR>　　　　void setInstanceVar(int i) <BR>　　　　　{ classVar=i; //实例方法不但可以访问类变量，也可以实例变量 <BR>　　　　　instanceVar=i; } <BR>　　　　　int getInstanceVar( ) <BR>　　　　　{ return instanceVar; } <BR>　　　　} <BR>　　　　public class MemberTest{ <BR>　　　　　public static void main(String args[]) { <BR>　　　　　　　　 Member m1=new member(); <BR>　　　　　　　　 Member m2=new member(); <BR>　　　　　　　　 m1.setClassVar(1); <BR>　　　　　　　　 m2.setClassVar(2); <BR>　　　　　　　　 System.out.println("m1.classVar="+m1.getClassVar()+" <BR>　　　　　　　　 　　　　　　　　　　m2.ClassVar="+m2.getClassVar()); <BR>　　　　　　　　 m1.setInstanceVar(11); <BR>　　　　　　　　 m2.setInstanceVar(22); <BR>　　　　　　　　 System.out.println("m1.InstanceVar="+m1.getInstanceVar <BR>　　　　　　　　　　　　　　()+" m2.InstanceVar="+m2.getInstanceVar()); <BR>　　　　　} <BR>　　　　} <BR>◇ 类java.lang.Object <BR>　　类java.lang.Object处于java开发环境的类层次的根部，其它所有的类都是直接或间接地继承了此类。该类定义了一些最基本的状态和行为。下面，我们介绍一些常用的方法。 <BR>　　equals() ：比较两个对象(引用)是否相同。 <BR>　　getClass()：返回对象运行时所对应的类的表示，从而可得到相应的信息。 <BR>　　toString()：用来返回对象的字符串表示。 <BR>　　finalize()：用于在垃圾收集前清除对象。 <BR>　　notify(),notifyAll(),wait()：用于多线程处理中的同步。 <BR><BR>3．2．4抽象类和接口 <BR><BR>　1． 抽象类 <BR>　　java语言中，用abstract 关键字来修饰一个类时，这个类叫做抽象类，用abstract 关键字来修饰一个方法时，这个方法叫做抽象方法。格式如下： <BR>　　abstract class abstractClass{ …} //抽象类 <BR>　　abstract returnType abstractMethod([paramlist]) //抽象方法 <BR>　　抽象类必须被继承，抽象方法必须被重写。抽象方法只需声明，无需实现；抽象类不能被实例化，抽象类不一定要包含抽象方法。若类中包含了抽象方法，则该类必须被定义为抽象类。 <BR><BR>若一个类继承了一个抽象类，则抽象类的抽象方法必须被实现，否则子类必须声明为abstract. <BR>　2． 接口 <BR>　　接口是抽象类的一种，只包含常量和方法的定义，而没有变量和方法的实现，且其方法都是抽象方法。它的用处体现在下面几个方面： <BR>　　◇ 通过接口实现不相关类的相同行为,而无需考虑这些类之间的关系。 <BR>　　◇ 通过接口指明多个类需要实现的方法。 <BR>　　◇ 通过接口了解对象的交互界面,而无需了解对象所对应的类。 <BR>1）接口的定义 <BR>　　接口的定义包括接口声明和接口体。 <BR>　　接口声明的格式如下： <BR>　　[public] interface interfaceName[extends listOfSuperInterface] { … } <BR>　 extends 子句与类声明的extends子句基本相同，不同的是一个接口可有多个父接口，用逗号隔开，而一个类只能有一个父类。 <BR>　　接口体包括常量定义和方法定义 <BR>　　常量定义格式为：type NAME=value; 该常量被实现该接口的多个类共享; 具有public ,final, static的属性。在接口中只能声明常量，不可以声明变量。 <BR>　　方法体定义格式为：(具有 public和abstract属性，不能声明为protected) <BR>　　returnType methodName([paramlist])； <BR><BR>注意：在接口的实现类中，实现的接口方法必须声明为public ，因为接口中定义的方法为public（默认）。所以其实现必须声明为public.否则编译不会通过。 <BR>2）接口的实现 <BR>　　在类的声明中用implements子句来表示一个类使用某个接口，在类体中可以使用接口中定义的常量，而且必须实现接口中定义的所有方法。一个类可以实现多个接口,在implements子句中用逗号分开。 <BR>3） 接口类型的使用 <BR>　　接口作为一种引用类型来使用。任何实现该接口的类的实例都可以存储在该接口类型的变量中，通过这些变量可以访问类所实现的接口中的方法。 <BR>3．2．5 内部类 <BR><BR>　1． 内部类的定义和使用： <BR>　　内部类是在一个类的内部嵌套定义的类，它可以是其它类的成员，也可以在一个语句块的内部定义，还可以在表达式内部匿名定义。 <BR>　　内部类有如下特性： <BR>　　◇ 一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称.名字不能与包含它的类名相同。 <BR>　　◇ 可以使用包含它的类的静态和实例成员变量,也可以使用它所在方法的局部变量。 <BR>　　◇ 可以定义为abstract。 <BR>　　◇ 可以声明为private或protected。 <BR>　　◇ 若被声明为static,就变成了顶层类,不能再使用局部变量。 <BR>　　◇ 若想在Inner Class中声明任何static成员,则该Inner Class必须声明为static。 <BR>例3-8】 <BR>　　import java.awt.*; <BR>　　import java.awt.event.*; <BR>　　public class TwoListenInner { <BR>　　　　private Frame f; <BR>　　　　private TextField tf; <BR>　　　　　　public static void main(String args[]) { <BR>　　　　　　　TwoListenInner that=new TwoListenInner(); <BR>　　　　　　　that.go(); <BR>　　　　} <BR>　　　　public void go() { <BR>　　　　　　　f=new Frame("Two listeners example"); <BR>　　　　　　　f.add("North",new Label("Click and drag the mouse")); <BR>　　　　　　　tf=new TextField(30); <BR>　　　　　　　f.add("South",tf); <BR>　　　　　　　f.addMouseMotionListener(new MouseMotionHandler()); <BR>　　　　　　　f.addMouseListener(new MouseEventHandler()); <BR>　　　　　　　f.setSize(300,300); <BR>　　　　　　　f.setVisible(true); <BR>　　　　} <BR>　　　　public class MouseMotionHandler extends MouseMotionAdapter { <BR>　　　　　　public void mouseDragged(MouseEvent e){ <BR>　　　　　　　String s="Mouse dragging:X="+e.getX()+"Y="+e.getY(); <BR>　　　　　　　tf.setText(s); <BR>　　　　　　} <BR>　　　　} <BR>　　　　public class MouseEventHandler extends MouseAdapter { <BR>　　　　　　public void mouseEntered(MouseEvent e){ <BR>　　　　　　　String s="The mouse entered"; <BR>　　　　　　　tf.setText(s); <BR>　　　　　　} <BR>　　　　　　public void mouseExited(MouseEvent e){ <BR>　　　　　　　String s="The mouse left the building"; <BR>　　　　　　　tf.setText(s); <BR>　　　　　　} <BR>　　　　} <BR>　　} <BR><BR>说明：Frame类的add方法来自于其祖先类Container类，addMouseMotionListener和addMouseListener方法来自于其祖先类Component, addMouseListener方法的参数为MouseListener接口，MouseAdapter类是实现了MouseListener接口的类。可见图形界面对于外部事件的响应是通过添加listener实现的 <BR>2． 匿名类的定义和使用： <BR>　　匿名类是一种特殊的内部类，它是在一个表达式内部包含一个完整的类定义。通过对例6-7中go()部分语句的修改，我们可以看到匿名类的使用情况。 <BR>　　public void go() { <BR>　　　　　　　　　f=new Frame("Two listeners example"); <BR>　　　　　　　　　f.add("North",new Label("Click and drag the mouse")); <BR>　　　　　　　　　tf=new TextField(30); <BR>　　　　　　　　　f.add("South",tf); <BR>　　　　　　　　　f.addMouseMotionListener(new MouseMotionHandler(){ <BR>　　　　　　　　　/*定义了一个匿名类，类名没有显式地给出，只是该类是 <BR>　　　　　　　　　　MouseMotionHandler类的子类*/ <BR>　　　　　　　　　　　public void mouseDragged(MouseEvent e){ <BR>　　　　　　　　　　　　　String s="Mouse dragging:X="+e.getX()+"Y <BR>　　　　　　　　　　　　　="+e.getY(); <BR>　　　　　　　　　　　　　tf.setText(s); <BR>　　　　　　　　　　　} <BR>　　　　　　　　　}); <BR>　　　　　　　　　f.addMouseListener(new MouseEventHandler()); <BR>　　　　　　　　　f.setSize(300,300); <BR>　　　　　　　　　f.setVisible(true); <BR>　　　　　　　　　} <BR>　3． 内部类的优缺点： <BR>　　◇ 优点:节省编译后产生的字节码文件的大小 <BR>　　◇ 缺点:使程序结构不清楚 <BR><BR>习题： <BR><BR>1 ：造型不可以从父类向子类造型，只能从子类向父类造型。否则编译 时可以通过，执行时会报错 <BR><BR>如：SubClass sc = new SubClass(); BaseClass bc = (BaseClass)sc ;---是正确的 <BR><BR>而 BaseClass bc = new BaseClass(); SubClass sc = (SubClass)bc ;---是错误的 <BR><BR>BaseClass bc = new SubClass()也是正确的，并且在调用bc中的方法时执行的方法体是子类的方法体，但该方法必须同时在子类，父类中同时存在，若子类中有，而父类中没有，则不可以这样调用bc.subMethod(); <BR><BR>若两个类都继承于同一个类(必须是直接继承，否则不对)，则这两个类可以互相赋值，如：Panel和Frame 同继承于Container，所以Panel p = new Frame() ；和Frame f = new Panel()都是正确的， <BR></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/wangxq/aggbug/13086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2005-09-15 15:37 <a href="http://www.blogjava.net/wangxq/articles/13086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载&gt;</title><link>http://www.blogjava.net/wangxq/articles/13077.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 15 Sep 2005 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/13077.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/13077.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/13077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/13077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/13077.html</trackback:ping><description><![CDATA[
		<table class="tablebody2" style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all" width="90%" border="0">
				<tbody>
						<tr>
								<td style="FONT-SIZE: 9pt; LINE-HEIGHT: 12pt" width="100%"> <b>[转帖]Java面向对象概述</b><br />Java面向对象概述    leeak（原作） 
<p></p><p>(如今的程序领域，大家都在说，面向对象OOP,但是真正能理解面向对象的含义的程序员却很少，究竟什么是对象，怎样面向对象)<br />一．面向对象：<br />1.何谓对象：在面向对象程序设计中，我们将问题空间中的元素以及他们在方案空间中的的表示物称作对象（object）<br /> Alan Kay总结了smalltalk中对象的5大基本特征：<br />所有的东西都是对象。<br />程序是一大堆对象的集合，他们通过消息传递，各个对象之间知道要做些什么。<br />每个对象都分配有自己的存储空间，可容纳其他对象。<br />每个对象都有一个类型。<br />同一类的所有对象能接收相同的消息。<br /> -----而所有的编程语言的最终目的是提供一种抽象方法----<br />2．对象的接口：我们向对象发出请求是通过它的接口定义的，对象的类型决定了它的接口形式。<br />3．OOP中唯一关心的： 就是接口是什么，就像汽车的发动机一样，我们不必要知道它的结构是什么，只要它能工作就行了。所有的程序是由一定的属性（数据）和行为（方法）组成的，不同的对象访问通过函数调用来完成，对象间的所有交流都是通过方法调用，通过对封装数据对象，很大程度上提高复用率。<br />4．对象的3个主要特征：<br />      behavior—说明这个对象能做什么。<br />      State—当对象施加方法时对象的反映。<br />      Identity---与其他相似行为对象的区分标志，每一个对象有唯一的indentity, 而这3者是相互影响的。<br />5．面向对象中最重要的思想 就是类，类是模板是蓝图，从类中构造一个对象，即创建了一个类的实例。（类好比一个建材市场，其中有许多子类--各种各样的装饰材料，而我们装修自己的房子就要选择我们需要的材料，（为了建立我们自己的程序，我们必须选 择我们需要的类）这个比喻可以很形象的解释类是什么。<br />6．类之间的关系：<br />        依赖关系：use-a  A类中的一个方法操作了另一个类中的对象。<br />        聚合关系：has-a  A类中的对象包含B类的对象。<br />        继承关系：is-a   A继承了B类，此时A类不仅有了B类的方法，还加入了自己的方法。以便我们创建我们自己需要的对象。<br />Java中定义的每一个类都必须继承另一个类，使用关键字extends，如果一个类在定义中不现实使用关键字extends,这个类就会隐式继承Object类。Object类又叫根超类，或基类。，我们从根超类继承来的叫子类。Java中每个类都是根超类的子类。</p><p>8．接口（interface）规定了可对特定的对象发出哪些请求。<br />9．继承=重新使用接口：创建出一个数据类型后，当需要新建立一个数据类型去实现相同的功能，是很没有意义的一件事，此时对其克隆后，再根据情况改进实现自己的目的就是继承。</p><p>10．封装：就是把数据和行为结合在一起在一个包中，并对对象使用者隐藏数据的实现过程。Java用3个关键字来设置边界，从而进行对数据的隐藏。Public(共有)的定义任何人都可使用.private（私有）意味着除你自己，类型创建者及那个类型的内部函数成员可以访问外其他任何人使用都会产生错误。Friendly（友好）<br />意味在包(package)中是可以访问的。（以上过程也可叫方案隐藏）<br />11．引用（Handle）操控对象：<br />    当创建一个引用时必须要对其进行初始化<br />  例: String s=”happy”（未建立连接）<br />     String s=new string(“happy”)与一个新的对象连接使用new 。此句建立了一个引用，并且连接引用并初始化对象 赋值字符串“happy”.<br />12.对象的创建及存在时间：数据存放的地点<br />       1：寄存器-速度快，数量少，在cpu内部，我们对寄存器没有控制权。<br />       2：堆栈：驻留长规内存中，堆栈指针下移建立新的内存，上移释放内存。<br />      3：堆：常用内存池，保存对象，有极大的灵活性，java的数据就存放在此，但是要以时间及效率为代价。Java的对象建立是在程序运行时才决定。而c++是在设计时建立对象。<br /> 对象的生存时间（lifetime）java提出的垃圾收集器可以很好的发现无须再用的对象，使用GC（grabage collector）垃圾收集器。清除对象，释放内存。<br />为此我们就要付出一定的运行期的开销。<br />13.在此我们就会有这样一个印象,一个程序只是一系列对象的集合,他们的方法将其他对象作为自己的变量使用.<br />14.主要类型: java的主要类型有:boolean,char,byte,short,int,long,float,double,void.这些主类型的大小都不随机器的结构变化而变化,提供了java很好的可移植性.<br />15.字段方法:字段又叫数据成员,成员函数又叫方法,java的全部工作就是定义类,制作累得对象及发送消息.<br />16.一个程序只是一系列对象的集合,他们的方法将其他的对象作为自己的变量使用,而且将消息发给那些对象.<br />17.名字的可见性:为了使名字不重复,作者可以定义自己的库,一般用自己域名的倒写形式 如: COM.:Leeak.utility.foidles<br />18.static关键字:即使没有创建对象,也需要一愕能调用的方法,此时可以使用static<br />19.java.lang默认自动的导入每个java程序中<br />20.OOP中对象使对属性和方法的封装,对象具有信息的隐蔽的性质,对细节的隐藏,对象只需要知道去这样做,而不知道如何做的细节,类的方法应谨慎控制对java数据的访问,可以用get读取方法,用set修改方法.</p><p>21:pakage:Java API中每个类和接口属于一个特定的包,包实际上市对类和接口进行组织的目录结构,提供了一种软件复用机制.<br />22.创建可复用的类得步骤:1.定义一个public类<br />                                               2.选择一个包名,并把pakage语句加到可复用的类的源码中.<br />                           3.编译这个类.<br />4.把可复用的类导入其他程序中即可.<br />23.java中提出在类定义的括号外的仅有2个语句,pakage和import.<br />24.软件的复用性,软件的复用性就是利用紫的已有的,定义良好的的经过仔细测试的文档清晰的可移植的易于获得的软件构件开发新的软件.</p><p></p><p>以上就是java面向对象的一些基本术语的概述,其中的有些部分可以扩展的更深,看过think in java的 朋友就会有此种感觉.此文章向对初学者阐述了面向对象的基本概念.对已是java程序员的朋友可以对他们的基本知识做以回顾.</p><p><br /><a href="http://www.csdn.net/Develop/article/22/22198.shtm" target="_blank"><font color="#000000">http://www.csdn.net/Develop/article/22/22198.shtm</font></a></p></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/wangxq/aggbug/13077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2005-09-15 14:53 <a href="http://www.blogjava.net/wangxq/articles/13077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>php和mysql分页显示详解</title><link>http://www.blogjava.net/wangxq/articles/11770.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 01 Sep 2005 09:21:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/11770.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/11770.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/11770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/11770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/11770.html</trackback:ping><description><![CDATA[<P>1.数据库连接的类dbClass.inc。<BR>&lt;?php<BR>/**<BR>* a class use to connect the MySQL database and do some query<BR>*/<BR>class dbClass {<BR>private $hostName = "localhost:3306";<BR>private $dbName = "ebooklib";<BR>private $Login = "root";<BR>private $Password = "";<BR>private $conn;<BR>private $result;</P>
<P>function dbClass(){ <BR>$this-&gt;conn = mysql_connect("$this-&gt;hostName","$this-&gt;Login","$this-&gt;Password");<BR>mysql_select_db("$this-&gt;dbName", $this-&gt;conn); <BR>}</P>
<P>function executeQuery($sql){ <BR>$this-&gt;result = mysql_query("$sql",$this-&gt;conn); <BR>return $this-&gt;result;<BR>}</P>
<P>function closeConn(){<BR>mysql_close($this-&gt;conn);<BR>}<BR>}</P>
<P>?&gt; </P>
<P>2.解决分页问题的PageQuery.inc<BR>&lt;?php<BR>include("dbClass.inc");<BR>class PageQuery extends dbClass {<BR>&nbsp;&nbsp;&nbsp; private $Offset;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录偏移量 <BR>&nbsp;&nbsp;&nbsp; private $Total;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录总数 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; private $maxLine;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录每页显示记录数 <BR>&nbsp;&nbsp;&nbsp; private $result;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 读出的结果 <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; private $TPages;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 总页数 <BR>&nbsp;&nbsp;&nbsp; private $CPages;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 当前页数 <BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; private $PageQuery;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 分页显示要传递的参数<BR>&nbsp;&nbsp;&nbsp; private $Query;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // query 语句<BR>&nbsp;&nbsp;&nbsp; private $QueryPart;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // " FROM " 以后的 query 部分 <BR>&nbsp;&nbsp;&nbsp; private $QueryString;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ? 以后部分&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; private $FilePath;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; // 每页显示行数<BR>&nbsp;&nbsp;&nbsp; function PageQuery($pageLine=10) {&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;dbClass();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;maxLine = $pageLine;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录总数<BR>&nbsp;&nbsp;&nbsp; function getTotal(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $this-&gt;Total;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 显示总页数<BR>&nbsp;&nbsp;&nbsp; function getTotalPages() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $this-&gt;TPages;<BR>&nbsp;&nbsp;&nbsp; }</P>
<P>&nbsp;&nbsp;&nbsp; //显示当前所在页数<BR>&nbsp;&nbsp;&nbsp; function getCurrenPages() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $this-&gt;CPages;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; function myQuery($sql, $flag=1){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GLOBAL $offset;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;Query = $sql;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 获取文件名<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //$this-&gt;FilePath = $GLOBALS["REQUEST_URI"];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;FilePath = $GLOBALS["SCRIPT_NAME"];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 获取查询条件<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;QueryString = $GLOBALS["QUERY_STRING"];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //echo $this-&gt;QueryString . "&lt;br&gt;";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 截取 " from " 以后的 query 语句<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;QueryPart = trim(strstr($sql, " from "));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 计算偏移量<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isset($offset)) $this-&gt;Offset = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else $this-&gt;Offset = (int)$offset;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 计算总的记录条数<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $SQL = "SELECT Count(*) AS total " . $this-&gt;QueryPart;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;result = $this-&gt;executeQuery($SQL);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;Total = mysql_result($this-&gt;result,0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 设置当前页数和总页数<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;TPages = (double)Ceil((double)$this-&gt;Total/$this-&gt;maxLine);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;CPages = (double)Floor((double)$this-&gt;Offset/$this-&gt;maxLine+1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 根据条件判断，取出所需记录<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ($this-&gt;Total &gt; 0) { <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //flag等于1表示要分页，否则不分页<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($flag==1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $SQL = $this-&gt;Query . " LIMIT " . $this-&gt;Offset . " , " . $this-&gt;maxLine; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $SQL = $this-&gt;Query;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo $SQL . "&lt;br&gt;";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;result = $this-&gt;executeQuery($SQL);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $this-&gt;result;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; //**********显示翻页提示栏*************&nbsp; <BR>&nbsp;&nbsp;&nbsp; // 显示首页、下页、上页、尾页<BR>&nbsp;&nbsp;&nbsp; function PageLegend() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; $str = "";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $i = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $first = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $next = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $prev = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $last = 0;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $next = $this-&gt;Offset + $this-&gt;maxLine; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $prev = $this-&gt;Offset - $this-&gt;maxLine; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $last = ($this-&gt;TPages - 1) * $this-&gt;maxLine; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GLOBAL $offset;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!isset($offset)) $this-&gt;QueryString .= "&amp;offset=";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;QueryString = substr($this-&gt;QueryString,0,strrpos($this-&gt;QueryString,'&amp;')) . "&amp;offset=";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($this-&gt;Offset &gt;= $this-&gt;maxLine) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .=&nbsp; " &lt;A href=" . $this-&gt;FilePath . "?" . $this-&gt;QueryString . $first . "&gt;首页&lt;/A&gt; ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else $str .= " 首页 ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($prev &gt;= 0) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .=&nbsp; " &lt;A href=" . $this-&gt;FilePath . "?" . $this-&gt;QueryString . $prev . "&gt;上一页&lt;/A&gt; "; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else $str .= " 上一页 ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($next &lt; $this-&gt;Total) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .=&nbsp; " &lt;A href=" . $this-&gt;FilePath . "?" . $this-&gt;QueryString . $next . "&gt;下一页&lt;/A&gt; "; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else $str .= " 下一页 ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if($this-&gt;TPages != 0 &amp;&amp; $this-&gt;CPages &lt; $this-&gt;TPages) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .=&nbsp; " &lt;A href=" . $this-&gt;FilePath . "?" . $this-&gt;QueryString . $last . "&gt;尾页&lt;/A&gt;"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else $str .= " 尾页 ";</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .= " 页次：" . $this-&gt;getCurrenPages() . "/" . $this-&gt;getTotalPages() . "页 ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $str .= $this-&gt;maxLine . "条/页 " . "共" . $this-&gt;Total . "条";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return $str;<BR>&nbsp;&nbsp;&nbsp; }<BR>}<BR>?&gt;<BR>3.用于显示结果的mysql_result_all.inc<BR>&lt;? <BR>function mysql_result_all($result,$format="") { <BR>echo "&lt;table $format&gt;&lt;tr&gt;"; <BR>for($i=0;$i&lt;mysql_num_fields($result);$i++) { <BR>echo "&lt;th&gt;".mysql_field_name($result,$i)."&lt;/th&gt;"; <BR>} <BR>echo "&lt;/tr&gt;"; <BR>while($row = mysql_fetch_array($result) ) {<BR>for($i=0;$i&lt;mysql_num_fields($result);$i++) { <BR>echo "&lt;td&gt;".$row[$i]."&lt;/td&gt;"; <BR>} <BR>echo "&lt;/tr&gt;"; <BR>}<BR>echo "&lt;/table&gt;";<BR>} <BR>?&gt; <BR>4.显示页面的代码：<BR>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<A href="http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</A>"&gt;<BR>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;title&gt;php＆mysql分页显示&lt;/title&gt;<BR>&lt;/head&gt;</P>
<P>&lt;body&gt;<BR>&lt;?php<BR>include("PageQuery.inc");</P>
<P>$pq = new PageQuery(5); // 获取Connection <BR>$res=$pq-&gt;myQuery("select * from users"); // 执行查询</P>
<P>require("mysql_result_all.inc");<BR>mysql_result_all($res,"border=1");<BR>echo $pq-&gt;PageLegend(2); // 翻页栏<BR>?&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;<BR></P><img src ="http://www.blogjava.net/wangxq/aggbug/11770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2005-09-01 17:21 <a href="http://www.blogjava.net/wangxq/articles/11770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载</title><link>http://www.blogjava.net/wangxq/articles/11709.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Thu, 01 Sep 2005 01:40:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/11709.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/11709.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/11709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/11709.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/11709.html</trackback:ping><description><![CDATA[<TABLE style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all" cellSpacing=1 cellPadding=3 width="98%" bgColor=#cccccc border=0>
<TBODY>
<TR bgColor=#f8f8f8>
<TD><STRONG><FONT face="">static用法</FONT></STRONG><BR>星☆星 发表于 2005-8-15 13:04:35 </TD></TR>
<TR bgColor=#ffffff>
<TD height=0>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><SPAN class=oblog_text>请先看下面这段程序： 
<P>
<TABLE style="BORDER-RIGHT: #999999 1px dotted; BORDER-TOP: #999999 1px dotted; FONT-SIZE: 12px; BORDER-LEFT: #999999 1px dotted; WIDTH: 95%; BORDER-BOTTOM: #999999 1px dotted; BACKGROUND-COLOR: #fdfddf; WORD-WRAP: break-word" cellSpacing=0 cellPadding=6 align=center>
<TBODY>
<TR>
<TD><SPAN style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段：</SPAN><BR><!-- BEGIN code -->&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;class&nbsp;Hello{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){&nbsp;//(1) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Hello,world!");&nbsp;&nbsp;&nbsp;//(2) <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <!-- END code --></TD></TR></TBODY></TABLE></P>
<P>　　看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。</P>
<P>　　在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：</P>
<P>　　javac Hello.java<BR>　　java Hello<BR>　　Hello,world!</P>
<P>　　这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：</P>
<P>　　public void println(String x)。</P>
<P>　　好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。</P>
<P>　　<STRONG>静态方法</STRONG></P>
<P>　　通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：</P>
<P>
<TABLE style="BORDER-RIGHT: #999999 1px dotted; BORDER-TOP: #999999 1px dotted; FONT-SIZE: 12px; BORDER-LEFT: #999999 1px dotted; WIDTH: 95%; BORDER-BOTTOM: #999999 1px dotted; BACKGROUND-COLOR: #fdfddf; WORD-WRAP: break-word" cellSpacing=0 cellPadding=6 align=center>
<TBODY>
<TR>
<TD><SPAN style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段：</SPAN><BR><!-- BEGIN code -->&nbsp;&nbsp;class&nbsp;Simple{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;go(){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Go..."); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;public&nbsp;class&nbsp;Cal{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Simple.go(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <!-- END code --></TD></TR></TBODY></TABLE></P>
<P>　　调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。</P>
<P>　　<STRONG>静态变量</STRONG></P>
<P>　　静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：</P>
<P>
<TABLE style="BORDER-RIGHT: #999999 1px dotted; BORDER-TOP: #999999 1px dotted; FONT-SIZE: 12px; BORDER-LEFT: #999999 1px dotted; WIDTH: 95%; BORDER-BOTTOM: #999999 1px dotted; BACKGROUND-COLOR: #fdfddf; WORD-WRAP: break-word" cellSpacing=0 cellPadding=6 align=center>
<TBODY>
<TR>
<TD><SPAN style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段：</SPAN><BR><!-- BEGIN code -->&nbsp;&nbsp;class&nbsp;Value{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;c=0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;inc(){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c++; <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;class&nbsp;Count{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;prt(String&nbsp;s){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;v1,v2; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1=new&nbsp;Value(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v2=new&nbsp;Value(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1.inc(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c);&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <!-- END code --></TD></TR></TBODY></TABLE></P>
<P>　　结果如下：</P>
<P>　　v1.c=0&nbsp; v2.c=0<BR>　　v1.c=1&nbsp; v2.c=1</P>
<P>　　由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：</P>
<P>
<TABLE style="BORDER-RIGHT: #999999 1px dotted; BORDER-TOP: #999999 1px dotted; FONT-SIZE: 12px; BORDER-LEFT: #999999 1px dotted; WIDTH: 95%; BORDER-BOTTOM: #999999 1px dotted; BACKGROUND-COLOR: #fdfddf; WORD-WRAP: break-word" cellSpacing=0 cellPadding=6 align=center>
<TBODY>
<TR>
<TD><SPAN style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段：</SPAN><BR><!-- BEGIN code -->&nbsp;&nbsp;class&nbsp;Value{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;c=0; <BR>&nbsp;&nbsp;&nbsp;&nbsp;Value(){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c=15; <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;Value(int&nbsp;i){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c=i; <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;inc(){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c++; <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;class&nbsp;Count{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;prt(String&nbsp;s){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;v=new&nbsp;Value(10); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;Value&nbsp;v1,v2; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1=new&nbsp;Value(27); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v2=new&nbsp;Value(15); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Count&nbsp;ct=new&nbsp;Count(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("ct.c="+ct.v.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v1.inc(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("v1.c="+v1.c+"&nbsp;&nbsp;v2.c="+v2.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prt("ct.c="+ct.v.c); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <!-- END code --></TD></TR></TBODY></TABLE>　　运行结果如下：</P>
<P>　　v1.c=0&nbsp; v2.c=0<BR>　　v1.c=27&nbsp; v2.c=27<BR>　　v1.c=15&nbsp; v2.c=15<BR>　　ct.c=10<BR>　　v1.c=10&nbsp; v2.c=10<BR>　　v1.c=11&nbsp; v2.c=11<BR>　　ct.c=11</P>
<P>　　这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是，static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。</P>
<P>　　<STRONG>静态类</STRONG></P>
<P>　　通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：</P>
<P>
<TABLE style="BORDER-RIGHT: #999999 1px dotted; BORDER-TOP: #999999 1px dotted; FONT-SIZE: 12px; BORDER-LEFT: #999999 1px dotted; WIDTH: 95%; BORDER-BOTTOM: #999999 1px dotted; BACKGROUND-COLOR: #fdfddf; WORD-WRAP: break-word" cellSpacing=0 cellPadding=6 align=center>
<TBODY>
<TR>
<TD><SPAN style="FONT-WEIGHT: bold; COLOR: #990000">以下是代码片段：</SPAN><BR><!-- BEGIN code -->&nbsp;&nbsp;public&nbsp;class&nbsp;StaticCls{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OuterCls.InnerCls&nbsp;oi=new&nbsp;OuterCls.InnerCls(); <BR>&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <BR>&nbsp;&nbsp;class&nbsp;OuterCls{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;class&nbsp;InnerCls{ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InnerCls(){ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("InnerCls"); <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <BR>&nbsp;&nbsp;} <!-- END code --></TD></TR></TBODY></TABLE></P>
<P>　　输出结果会如你所料：</P>
<P>　　InnerCls</P>
<P>　　和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。<BR><BR>static指向同一块内存，当你把某数据成员或函数声明为static时，它就不再局限于所属的class object，这样就有了一个好处，可以让你在不建立任何对象的情况下，调用你声明的函数。<BR>举一个例子：<BR>class Test{<BR>static int i=1;<BR>}<BR>Test t1=new Test();<BR>Test t2=new Test();<BR>那么t1.i和t2.i都是1，它们其中任一个值改变，另外的也会一起改变。</P></SPAN></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
<TBODY>
<TR>
<TD width="74%"><A href="file:///E:/books/PHP/static用法--D_T_S_Cloud.htm#">阅读全文(<SPAN id=ob_logreaded></SPAN>)</A> | <A href="file:///E:/books/PHP/static用法--D_T_S_Cloud.htm#comment">回复(0)</A> | <A href="file:///E:/showtb.asp?id=372" target=_blank>引用通告(<SPAN id=ob_tbnum></SPAN>)</A>
<SCRIPT src="/count.asp?action=logtb&amp;id=372"></SCRIPT>
 | <A href="file:///E:/user_post.asp?logid=372" target=_blank>编辑</A></TD>
<TD width="26%">
<DIV align=right>&nbsp;</DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><A name=comment></A><img src ="http://www.blogjava.net/wangxq/aggbug/11709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2005-09-01 09:40 <a href="http://www.blogjava.net/wangxq/articles/11709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载</title><link>http://www.blogjava.net/wangxq/articles/10916.html</link><dc:creator>扭转乾坤</dc:creator><author>扭转乾坤</author><pubDate>Wed, 24 Aug 2005 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/wangxq/articles/10916.html</guid><wfw:comment>http://www.blogjava.net/wangxq/comments/10916.html</wfw:comment><comments>http://www.blogjava.net/wangxq/articles/10916.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wangxq/comments/commentRss/10916.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wangxq/services/trackbacks/10916.html</trackback:ping><description><![CDATA[<DIV class=newsmallbox>Windows下PHP5和Apache的安装与配置 </DIV>
<DIV class=clear1></DIV>
<DIV class=newsmall1box>
<DIV class=newtitle1>作者： mylxiaoyi </DIV>
<DIV class=newtitle2>&nbsp;</DIV>
<DIV class=newtitle3>
<DIV class=space2><SPAN id=ad5></SPAN></DIV>在这里以PHP5为例介绍一下<A class=bluekey href="http://www.yesky.com/key/1246/206246.html" target=_blank><FONT color=#002c99>Windows下</FONT></A>Apache和PHP5的安装与配置方法。<BR>一 下载安装程序<BR>　　Apache可以从http://www.apache.org/dyn/closer.cgi/httpd/binaries/win32/下载<BR><BR>　　PHP可以从http://www.php.net下载.<BR><BR>　　二 安装程序<BR><BR>　　1、Apache的程序安装相对来说要较为的简单一些,我们从网站下来的是一个Windows下的安装程序,我们可以直接双击运行,这样我们就便利Apache在我们的电脑上安下家来了。<BR><BR>　　2、我们在这里要注意的就是在下载PHP时一定要下载那个zip包的,而不要下载Installer的.将我们下载下来的PHP包解压到C盘下的根目录下,并将解压出来的文件夹改名为php。<BR><BR>　　三 配置<BR><BR>　　1、最好是无论使用何种接口（CGI 或者 SAPI）都确保 php5ts.dll 可用，因此必须将此文件放到 Windows 路径中。最好的位置是 Windows 的 system 目录： <BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>c:\windows\system for Windows 9x/ME <BR>c:\winnt\system32 for Windows NT/2000 或者 c:\winnt40\system32 for Windows NT/2000 服务器版 <BR>c:\windows\system32 for Windows XP </TD></TR></TBODY></TABLE><BR>　　2、下一步是设定有效的 PHP 配置文件，php.ini。压缩包中包括两个 ini 文件，php.ini-dist 和 php.ini-recommended。建议使用 php.ini-recommended，因为此文件对默认设置作了性能和安全上的优化。<BR><BR>　　将选择的 ini <A class=bluekey href="http://www.yesky.com/key/2458/407458.html" target=_blank><FONT color=#002c99>文件拷贝</FONT></A>到 PHP 能够找到的目录下并改名为 php.ini。PHP 默认在 Windows 目录下搜索 php.ini： <BR><BR>　　3 在 Windows 9x/ME/XP 下将选择的 ini 文件拷贝到 %WINDIR%，通常为 c:\windows。 <BR><BR>　　在 Windows NT/2000 下将选择的 ini 文件拷贝到 %WINDIR% 或 %SYSTEMROOT% 下，通常为 c:\winnt 或 c:\winnt40 对应于服务器版本。 <BR><BR>　　4 Apache中PHP的设置<BR><BR>　　有两种方法使得 PHP 工作在 Windows 下的 Apache。一是使用 CGI <A class=bluekey href="http://www.yesky.com/key/3799/203799.html" target=_blank><FONT color=#002c99>二进制文件</FONT></A>，另一是使用 Apache 模块 DLL。无论那种方法，您首先必须停止 Apache 服务器，然后编辑 httpd.conf，以配置 Apache 和 PHP 协同工作。 <BR><BR>　　如果我们要使用CGI二进制文件,那么我们要将如下指令插入到 Apache 的 httpd.conf 配置文件中，以设置 CGI 二进制文件：<BR><BR>　　PHP 以 CGI 方式安装到 Apache 2.0:<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>ScriptAlias /php/ "c:/php/"<BR>AddType application/x-httpd-php .php<BR>Action application/x-httpd-php "/php/php.exe"</TD></TR></TBODY></TABLE><BR>　　如果我们想把 PHP 作为 Apache 2.0 的模块，那么就一定要移动 php4ts.dll 到 winnt/system32（Windows NT/2000）或 windows/system32（Windows XP），覆盖原有文件（如果有的话），对于 PHP 5，这个文件是 php5ts.dll。然后我们要插入如下两行到 httpd.conf 中，以使我们的 PHP 作为 Apache 的 PHP-Module 安装：<BR><BR>　　PHP 以模块方式安装到 Apache 2.0:<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>; For PHP 4 do something like this:<BR>LoadModule php4_module "c:/php/php4apache2.dll"<BR>AddType application/x-httpd-php .php<BR><BR>; For PHP 5 do something like this:<BR>LoadModule php5_module "c:/php/php5apache2.dll"<BR>AddType application/x-httpd-php .php</TD></TR></TBODY></TABLE><BR>　　经过这样的配置以后,我们就安装好了我们的PHP和<A class=bluekey href="http://www.yesky.com/key/3867/168867.html" target=_blank><FONT color=#002c99>Apache服务器</FONT></A>了。我们可以简单的测试一下:<BR><BR>　　1、测试Apache:<BR><BR>　　我们打开浏览器,在地址栏中输入localhost,如果可以出现Apache页面,则说明我们的Apache可以正常工作了。<BR><BR>　　2、测试PHP设置:<BR><BR>　　我们可以简单的编写一个PHP页面,我们可以用文本编辑器,输入下面的代码:<BR><BR>
<TABLE borderColor=#cccccc width="90%" align=center bgColor=#e3e3e3 border=1>
<TBODY>
<TR>
<TD>＜html＞<BR>＜head＞<BR>＜<A class=bluekey href="http://www.yesky.com/key/977/215977.html" target=_blank><FONT color=#002c99>title</FONT></A>＞<BR>hello<BR>＜/title＞<BR>＜/head＞<BR>＜body＞<BR>＜?php echo "hello,php"; ?＞<BR>＜/body＞<BR>＜/html＞</TD></TR></TBODY></TABLE><BR>　　然后将这个文件存为hello.php,将其放在Apache的htdocs目录中(我们也可以在http.conf文件中来更改这个目录的),然后在我们的浏览器中输入http://localhost/hello.php,如果能够正确的显示hello,php就说明我们的PHP配置是可以正常工作的。<BR><BR>　　这样以后我们也可以来设计我们的PHP站点了。<BR><BR></DIV></DIV>
<DIV class=newmiddlebox style="OVERFLOW: hidden">
<DIV class=guanggao><SPAN id=ad4></SPAN></DIV>
<DIV class=guanggao><SPAN id=contentAdv>
<TABLE cellSpacing=0 cellPadding=0 width=360 border=0>
<TBODY>
<TR></TR></TBODY></TABLE></SPAN></DIV></DIV><img src ="http://www.blogjava.net/wangxq/aggbug/10916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wangxq/" target="_blank">扭转乾坤</a> 2005-08-24 14:45 <a href="http://www.blogjava.net/wangxq/articles/10916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>