<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>muscle-liu</title>
    <description>无路可循，才有更多可能...我要实现我的自我.</description>
    <link>http://muscle-liu.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>request与getServletContext()的getRealPath()</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/205979" style="color:red;">http://muscle-liu.javaeye.com/blog/205979</a>&nbsp;
          发表时间: 2008年06月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天一个同事问我怎样实现PDF文件内嵌到html页面。下边是在html里实现的代码（来自网上）：<br /><pre name="code" class="java">
&lt;object   classid="clsid:CA8A9780-280D-11CF-A24D-444553540000"   width="760"   height="411"   border="0">     
              &lt;param   name="_Version"   value="65539">     
              &lt;param   name="_ExtentX"   value="20108">     
              &lt;param   name="_ExtentY"   value="10866">     
              &lt;param   name="_StockProps"   value="0">     
              &lt;param   name="SRC"   value="illustrator.pdf">     
&lt;/object>
</pre><br /><br />但是，要把它用一个servlet打开，在servlet中直接把这个嵌有pdf的html print出来.<br />但是其路径问题不能打开。我就用getServletContext().getRealPath("\")；来确定其路径，但却发现打开网页时弹出“Access Denied.”的信息，不能打开。后来试了，用request.getRealPath("\");就能正常打开了。
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/205979#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 19 Jun 2008 21:32:53 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/205979</link>
        <guid>http://muscle-liu.javaeye.com/blog/205979</guid>
      </item>
      <item>
        <title>Java applet 与 log4j</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/204310" style="color:red;">http://muscle-liu.javaeye.com/blog/204310</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          有差不多两个月没写东西了...这两个月来我给另一个team借去做一个J2ee项目，之前的j2me 项目就停下来了...<br /><br />在这个项目里主要负责是一个Softphone的客户端, 是用 applet 实现，运行在jsp 页面里。 在applet客户端里，applet的jar我已经signed 了，但是还是不能生成日志...查了一下，发现applet 在客户端里并不能用一般的log4j appender生成日志在服务端里。要用到log4j SocketAppender， 但这要求服务端架构一个日志服务器...<br /><br /><br />哈哈，过了两天后，我发现了，原来log4j这个包也要签名，这样在客户端里用一般的appender 生成日志，不过这个日志只能产生在客户端的PC上.....
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/204310#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Jun 2008 20:40:04 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/204310</link>
        <guid>http://muscle-liu.javaeye.com/blog/204310</guid>
      </item>
      <item>
        <title>甘晚删着一个系统, 让grub搞着成晚</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/181988" style="color:red;">http://muscle-liu.javaeye.com/blog/181988</a>&nbsp;
          发表时间: 2008年04月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我噶机上装着双系统window xp + FC5 linux, 但我噶windos下空间越来越少了，甘晚吾知发乜疯，一时兴起系window下直接用软件delete着linux分区，重建着一个window下噶区.....一时没考虑到grub引度程序噶问题，所以重启后，my god! 显示“grub>:”提示符，进不了系统.......一时忙了怎样处理, 晕啊!哪就重装一次windows吧，最糟的是我的winodw是ghost版本，copy完后还是进不了去， grub 还在...<br /><br />到最后就到另人机子上网查了一下，用dos引导盘在dos操作介面操作："fdisk /mbr" 就这一句就可以报grub 删掉了，再重启就可以了....
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/181988#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Apr 2008 00:25:05 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/181988</link>
        <guid>http://muscle-liu.javaeye.com/blog/181988</guid>
      </item>
      <item>
        <title>j2me 实现 j2se 的 Properties 功能</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/180202" style="color:red;">http://muscle-liu.javaeye.com/blog/180202</a>&nbsp;
          发表时间: 2008年04月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我们知道 j2me 中没有 j2se 里边的 Properties 类，要自己实现才能像 j2se 那样读取文件的，现在 j2mepolish 里边的 de.enough.polish.util.Properties 就实现了类似 j2se 的 Properties, 加上de.enough.polish.util.ResourceStreamUtil（旧版本polish 没有这个类，要自己实现相应功能）可以让我们容易读取属性文件。关于 ResourceStreamUtil 类和 Properties 类的介绍大家可以参考 j2mepolish 里边的 api doc。<br /><br />只要在把你所新建的 .properties 文件放在 resources 文件夹下(相当于一个资源文件,也可以放其他地方，但一定要把它配置成资源),就可以用相应的方法读取, 看下边例子:<br /><br />test.properties文件:<br /><pre name="code" class="java">
name=muscle-liu
sex=male
age=24
</pre><br /><br />读取时的部分代码：<br /><pre name="code" class="java">
Properties prop = new Properties();
InputStream in = null;
try{
  byte[] sData = ResourceStreamUtil.getResourceAsByteArray("/test.properties");
  System.out.println("sData.length:  "+sData.length);
  in =  new ByteArrayInputStream(sData);
            
  prop.load(in);
}catch (IOException e){
  e.printStackTrace();
}

System.out.println("prop.getProperty(\"name\"): "+prop.getProperty("name"));
System.out.println("prop.getProperty(\"sex\"): "+prop.getProperty("sex"));
System.out.println("prop.getProperty(\"age\"): "+prop.getProperty("age"));
</pre><br /><br />运行结果如下：<br /><pre name="code" class="java">
prop.getProperty("name"): muscle-liu
prop.getProperty("sex"): male
prop.getProperty("age"): 24
</pre><br /><br />在运用中我发现这个 Properties 类有个 bug，就是不支持 # 的注释(也就是说，属性文件里边除了 key-value 的内容，不能有其他的非 k-v 内容)。下边是我修改 Properties 里边的 load 方法，令它支持 # 注释:<br />原来的 load 方法：<br /><pre name="code" class="java">
public void load(InputStream in, String encoding, boolean generateIntegerValues ) throws IOException
	{
		this.isIntegerValues = generateIntegerValues;
		int bufferLength = 2 * 1024;
		byte[] buffer = new byte[ bufferLength ];
		int read;
		int start = 0;
		int end = 0;
		boolean newLineFound;
		while ( (read = in.read(buffer, start, bufferLength - start )) != -1) {
			// search for next \r or \n
			String line;
			if (encoding != null) {
				line = new String( buffer, 0, read + start, encoding );
			} else {
				line = new String( buffer, 0, read + start );				
			}
			start = 0;
			newLineFound = true;
			while (newLineFound) {
				newLineFound = false;
				char c = '\n';
				for (int i = start; i &lt; line.length(); i++) {
					c = line.charAt(i);
					if (c == '\r' || c == '\n') {
						end = i;
						newLineFound = true;
						break;
					}
				}
				if (newLineFound) {
					int splitPos = line.indexOf('=', start);
					if(splitPos == -1) {
						throw new IOException("no = separator: " + line.substring( start, end ));
					}
					String key = line.substring( start, splitPos );
					String value = line.substring( splitPos + 1, end );
					if (generateIntegerValues) {
						try {
							put( key, Integer.valueOf(value) );
						} catch(NumberFormatException ex) {
							throw new IOException( ex.toString() );
						}												
					} else {
						put( key, value );	
					}
					if (c == '\r') {
						start = end + 2;
					} else {
						start = end + 1;
					}
				}
			}
			// now all key-value pairs have been read, now move any remaining data to the beginning of the buffer:
			if (start &lt; read) {
				System.arraycopy( buffer, start, buffer, 0, read - start );
				start = read - start;
			} else {
				start = 0;
			}
		}
	}	
</pre><br /><br /><br />修改后的 load 方法:<br /><pre name="code" class="java">
public void load(InputStream in, String encoding, boolean generateIntegerValues ) throws IOException
	{
		this.isIntegerValues = generateIntegerValues;
		int bufferLength = 2 * 1024;
		byte[] buffer = new byte[ bufferLength ];
		int read;
		int start = 0;
		int end = 0;
		boolean newLineFound;
		boolean isComment;
		while ( (read = in.read(buffer, start, bufferLength - start )) != -1) {
			// search for next \r or \n
			String line;
			if (encoding != null) {
				line = new String( buffer, 0, read + start, encoding );
			} else {
				line = new String( buffer, 0, read + start );				
			}
			start = 0;
			newLineFound = true;
			while (newLineFound) {
				newLineFound = false;
				isComment = false;
				char c = '\n';

				char firstChar = line.charAt(start);
				if(firstChar == '#'){
					isComment = true;
				}

				for (int i = start; i &lt; line.length(); i++) {
					c = line.charAt(i);
					
					if (c == '\r' || c == '\n') {
						end = i;
						newLineFound = true;
						break;
					}
				}
				if (newLineFound && !isComment) {
					int splitPos = line.indexOf('=', start);
					if(splitPos == -1) {
						throw new IOException("no = separator: " + line.substring( start, end ));
					}
					String key = line.substring( start, splitPos );
					String value = line.substring( splitPos + 1, end );
					if (generateIntegerValues) {
						try {
							put( key, Integer.valueOf(value) );
						} catch(NumberFormatException ex) {
							throw new IOException( ex.toString() );
						}												
					} else {
						put( key, value );	
					}
				}

				if (c == '\r') {
					start = end + 2;
				} else {
					start = end + 1;
				}
			}
			// now all key-value pairs have been read, now move any remaining data to the beginning of the buffer:
			if (start &lt; read) {
				System.arraycopy( buffer, start, buffer, 0, read - start );
				start = read - start;
			} else {
				start = 0;
			}
		}
	}
</pre><br /><br />这样我们就可以像 j2se 那样写 properties 文件了..当然，如果你的项目中没有用 j2mepolish, 那你也可以借用这两个类到你的工程，照样可以实现 j2se 的 properties 功能
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/180202#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 07 Apr 2008 17:45:05 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/180202</link>
        <guid>http://muscle-liu.javaeye.com/blog/180202</guid>
      </item>
      <item>
        <title>blackberry 程序的调试</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/179031" style="color:red;">http://muscle-liu.javaeye.com/blog/179031</a>&nbsp;
          发表时间: 2008年04月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我们知道 BB 上的程序有用 BB api 写的，也有 j2me 写的。一般用 BB api/j2me api 在 blackberry上 开发的程序用 BB jde 编译运行，在 jde 上就可以调试，这我就不多讲了。但很多时候我们用下载了 j2me 程序的 jar 包，再转为 .cod 文件来安装到 BB 上的，或者在开发过程中引用了一些第三方的框架(如j2mepolish)，是无法再用 BB jde 来编译的了， 那么原来的调试信息（如“System.out.println()；”语句）就不能显示了。这怎样在 BB 环境中进行调试呢？<br /><br />我们在转 j2me 程序为 .cod 文件时，还会产生一些以 .debug 为后缀名的文件（当然如果你程序中一句println语句都没有的话是不会产生这种文件的）, 这些 .debug 文件就是用来在 BB jde 中进行调试的：<br /><br />1)、将 j2me 程序转 .cod 文件后产生的全部文件都 copy 到  C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\simulator\ 目录下（这是你的 BB jde 安装目录，主要是把.cod 和 .debug 文件放在这里， copy 到这里就相当于安装了程序）。<br /><br />2）、在 jde 里边启动 emulator ,  运行你的 j2me 程序，这样在 jde 的 debug output 窗口就会产生 debug 的信息出来了。 (怎样在 jde 里边启动 emulator? 我是随便用 jde 写一个程序让它把 emulator 跑起来就可以了。 在 Edit->Preferences->General里选择 Launch Emulator，这就能用 build all and run 来启动 emulator了).
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/179031#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 03 Apr 2008 00:35:10 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/179031</link>
        <guid>http://muscle-liu.javaeye.com/blog/179031</guid>
      </item>
      <item>
        <title>eWebEditor 运行在linux服务器上</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/176484" style="color:red;">http://muscle-liu.javaeye.com/blog/176484</a>&nbsp;
          发表时间: 2008年03月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本人下载了一个jsp版的 eWebEditor 在本机 window+tomcat下运正常，但当我发布到linux 服务器上时却不能正常运行，错误如下：<br /><br />500 Servlet Exception<br />java.lang.NullPointerException<br />	at _eWebEditor__jsp._jspService(/www/users/eWebEditor.jsp:134)<br />	at com.caucho.jsp.JavaPage.service(JavaPage.java:75)<br />	at com.caucho.jsp.Page.subservice(Page.java:506)<br />	at com.caucho.server.http.FilterChainPage.doFilter(FilterChainPage.java:182)<br />	at com.caucho.server.http.Invocation.service(Invocation.java:315)<br />	at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:135)<br />	at com.caucho.server.http.RunnerRequest.handleRequest(RunnerRequest.java:346)<br />	at com.caucho.server.http.RunnerRequest.handleConnection(RunnerRequest.java:274)<br />	at com.caucho.server.TcpConnection.run(TcpConnection.java:139)<br />	at java.lang.Thread.run(Thread.java:534)<br /><br /><br />--------------------------------------------------------------------------------<br />Resin 2.1.14 (built Thu Jul 1 18:39:55 PDT 2004) <br /><br />程序的其它页面都能正常显示/操作，就是 eWebEditor 不行。本人在网上搜过了，有这样的问题却没有人提供解决办法。期待各位达人的指教......
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/176484#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 26 Mar 2008 20:13:39 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/176484</link>
        <guid>http://muscle-liu.javaeye.com/blog/176484</guid>
      </item>
      <item>
        <title>BlackBerry 中的 udp 连接</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/176450" style="color:red;">http://muscle-liu.javaeye.com/blog/176450</a>&nbsp;
          发表时间: 2008年03月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          之前的 j2me 项目要转移到 blackberry 运行，明白了转化过程后，而且能转成功后，却有新的问题： 在 j2me 中用到的 udp 连接在 blackberry 行不通。从外国的论坛或 RIM 主站上或文档上都说只要运行 MDS 就能实现 tcp/udp 连接。但是我的项目转为 cod 后连接 udp 时却出错。所以我用一个简单例子来测试一下, 我把 sun wtk 里边的一个 udp 例子转为 cod 文件后，发觉 server 端到 client 端能通信，但 client 端到 server 端却不能通信(运行在wtk时能相互通信)<img src="/images/smiles/icon_sad.gif"/>。 很陏闷，这个问题拖了我二个月了。甘天在同事的帮阻下终于弄明白了。<br /><br />在bb api 文档里边介绍 upd 连接时有两种介绍：一种是用"datagram://"头，另一种是用"udp://"头, 对于 j2me 里边的介绍是用"datagram://"的, 经过我的测试下边有两种连接方式能正常收发的:<br /><br />一、(这是我同事发现的)<br />发信息时：<br />String sURL = "datagram://192.168.1.102:5042“；<br />收信息时：<br />String rURL = "udp://:4444";<br /><br />二、(这是我参考bb api 写的连接时的代码，想吾到仿照写能够成功通信)<br />发信息时：<br />String sURL = "datagram://192.168.1.102:5042/4444“；<br />收信息时：<br />String rURL = "datagram://192.168.1.102:5042/4444“；
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/176450#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 26 Mar 2008 17:56:49 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/176450</link>
        <guid>http://muscle-liu.javaeye.com/blog/176450</guid>
      </item>
      <item>
        <title>请教使用cygwin编译kvm</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/164164" style="color:red;">http://muscle-liu.javaeye.com/blog/164164</a>&nbsp;
          发表时间: 2008年02月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          hi, all<br /><br />我从 sun 上边下载了 cldc1.1 源码，打算扩展 kvm。但尝试用cygwin编译时，出现下边的错：<br /><pre name="code" class="java">
make 
>>>Recursively making ../../tools/preverifier/build/win32 all... 
make[1]: Entering directory `/cygdrive/f/j2me_cldc/tools/preverifier/build/win32 
' 
make[1]: *** [check_class.obj] Error 255 
make[1]: Leaving directory `/cygdrive/f/j2me_cldc/tools/preverifier/build/win32' 

make: *** [all] Error 1 

</pre><br /><br />期待各位的意见..you all will be appreciated.
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/164164#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 22 Feb 2008 12:33:47 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/164164</link>
        <guid>http://muscle-liu.javaeye.com/blog/164164</guid>
      </item>
      <item>
        <title>反射和代理（转载）</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/161451" style="color:red;">http://muscle-liu.javaeye.com/blog/161451</a>&nbsp;
          发表时间: 2008年02月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一. 关于数据库.<br />当今的数据处理大致可以分成两大类：联机事务处理OLTP（on-line transaction processing）、联机分析处理OLAP（On-Line Analytical Processing）。OLTP是传统的关系型数据库的主要应用，主要是基本的、日常的事务处理，例如银行交易。OLAP是数据仓库系统的主要应用，支持复杂的分析操作，侧重决策支持，并且提供直观易懂的查询结果。<br /><br />二. Java中的类反射： <br />反射就是把Java类中的各种成分映射成相应的java类.<br />Reflection 是 Java 程序开发语言的特征之一，它允许运行中的 Java 程序对自身进行检查，或者说“自审”，并能直接操作程序的内部属性。<br /><br />1．检测类： <br /><br />1.1 reflection的工作机制 <br /><br />考虑下面这个简单的例子，让我们看看 reflection 是如何工作的。 <br /><pre name="code" class="java">

import java.lang.reflect.*; 
public class DumpMethods { 
 public static void main(String args[]) { 
  try { 
   Class c = Class.forName(args[0]); 
   Method m[] = c.getDeclaredMethods(); 
   for (int i = 0; i &lt; m.length; i++) 
   System.out.println(m[i].toString()); 
  } 
  catch (Throwable e) { 
   System.err.println(e); 
  } 
 } 
} 
</pre><br /><br />按如下语句执行： <br /><br />java DumpMethods java.util.Stack <br /><br />它的结果输出为： <br /><pre name="code" class="java">

public java.lang.Object java.util.Stack.push(java.lang.Object) 

public synchronized java.lang.Object java.util.Stack.pop() 

public synchronized java.lang.Object java.util.Stack.peek() 

public boolean java.util.Stack.empty() 

public synchronized int java.util.Stack.search(java.lang.Object) 
</pre><br /><br />这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。 <br /><br />这个程序使用 Class.forName 载入指定的类，然后调用 getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。 <br /><br />1.2 Java类反射中的主要方法 <br /><br />对于以下三类组件中的任何一类来说 -- 构造函数、字段和方法 -- java.lang.Class 提供四种独立的反射调用，以不同的方式来获得信息。调用都遵循一种标准格式。以下是用于查找构造函数的一组反射调用： <br /><br />Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数， <br /><br />Constructor[] getConstructors() -- 获得类的所有公共构造函数 <br /><br />Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关) <br /><br />Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关) <br /><br />获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用，在参数类型数组中使用了字段名： <br /><br />Field getField(String name) -- 获得命名的公共字段 <br /><br />Field[] getFields() -- 获得类的所有公共字段 <br /><br />Field getDeclaredField(String name) -- 获得类声明的命名的字段 <br /><br />Field[] getDeclaredFields() -- 获得类声明的所有字段 <br /><br />用于获得方法信息函数： <br /><br />Method getMethod(String name, Class[] params) -- 使用特定的参数类型，获得命名的公共方法 <br /><br />Method[] getMethods() -- 获得类的所有公共方法 <br /><br />Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型，获得类声明的命名的方法 <br /><br />Method[] getDeclaredMethods() -- 获得类声明的所有方法 <br /><br /><br />1.3开始使用 Reflection： <br /><br />用于 reflection 的类，如 Method，可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤：第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中，用 java.lang.Class 类来描述类和接口等。 <br /><br />下面就是获得一个 Class 对象的方法之一： <br /><br />Class c = Class.forName("java.lang.String"); <br /><br />这条语句得到一个 String 类的类对象。还有另一种方法，如下面的语句： <br /><br />Class c = int.class; <br /><br />或者 <br /><br />Class c = Integer.TYPE; <br /><br />它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。 <br /><br />第二步是调用诸如 getDeclaredMethods 的方法，以取得该类中定义的所有方法的列表。 <br /><br />一旦取得这个信息，就可以进行第三步了——使用 reflection API 来操作这些信息，如下面这段代码： <br /><pre name="code" class="java">
Class c = Class.forName("java.lang.String"); 

Method m[] = c.getDeclaredMethods(); 

System.out.println(m[0].toString()); 
</pre><br /><br />它将以文本方式打印出 String 中定义的第一个方法的原型。 <br /><br />2．处理对象： <br /><br />如果要作一个开发工具像debugger之类的，你必须能发现filed values,以下是三个步骤: <br /><br />a.创建一个Class对象 <br />b.通过getField 创建一个Field对象 <br />c.调用Field.getXXX(Object)方法(XXX是Int,Float等，如果是对象就省略；Object是指实例). <br /><br />例如： <br /><pre name="code" class="java">
import java.lang.reflect.*; 
import java.awt.*; 

class SampleGet {  
 public static void main(String[] args) { 
  Rectangle r = new Rectangle(100, 325); 
  printHeight(r);  
 } 
 
 static void printHeight(Rectangle r) { 
  Field heightField; 
  Integer heightValue; 
  Class c = r.getClass(); 
  try { 
   heightField = c.getField("height"); 
   heightValue = (Integer) heightField.get(r); 
   System.out.println("Height: " + heightValue.toString()); 
  } catch (NoSuchFieldException e) { 
   System.out.println(e); 
  } catch (SecurityException e) { 
   System.out.println(e); 
  } catch (IllegalAccessException e) { 
   System.out.println(e); 
  } 
 } 
} 
</pre><br /><br />顾名思义，反射 (reflection) 机制就像是在吴承恩所写的西游记中所提及的「照妖镜」，可以让类别或对象 (object) 在执行时期「现出原形」。我们可以利用反射机制来深入了解某类(class) 的构造函数 (constructor)、方法 (method)、字段 (field)，甚至可以改变字段的值、呼叫方法、建立新的对象。有了反射机制，程序员即使对所想使用的类别所知不多，也能照样写程序。反射机制能够用来呼叫方法，这正是反射机制能够取代函数指针的原因。<br /><br />以 Java 来说，java.lang.reflect.Method (以下简称 Method) 类别是用来表示某类别的某方法。我们可以透过 java.lang.Class (以下简称 Class) 类别的许多方法来取得 Method 对象。Method 类别提供 invoke() 方法，透过 invoke()，此 Method 对象所表示的方法可以被呼叫，所有的参数则是被组织成一个数组，以方便传入 invoke()。<br /><br />举个例子，下面是一个名为 Invoke 的程序，它会将命令列的 Java 类别名称和要呼叫的方法名称作为参数。为了简单起见，我假定此方法是静态的，且没有参数：<br /><br /><pre name="code" class="java">
import java.lang.reflect.*;
class Invoke {        
 public static void main(String[] args ) {               
  try {                       
   Class c = Class.forName( args[0] );                       
   Method m = c.getMethod( args[1], new Class [] { } );                       
   Object ret = m.invoke( null, null );                       
   System.out.println(args[0] + "." + args[1] +"() = " + ret );               
  } catch ( ClassNotFoundException ex ) {                       
   System.out.println("找不到此类别");               
  } catch (NoSuchMethodException ex ) {                       
   System.out.println("此方法不存在");               
  } catch (IllegalAccessException ex ) {                       
   System.out.println("没有权限调用此方法");               
  } catch (InvocationTargetException ex ) {                       
   System.out.println("调用此方法时发生下列例外:\n" + ex.getTargetException() );               
  }        
 }
}
</pre><br /><br />我们可以执行 Invoke 来取得系统的时间：<br /><br />java Invoke java.lang.System CurrentTimeMillis执行的结果如下所示：<br /><br />java.lang.System.currentTimeMillis() = 1049551169474我们的第一步就是用名称去寻找指定的 Class。我们用类别名称 (命令列的第一个参数) 去呼叫 forName() 方法，然后用方法名称 (命令列的第二个参数) 去取得方法。getMethod() 方法有两个参数：第一个是方法名称 (命令列的第二个参数)，第二个是 Class 对象的数组，这个阵例指明了方法的 signature (任何方法都可能会被多载，所以必须指定 signature 来分辨。) 因为我们的简单程序只呼叫没有参数的方法，我们建立一个 Class 对象的匿名空数组。如果我们想要呼叫有参数的方法，我们可以传递一个类别数组，数组的内容是各个类别的型态，依顺序排列。<br /><br />一旦我们有了 Method 对象，就呼叫它的 invoke() 方法，这会造成我们的目标方法被调用，并且将结果以 Object 对象传回。如果要对此对象做其它额外的事，你必须将它转型为更精确的型态。<br /><br />invoke() 方法的第一个参数就是我们想要呼叫目标方法的对象，如果该方法是静态的，就没有对象，所以我们把第一个参数设为 null，这就是我们范例中的情形。第二个参数是要传给目标方法作为参数的对象数组，它们的型态要符合呼叫 getMethod() 方法中所指定的型态。因为我们呼叫的方法没有参数，所以我们传递 null 作为 invoke() 的第二个参数。<br /><br /><pre name="code" class="java">
 import  java.lang.reflect.Constructor;
 import  java.lang.reflect.Field;
 import  java.lang.reflect.Method;
 import  java.lang.reflect.Modifier;
 import  java.util.HashMap;

 public   class  TestRef   {
     public   static   void  main(String[] args)  throws  Exception  {
        TestRef testRef  =   new  TestRef();
        Class clazz  =  TestRef. class ;
        System.out.println( " getPackage() =  "   +  clazz.getPackage().getName());
        //  getModifiers()的返回值可以包含类的种类信息。比如是否为public,abstract,static 
        int  mod  =  clazz.getModifiers();
        System.out.println( " Modifier.isAbstract(mod) =  " + Modifier.isAbstract(mod));
        System.out.println( " getName() =  " + clazz.getName());
        System.out.println( " getSuperclass() =  " + clazz.getSuperclass().getName());
        System.out.println( " getInterfaces() =  " + clazz.getInterfaces()); // 实现了哪些Interface 
        System.out.println( " clazz.getDeclaredClasses() =  " + clazz.getDeclaredClasses()); // 包含哪些内部类 
        System.out.println( " getDeclaringClass() =  " + clazz.getDeclaringClass()); 
        // 如果clazz是inner class 那么返回其outer class 
         
        System.out.println( " ---------- " );
        Constructor[] constructor  =  clazz.getDeclaredConstructors(); // 返回一组构造函数 Constructor[] 
           if  (constructor  !=   null )  {
             for  ( int  i  =   0 ; i  &lt;  constructor.length; i ++ )   {
                System.out.println(constructor[i].getName());
            } 
        } 
        
        System.out.println( " ---------- " );
        Method[] method  =  clazz.getDeclaredMethods();  //  Method[] 
           if  (method  !=   null )  {
             for  ( int  i  =   0 ; i  &lt;  method.length; i ++ )   {
                System.out.println(method[i].getName());
            } 
        } 
        
        System.out.println( " ---------- " );
        Field[] field  =  clazz.getDeclaredFields();  //  Field[] 
           if  (field  !=   null )  {
             for  ( int  i  =   0 ; i  &lt;  field.length; i ++ )   {
                System.out.println(field[i].getName());
                System.out.println(field[i].getType().getName());
                System.out.println(field[i].get(testRef));
            } 
        } 
        
        //  动态生成instance(无参数) 
        Class clz  =  Class.forName( " reflection.TestRef " );
        Object obj  =  clz.newInstance();
        System.out.println(((TestRef)obj).getStr());
        
        //  动态生成instance(有参数) 
         Class[] params  =   new  Class[]  {String. class ,  int . class ,  double . class } ;
        Constructor construct  =  clz.getConstructor(params);
        //  JDK1.5的情况下可以直接用{"haha",999,100.01}作为参数         
         Object obj2  =  construct.newInstance(new Object[]{"haha",new Integer( 999 ),  new  Double( 100.01 )} ); 
        System.out.println(((TestRef)obj2).getStr());
        
        //  动态调用method(public method) 
         Class[] params2  =   new  Class[]  {String. class } ;
        Method methods  =  clz.getMethod( " setStr " , params2);
        methods.invoke(testRef,  new  Object[]  { " invoke method " } );
        System.out.println(testRef.getStr());
        
        //  动态改变field内容(public field) 
        Field fields  =  clz.getField( " str " );
        fields.set(testRef,  " set field's value " );
        System.out.println(testRef.getStr());
        
    } 
 
     public  TestRef()  {
        System.out.println( " --- complete TestRef() --- " );
    } 
    
    public  TestRef(String str,  int  i,  double  d)  {
         this .str  =  str;
         this .i  =  i;
         this .d  =  d;
        System.out.println( " --- complete TestRef(String str, int i, double d) --- " );
    } 
    
    public  String str  =   " I'm a string " ;

    int  i  =   1 ;

    double  d  =   3.14 ;

    HashMap map  =   new  HashMap();

     public   double  getD()   {
         return  d;
    } 
 
      public   void  setD( double  d)   {
         this .d  =  d;
    } 
 
      public   int  getI()   {
         return  i;
    } 
 
      public   void  setI( int  i)   {
         this .i  =  i;
    } 
 
      public  HashMap getMap()   {
         return  map;
    } 
 
      public   void  setMap(HashMap map)   {
         this .map  =  map;
    } 
 
      public  String getStr()   {
         return  str;
    } 
 
      public   void  setStr(String str)   {
         this .str  =  str;
    } 
} 
</pre><br /><br />三. 代理(Proxy)<br />1.<br />我们直接从代码入手吧，我们可以使用一个动态代理类(Proxy)，通过拦截一个对象的行为并添加我们需要的功能来完成。Java中的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口为我们实现动态代理类提供了一个方案，但是该方案针对的对象要实现某些接口；如果针对的目的是类的话，cglib为我们提供了另外一个实现方案。等下会说明两者的区别。<br />一、接口的实现方案：<br />1）首先编写我们的业务接口（StudentInfoService.java）：<br /><pre name="code" class="java">
public interface StudentInfoService{
 void findInfo(String studentName);
}
</pre><br />及其实现类（StudentInfoServiceImpl.java）：<br /><pre name="code" class="java">
public class StudentInfoServiceImpl implements StudentInfoService{
 public void findInfo(String name){
  System.out.println("你目前输入的名字是:"+name);
 }
}
</pre><br /><br />2）现在我们需要一个日志功能，在findInfo行为之前执行并记录其行为，那么我们就首先要拦截该行为。在实际执行的过程中用一个代理类来替我们完成。Java中为我们提供了实现动态代理类的方案：<br /><br />1'处理拦截目的的类（MyHandler.java）<br /><pre name="code" class="java">
import org.apache.log4j.Logger;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

public class MyHandler implements InvocationHandler{
 private Object proxyObj;
 private static Logger log=Logger.getLogger(MyHandler.class);
 
 public Object bind(Object obj){
  this.proxyObj=obj;
  return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
 }
 
 public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
  Object result=null;
  try{
   //请在这里插入代码，在方法前调用
   log.info("调用log日志方法"+method.getName());
   result=method.invoke(proxyObj,args); //原方法
   //请在这里插入代码，方法后调用
  }catch(Exception e){
   e.printStackTrace();
  }
  return result;
 }
}
</pre><br /><br />2'我们实现一个工厂，为了方便我们使用该拦截类(AOPFactory.java)：<br /><pre name="code" class="java">
public class AOPFactory{
 private static Object getClassInstance(String clzName){
  Object obj=null;
  try{
   Class cls=Class.forName(clzName);
   obj=(Object)cls.newInstance();
  }catch(ClassNotFoundException cnfe){
   System.out.println("ClassNotFoundException:"+cnfe.getMessage());
  }catch(Exception e){
   e.printStackTrace();
  }
  return obj;
 }
 
 public static Object getAOPProxyedObject(String clzName){
  Object proxy=null;
  MyHandler handler=new MyHandler();
  Object obj=getClassInstance(clzName);
  if(obj!=null) {
   proxy=handler.bind(obj);
  }else{
   System.out.println("Can't get the proxyobj");
   //throw
  }
  return proxy;
 }
}
</pre><br /><br />3)基本的拦截与其工厂我们都实现了，现在测试（ClientTest.java）：<br /><pre name="code" class="java">
public class ClientTest{
 public static void main(String[] args){
  StudentInfoService studentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
  studentInfo.findInfo("阿飞");
 }
}
</pre><br /><br />输出结果（看你的log4j设置）：<br />[INFO]调用log日志方法findInfo<br />你目前输入的名字是:阿飞<br />     这样我们需要的效果就出来了，业务处理自己在进行，但是我们实现了日志功能<br /><br />2.再看一个例子:<br />　　假设系统由一系列的BusinessObject所完成业务逻辑功能，系统要求在每一次业务逻辑处理时要做日志记录。这里我们略去具体的业务逻辑代码。 <br /><br /><pre name="code" class="java">
public interface BusinessInterface { 
　public void processBusiness(); 
} 

public class BusinessObject implements BusinessInterface { 
　private Logger logger = Logger.getLogger(this.getClass().getName()); 
　public void processBusiness(){ 
　　try { 
　　　logger.info("start to processing..."); 
　　　//business logic here. 
　　　System.out.println(“here is business logic”); 
　　　logger.info("end processing..."); 
　　} catch (Exception e){ 
　　　logger.info("exception happends..."); 
　　　//exception handling 
　　} 
　} 
} 

</pre><br />　　这里处理商业逻辑的代码和日志记录代码混合在一起，这给日后的维护带来一定的困难，并且也会造成大量的代码重复。完全相同的log代码将出现在系统的每一个BusinessObject中。 <br /><br />按照AOP的思想，我们应该把日志记录代码分离出来。要将这些代码分离就涉及到一个问题，我们必须知道商业逻辑代码何时被调用，这样我们好插入日志记录代码。一般来说要截获一个方法，我们可以采用回调方法或者动态代理。动态代理一般要更加灵活一些，目前多数的AOP Framework也大都采用了动态代理来实现。这里我们也采用动态代理作为例子。 <br />JDK1.2以后提供了动态代理的支持，程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器，然后通过java.lang.reflect.Proxy得到一个代理对象，通过这个代理对象来执行商业方法,在商业方法被调用的同时，执行处理器会被自动调用。 <br /><br />　　有了JDK的这种支持，我们所要做的仅仅是提供一个日志处理器。 <br /><br /><pre name="code" class="java">
public class LogHandler implements InvocationHandler { 

　private Logger logger ＝ Logger.getLogger(this.getClass().getName()); 
　　private Object delegate; 
　　public LogHandler(Object delegate){ 
　　　this.delegate = delegate; 
　　} 

　public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
　　Object o = null; 
　　try { 
　　　logger.info("method stats..." ＋ method); 
　　　o = method.invoke(delegate,args); 
　　　logger.info("method ends..." + method); 
　　} catch (Exception e){ 
　　　logger.info("Exception happends..."); 
　　　//excetpion handling. 
　　} 
　　return o; 
　} 
} 
</pre><br />　　现在我们可以把BusinessObject里面的所有日志处理代码全部去掉了。 <br /><pre name="code" class="java">
public class BusinessObject implements BusinessInterface { 

　private Logger logger = Logger.getLogger(this.getClass().getName()); 
　public void processBusiness(){ 
　　//business processing 
　　System.out.println(“here is business logic”); 
　} 
} 
</pre><br /><br />　　客户端调用商业方法的代码如下：<br /><br /><pre name="code" class="java">
BusinessInterface businessImp = new BusinessObject(); 

InvocationHandler handler = new LogHandler(businessImp); 

BusinessInterface proxy = (BusinessInterface) Proxy.newProxyInstance( 
　businessImp.getClass().getClassLoader(), 
　businessImp.getClass().getInterfaces(), 
　handler); 

proxy.processBusiness(); 
</pre><br /><br />　　程序输出如下： <br /><br /><pre name="code" class="java">
INFO: method stats... 
here is business logic 
INFO: method ends... 
</pre><br /><br />　　至此我们的第一次小尝试算是完成了。可以看到，采用AOP之后，日志记录和业务逻辑代码完全分开了，以后要改变日志记录的话只需要修改日志记录处理器就行了，而业务对象本身（BusinessObject）无需做任何修改。并且这个日志记录不会造成重复代码了，所有的商业处理对象都可以重用这个日志处理器。 <br /><br /><br /> <br /><br /><br /><br /><br />Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1155794
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/161451#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 04 Feb 2008 20:53:23 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/161451</link>
        <guid>http://muscle-liu.javaeye.com/blog/161451</guid>
      </item>
      <item>
        <title>纯做技术是自娱自乐 抛开技术做技术才是出路(转载)</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/161319" style="color:red;">http://muscle-liu.javaeye.com/blog/161319</a>&nbsp;
          发表时间: 2008年02月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          甘日采网上浏览，见到一篇关于做技术人对技术生涯的见解的文章，觉得有些观点值得参考一下， 源文：<a href="http://www.builder.com.cn/2007/1213/681681.shtml" target="_blank">http://www.builder.com.cn/2007/1213/681681.shtml</a><br /><br /><br />摘录一段关于“作事业”的心态的：<br /><div class="quote_title">引用</div><div class="quote_div"><br />“我自己的开发实践还在继续，还在继续写着代码，只是现在已经很少跟人就某个技术细节再进行多么深入多么深刻的讨论了(只跟我的同事讨论，网上讨论的很少)，而是把精力更多的放在了关注产品整体质量，促进产品整体质量方面。”这个“质量”不仅仅包括技术，还包括策划和设计环节，包括服务环节，甚至包括运营、维护环节。  <br /><br />所以大宝觉得“作事业”的心态，对于一个人的成长与成功非常重要。我们现在很多人，抱怨上天不给自己机会，待遇不好，环境不好，的确，很多的时候，我们确实是面临着这样的困难境地。但是，即使在不太好的环境里，我们也有选择的权利，我们有选择积极面对还是临阵退缩的权利，有选择激情奋斗还是得过且过的权利。积极的工作和生活态度，会让我们终生受用。当你以“作事业”的心态去面对自己的工作时，你会发现更宽广的空间和舞台，你自己的成长也会更快。 <br /><br />有很多人可能会说，“作事业”的心态说起来容易，我是把它当事业来作了，但我没取得应得的回报呀。我不反对确实存在这样的情况，这个世界永远充满着黑暗面，如果你总是以这样的心态去拒绝付出，那我只能说，你从团队得到的回报就会比你付出的更少。有这样抱怨的朋友，我建议你可以对比一下：自己当前的能力是不是与你的回报成正比的，不仅与公司内的比，也与公司外的比一比，与整个行业比一比。你要是实在觉得委屈，你大可以换一个公司，但是，有句话，我还是想提醒：换工作，不能仅仅为了看得到的那点工资，换工作的成本同时还包括了你要重建你的同事关系，上下级关系甚至行业资源，而这些，是决定你是不是能把一件事作成作大的重要因素，人的眼光，有的时候要放远一点，如果老板是值得跟随的老板，从未亏待过你，如果公司在可预期的未来不会马上倒闭进而导致你没有饭吃，何不再坚持一下呢？ <br /></div>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/161319#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 03 Feb 2008 16:29:10 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/161319</link>
        <guid>http://muscle-liu.javaeye.com/blog/161319</guid>
      </item>
      <item>
        <title>黑莓BlackBerry 模拟器上浏览网页</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/158859" style="color:red;">http://muscle-liu.javaeye.com/blog/158859</a>&nbsp;
          发表时间: 2008年01月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          BB 上有一个 browser，我们可以运行它来上网，就跟在电脑上一样，可以浏览你平时上的网。但是在模拟上，你需要安装 BlackBerry Email and MDS Services Simulators 在你的电脑上并运行起来，这样你才能正常上网。
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/158859#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 23 Jan 2008 23:14:12 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/158859</link>
        <guid>http://muscle-liu.javaeye.com/blog/158859</guid>
      </item>
      <item>
        <title>java产生随机数的方式小结</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/158474" style="color:red;">http://muscle-liu.javaeye.com/blog/158474</a>&nbsp;
          发表时间: 2008年01月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          下边是在<a href="http://hi.baidu.com/wliang950/blog/item/e0c54a82726789a30df4d2a7.html" target="_blank">http://hi.baidu.com/wliang950/blog/item/e0c54a82726789a30df4d2a7.html</a>]上转过来的<br /><div class="quote_title">引用</div><div class="quote_div"><br />一.在j2se里我们可以使用Math.random()方法来产生一个随机数，这个产生的随机数是0-1之间的一个double，我们可以把他乘以一定的数，比如说乘以100，他就是个100以内的随机，这个在j2me中没有。<br /><br />二.在java.util这个包里面提供了一个Random的类，我们可以新建一个Random的对象来产生随机数，他可以产生随机整数、随机float、随机double，随机long，这个也是我们在j2me的程序里经常用的一个取随机数的方法。<br /><br />三.在我们的System类中有一个currentTimeMillis()方法，这个方法返回一个从1970年1月1号0点0分0秒到目前的一个毫秒数，返回类型是long，我们可以拿他作为一个随机数，我们可以拿他对一些数取模，就可以把他限制在一个范围之内啦<br /><br />其实在Random的默认构造方法里也是使用上面第三种方法进行随机数的产生的<br /><br />对于方法二中的Random类有以下说明： <br /><br />java.util.Random类有两种方式构建方式：带种子和不带种子<br /><br />不带种子：<br /><br />此种方式将会返回随机的数字，每次运行结果不一样<br /><pre name="code" class="java">

public class RandomTest {

public static void main(String[] args) {

java.util.Random r=new java.util.Random(); 

for(int i=0;i&lt;10;i++){ 

System.out.println(r.nextInt());

}

}

</pre><br />带种子：<br /><br />此种方式，无论程序运行多少次，返回结果都是一样的<br /><pre name="code" class="java">

public static void main(String[] args) {

java.util.Random r=new java.util.Random(10);

for(int i=0;i&lt;10;i++){

System.out.println(r.nextInt());

}

}
</pre><br /><br />两种方式的差别在于<br /><br />(1) 首先请打开Java Doc，我们会看到Random类的说明：<br /><br />此类的实例用于生成伪随机数流，此类使用 48 位的种子，该种子可以使用线性同余公式对其进行修改（请参阅 Donald Knuth 的《The Art of Computer Programming, Volume 2》，第 3.2.1 节）。<br /><br />如 果用相同的种子创建两个 Random 实例，则对每个实例进行相同的方法调用序列，它们将生成并返回相同的数字序列。为了保证实现这种特性，我们为类Random指定了特定的算法。为了 Java 代码的完全可移植性，Java 实现必须让类 Random 使用此处所示的所有算法。但是允许 Random 类的子类使用其他算法，只要其符合所有方法的常规协定即可。<br /><br />Java Doc对Random类已经解释得非常明白，我们的测试也验证了这一点。<br /><br />(2) 如果没有提供种子数，Random实例的种子数将是当前时间的毫秒数，可以通过System.currentTimeMillis()来获得当前时间的毫秒数。打开JDK的源代码，我们可以非常明确地看到这一点。<br /><br />/** <br />* Creates a new random number generator. Its seed is initialized to <br />* a value based on the current time: <br />* Random() { this(System.currentTimeMillis()); }java.lang.System#currentTimeMillis()<br />*/ <br />public Random() { this(System.currentTimeMillis()); } <br /><br />另外： <br /><br />random对象的nextInt(),nextInt(int n)方法的说明：<br /><br />int nextInt() <br />返回下一个伪随机数，它是此随机数生成器的序列中均匀分布的 int 值。<br /><br />int nextInt(int n) <br />返回一个伪随机数，它是从此随机数生成器的序列中取出的、在 0（包括）和指定值（不包括）之间均匀分布的 int 值 <br /></div><br /><br />那么,怎样产生一列不重复的随机数呢？ 以产生1-12个不重复的随机数为例，网上有许多实现算法如：<br /><div class="quote_title">引用</div><div class="quote_div"><br />算法一：用java的随机方法生成一个数字，然后mod 12，如果和前面的数值有相同的，那么抛弃这个数值，否则保存，直到数组中有12个数为止。<br /><br />算法二：定义一个数组，长度为输入的数组的长，在得到输入的整数，即其长度时进行初始化，a[0]=1,a[1]=2,a[2]=3,......,a[11]=12。然后生成的数组为b[12],用随机函数产生1到12的整数，作为a数组的下标，然后顺序赋值给b数组，赋值过的a就讲其值置为0，每次在赋值b之前检查这个a是不是0，不是则赋值，是则再得到另外一个a。这比上一个算法应该好点吧。<br /></div><br /><br />这里本人提出一个简单些的算法，原理如下：<br />用一个长度为12的数组保存1-12个数,如a[12]； 在一个循环中，用随机函数产生0到11的整数，如 ranX, 与-1比较，如果不相等，就输出a[ranX], 然后把a[ranX]的值设为-1, 否则进入下一循环。<br /><pre name="code" class="java">
 public void createNumber(){
        int[] randoms = {1,2,3,4,5,6,7,8,9,10,11,12};
        Random randX = new Random();
        int x = 0;
        int count = 0;
        while(count != 12) {
            x = randX .nextInt(11);
            if(randoms[x] != -1) {
                System.out.println(randoms[x]);
                randoms[x] = -1;
                count ++;
            }
        }
    }
</pre><br /><br />各位谁有更好的方法，不防写出来一起讨论...
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/158474#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 23 Jan 2008 00:01:57 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/158474</link>
        <guid>http://muscle-liu.javaeye.com/blog/158474</guid>
      </item>
      <item>
        <title>JAVA对象比较器Comparator</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/157261" style="color:red;">http://muscle-liu.javaeye.com/blog/157261</a>&nbsp;
          发表时间: 2008年01月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          排序的算法是我们最常用的算法，初学程序，每个人都尝试过排序。但只是局限于简单的排序。<br />如将下列数字进行排序<br />1，3，5，8，3，6<br />于是我们得出结果<br />1，3，3，5，6，8<br />将下列字母（字符）进行排序<br />a,i,e,f,w,s<br />于是我们得出结果<br />a,e,f,i,s,w<br />但是我们遇到的情况就不是如此简单了。如给公司里的商品进行排序，我们很轻易的想到按照商品的名称排序不就完了，而且简单明了。但现实并如我们相信般简单。同一商品名称可以有不同的批次，进货时间，可能还会有单价的不同。显然只根据商品名称排序是不合理的。<br /><br />再举个简单例子然后用程序实现。如公司要将员工进行排序（不要说领导排在前面），假设我们的需求比较复杂。先进行姓排序，谁的姓拼音靠前，谁就排前面。然后对名字进行排序。恩.如果同名，女性排前头。如果名字和性别都相同，年龄小的排前头。ok，一个也不算复杂的需求。<br /><br />如果对java比较熟悉的会知道java.util.Comparator 接口。要实现里面的函数<br />int compare(Object o1, Object o2) 返回一个基本类型的整型，返回负数表示o1 小于o2，返回0 表示o1和o2相等，返回正数表示o1大于o2。<br /><br />于是我们设计的人员类要有几个变量，firstname,lastname,sex,age分别表示姓，名，性别，年龄。<br /><br /><pre name="code" class="java">
public class Person {
String firstname,lastname;
Boolean sex;
Integer age;
public Person(String firstname,String lastname,Boolean sex,Integer age) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.sex = sex;
    this.age = age;
}
public String getFirstName() {
     return firstname;
   }

   public String getLastName() {
     return lastname;
   }
   public Boolean getSex() {
      return sex;
    }

    public Integer getAge() {
      return age;
    }

//为了输入方便，重写了toString()
public String toString()
    {
      return firstname +" "+lastname+" "+(sex.booleanValue()?"男":"女")+" "+age;
    }
}
//end person

</pre><br /><br />下面是要实现比较器<br /><br /><pre name="code" class="java">
public class Comparators {
public static java.util.Comparator getComparator() {
    return new java.util.Comparator() {

      public int compare(Object o1, Object o2) {
        if (o1 instanceof String) {
          return compare( (String) o1, (String) o2);
        }else if (o1 instanceof Integer) {
          return compare( (Integer) o1, (Integer) o2);
        }else if (o1 instanceof Person) {
        return compare( (Person) o1, (Person) o2);
        }else {
          System.err.println("未找到合适的比较器");
          return 1;

        }
      }

      public int compare(String o1, String o2) {
        String s1 = (String) o1;
        String s2 = (String) o2;
        int len1 = s1.length();
        int len2 = s2.length();
        int n = Math.min(len1, len2);
        char v1[] = s1.toCharArray();
        char v2[] = s2.toCharArray();
        int pos = 0;

        while (n-- != 0) {
          char c1 = v1[pos];
          char c2 = v2[pos];
          if (c1 != c2) {
            return c1 - c2;
          }
          pos++;
        }
        return len1 - len2;
      }

      public int compare(Integer o1, Integer o2) {
        int val1 = o1.intValue();
        int val2 = o2.intValue();
        return (val1 &lt; val2 ? -1 : (val1 == val2 ? 0 : 1));

      }
      public int compare(Boolean o1, Boolean o2) {

         return (o1.equals(o2)? 0 : (o1.booleanValue()==true?1:-1));

       }

      public int compare(Person o1, Person o2) {
        String firstname1 = o1.getFirstName();
        String firstname2 = o2.getFirstName();
        String lastname1 = o1.getLastName();
        String lastname2 = o2.getLastName();
        Boolean sex1 = o1.getSex();
        Boolean sex2 = o2.getSex();
        Integer age1 = o1.getAge();
        Integer age2 = o2.getAge();
        return (compare(firstname1, firstname2) == 0 ?
             (compare(lastname1, lastname2) == 0 ? (compare(sex1, sex2) == 0 ? (compare(age1, age2) == 0 ? 0 :
              compare(age1, age2)) :
              compare(sex1, sex2)) :
              compare(lastname1, lastname2)) :
              compare(firstname1, firstname2));

      }

    };
}

}
</pre><br />以上代码有可能因为浏览器的布局自动换行。<br />compare(Person o1, Person o2)的返回值看起来比较别扭。最简单的是<br /><pre name="code" class="java">
    public int compare(Boolean o1, Boolean o2) {

         return (o1.equals(o2)? 0 : (o1.booleanValue()==true?1:-1));

     }
</pre><br /><br />o1和o2相等返回0，否则o1如果是true 就表示o1大于o2。<br /><br />再尝试输出结果看看<br /><br /><br /><pre name="code" class="java">
public class Main {
public Main() {
}
public static void main(String[] args) {
    Person[] person = new Person[] {
         new Person("ouyang", "feng", Boolean.TRUE, new Integer(27)),
         new Person("zhuang", "gw", Boolean.TRUE, new Integer(27)),
         new Person("zhuang", "gw", Boolean.FALSE, new Integer(27)),
         new text.Person("zhuang", "gw", Boolean.FALSE, new Integer(2)),


     };
     for (int i = 0; i &lt; person.length; i++) {
       System.out.println("before sort=" + person[i]);
     }
     java.util.Arrays.sort(person, Comparators.getComparator());

     for (int i = 0; i &lt; person.length; i++) {
        System.out.println("after sort=" + person[i]);
     }


}

}

</pre><br />输出结果：<br /><br /><pre name="code" class="java">
before sort=ouyang feng 男 27

before sort=zhuang gw 男 27

before sort=zhuang gw 女 27

before sort=zhuang gw 女 2

after sort=ouyang feng 男 27

after sort=zhuang gw 女 2

after sort=zhuang gw 女 27

after sort=zhuang gw 男 27

</pre><br />仔细理解java的Comparator会给你写排序带来很大帮助<br /><br />文章来自:<a href="http://hi.baidu.com/zgz0809/blog/item/fdc65e16f1c4181b962b43e1.html" target="_blank">http://hi.baidu.com/zgz0809/blog/item/fdc65e16f1c4181b962b43e1.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/157261#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 18 Jan 2008 13:54:39 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/157261</link>
        <guid>http://muscle-liu.javaeye.com/blog/157261</guid>
      </item>
      <item>
        <title>j2me 中http与socket的区别</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/155078" style="color:red;">http://muscle-liu.javaeye.com/blog/155078</a>&nbsp;
          发表时间: 2008年01月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近日睇着关于j2me GCF方面的野，发觉对于http与socket两种协议有点不明。在网上查了一下才了解到：<br /><br />1、http协议手机都支持，socket不一定   <br />2、http只能是一问一答（即系以request/response噶方式连网收发信息）， 而socket可以双向通讯（定位到某一URL后，就可以双方收发信息，无需request/response）   <br /><br /><br />GCF连接接口:<br /><br />Connection接口是最基本的连接,可以用于打开或关闭一个连接.  <br /><br />在流连接中,可以使用ContentConnection接口访问放置在Web服务器上的信息;  <br /><br />可以使用DatagramConnection接口通过自带寻址信息的数据包进行连接，完成包的传输；  <br /><br />可以使用InputConnectiont和OutputConnection接口从通信设备接收数据和发送数据到通信设备；  <br /><br />可以使用StreamConnection接口实现通信设备间的双向传输；  <br /><br />建立流连接时，可以使用StreamConnectionNotifier接口
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/155078#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 11 Jan 2008 14:21:40 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/155078</link>
        <guid>http://muscle-liu.javaeye.com/blog/155078</guid>
      </item>
      <item>
        <title>netbeans+j2mepolish 环境下开发黑莓(BlackBerry) 程序</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/152564" style="color:red;">http://muscle-liu.javaeye.com/blog/152564</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近日公司要求把之前做的一个 j2mepolish 项目在 BB 上运行。我是一个新手，所以一星期了，还是有小部分bug, 没能成功运行。下边是我对 BB 应用程序开发的一些见解：<br /><br />BlackBerry 的介绍我不说了，想了解的朋友可以在网上搜索。在开发之前准备的开发工具：Java JDK, BB JDE, BB emulator. 其中BB JDE/emulator 可以到BB主站下载：<a href="www.blackberry.com" target="_blank">www.blackberry.com</a>, 但本人在公司的机上下载不了，显示IP不允许(=.=)，所以找到一个国内网站可以下载：<a href="http://down.maxpda.com/download/category-86-1.html" target="_blank">http://down.maxpda.com/download/category-86-1.html</a><br /><br />第一次使用 BB 模拟器的可以浏览下<a href="http://hi.baidu.com/ay_digitalbaby/blog/item/fa3520384b7213f3b211c7f8.html" target="_blank">http://hi.baidu.com/ay_digitalbaby/blog/item/fa3520384b7213f3b211c7f8.html</a>里边是使用 BB 模拟器的教程。<br /><br />在网上广为流传的一份 BlackBerry 应用程序开发者指南：<a href="http://www.36sign.com/blog/blackberry/the-guide-of-blackberry-development.html" target="_blank">http://www.36sign.com/blog/blackberry/the-guide-of-blackberry-development.html</a>里边详细介绍如何用BB api开发BB application 的各方面内容。<br /><br />但是我们一般都是用j2me开发，开发出来的程序是 jar 格式，可以运行在大部分型号的手机上。可是 BB 是不支持 jar 的，它支持的是 cod 格式。所以如果你想你开发的 j2me 程序运行在 BB 上，就必须先把它转为 cod 格式。<br />要把一般 j2me 程序转为 cod 可以在程序开发编译过程序中转，也可以对打包好的jar 转。<br /><br />1) 对已经打包好的 jar 文件转为 BB cod 格式: 进入 jar 文件所在目录，在cmd(命令行) 中进入相应目录，输入下边命令就可以了：<div class="quote_title">引用</div><div class="quote_div">rapc import="C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\lib\net_rim_api.jar" codename=TestBB jad=TestBB.jad TestBB.jar</div>(注：这里rapc 是 C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\bin\ 目录里的 rapc.exe, 如果环境变量没有设置，这里就要用绝对路径：C:\Program Files\Research In Motion\BlackBerry JDE 4.2.1\bin\rapc, 当然你可以把它写成一个.bat文件来执行。而网上你可以搜索到一个名为 Java2Cod.exe 的小程序可以直接转换。) <br /><br />2) 在JDE中编译程序: 无论你是用 BB api 或者 j2me/midp api 来开发j2me程序，都可以在 JDE 上编译。最终他会自动打包成 cod 文件。<br /><br />3) 在其 IDE 中编译打包：因为我是用 netbeans 来开发的，所以本人只能提供用 netbeans 开发 BB 程序的见解。<a href="http://gceclub.sun.com.cn/NetBeans/tutorials/mobility/blackberry.html" target="_blank">http://gceclub.sun.com.cn/NetBeans/tutorials/mobility/blackberry.html</a> 这里有介绍如何整合netbean 来开发 BB 程序。<br />而本人是在 netbean 中用 j2mepolish 来整合开发的。下边介绍j2mepolish 中开发 BB 程序（可以参考<a href="http://www.j2mepolish.org/docs/platform-blackberry.html" target="_blank">http://www.j2mepolish.org/docs/platform-blackberry.html</a>）: <br /><br />一）、在 j2mepolish 安装目录里找到 platforms.xml, 在里边的 BlackBerry 部分中，加上 &lt;capability name="build.Finalizer" value="jar2cod" />（我用的是Preview 2.0版本，里边这一句是注释掉，所以要把它 activate , 也可以在 devices.xml 中在你想用的 emulator 属性里加上这一句。如果没有这一句编译时就不会自动把 jar 转换为 cod 文件的.）<br />polish里支持的版本最新系4.2.0, 如果你安装噶 BB 版本最新的如4.2.1/4.3.0,哪么你要把${BB目录}/lib/net_rim_api.jar copy 到 ${j2mepolish}/import 里，在platforms.xml 的 BlackBerry 中修改&lt;capability name="build.BootClassPath" value="net_rim_api.jar" /> <br /><br />二）、在工程的 build.xml 中添加 blackberry.home 属性（你安装的BB JDE目录）<br /><pre name="code" class="java">
&lt;property 
	name="blackberry.home" 
	location="C:/Program Files/Research In Motion/BlackBerry JDE 4.2.1" 
/>
</pre><br />三）、如果你编译后打包的 jad 文件中缺少 MicroEdition-Configuration 和 MicroEdition-Profile 两个属性是不能成功转成 cod 文件的。这可以在工程的 build.xml 中的&lt;build>属性里的&lt;jad>元素中添加：<br /><pre name="code" class="java">
&lt;jad>
  &lt;attribute target="jad" name="MicroEdition-Configuration" value="CLDC-1.1" if="polish.cldc11"/>
  &lt;attribute target="jad" name="MicroEdition-Profile" value="MIDP-2.0"/>
&lt;/jad>
</pre><br />四）、如果你用了混淆器的（obfuscator），要把它 unactivate, 不要用它，因为 BB 中的 rapc 转换过程中会对程序混淆的。<br /><pre name="code" class="java">
&lt;obfuscator name="ProGuard" unless="test or polish.blackberry" >
&lt;/obfuscator>
</pre><br />五）、在工程的 build.xml 中的&lt;j2mepolish>属性 requirements 用你想编译的 BB emulator,如：<br /><pre name="code" class="java">
&lt;deviceRequirements>
   &lt;requirement name="Identifier" value="BlackBerry/8800" />           
&lt;/deviceRequirements>
</pre><br />如果你的程序是一般的j2me程序，那么就可以编译运行了。但如果你是用 BB api 开发的，就要就把build.xml里&lt;build>元素中的&lt;midlet>,改为&lt;main>，同时要添加 polish.classes.midlet-1 的variable, 如：<br /><pre name="code" class="java">
&lt;!-- midlets definition -->
&lt;main class="com.protel.bbim.ui.BBIMMidlet" />
                
&lt;!-- project-wide variables - used for preprocessing  -->
&lt;variables>
   &lt;variable name="polish.classes.midlet-1" value=" " />
&lt;/variables>
</pre><br />(注：polish.classes.midlet-1 的 value 是" "，中间有一个空格的，我试过了，如果没有这个定义变量或者这个值中间没有空格，jar 是不能转为 cod 格式。)<br /><br />这是我初接触 BB 时的一点心得。我用BB api 在netbeans+j2mepolish的环境下写过一个test app，是能成功运行的，希望对初接触 BB 的朋友有帮助。
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/152564#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 07 Jan 2008 15:11:19 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/152564</link>
        <guid>http://muscle-liu.javaeye.com/blog/152564</guid>
      </item>
      <item>
        <title>j2mepolih 中获取 TreeItem 的多级节点</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/145433" style="color:red;">http://muscle-liu.javaeye.com/blog/145433</a>&nbsp;
          发表时间: 2007年12月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用过 j2mepolish 的人一定知道，在 现在发行的 polish 2.0RC4 版本里有一个 TreeItem 的 component。 TreeItem 可以动态实现一个多级节点的树结构，而且其节点是一个 Item(只要是 polish 里边的 Item 都可以，如 StringItem, IconItem ..), 同时 TreeItem 是一个 Item 很容易被 j2me 里的高级UI调用。 但是在现有的版本中，TreeItem 里边的方法 getFocusedItem/getFocusedIndex 返回的是第一级结点，并不能返回 2+ 级结点。如下边的一个树结构(设名为: treeItem)：<br /><pre name="code" class="java">
A
  A1
  A2
  ...
B
  B1
  B2
  ...
</pre><br />当光标（焦点）在 A 或是在 A1/A2 时， treeItem.getFocusedItem()都是返回 A，而 treeItem.getFocusedIndex() 返回的是0；同理，当光标（焦点）在 B 或是在 B1/B2 时，这两个方法返回是分别是 B 和 1；<br /><br />研究了一下 polish 里边的 TreeItem.java 源文件， 发现里嵌套了一个结点类 Node, 这个 Node 类其实就是一个 Item 类的一个子类， 里边主要有一个叫 children 的属性（是一个 Container，而 Container 相当于 Java 中的 List），用来保存当前结点的子结点。所以我们调用 getFocusedItem() 里并没有具体深入到其子结点里边，只是获取的第一级结点。下边是我对获取第二级以上结点添加的一个方法：<br /><pre name="code" class="java">
public Item getExactItem(Item item){    
    if( item instanceof Node && item != null){
        if( ((Node)item).children.size() != 0){
            item = ((Node)item).children;
            if(item instanceof Container){
               return getExactItem( ((Container)item).getFocusedItem() );
            }
        } 
    }

    return item;
}
</pre><br /><br />只要我们把 treeItem.getFocusedItem() 得到的 Item 做为参数代入上边方法就可以获得 TreeItem 的真正焦点 Item。如上边的 treeItem, 当光标（焦点）在 A1 时，treeItem.getExactItem( treeItem.getFocusedItem() ) 得到的是 A1 了。<br /><br />而对于怎样修改 polish 源文件，本人方法如下： 在 polish 安装目录下的 lib 里边有个 enough-j2mepolish-build.jar 的包（其实这是build.xml文件里边&lt;taskdef> 的classpath属性里必要的一个包），里边有 polish 各component 的源文件。 用 RAR 的方式打开 enough-j2mepolish-build.jar，进入相应路径(注意这里并不是解压出来，你修改时可以另外解压出来修改)， 把修改好的 TreeItem 源文件， 直接添加替换旧的就可以了。修改后，在IDE里边或许会显示找不到这个方法，但是编译是可以通过的(因为polish工程编译时是调用 enough-j2mepolish-build.jar 里的源文件编译的)。
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/145433#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 02 Dec 2007 14:55:10 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/145433</link>
        <guid>http://muscle-liu.javaeye.com/blog/145433</guid>
      </item>
      <item>
        <title>j2mepolish中obfuscator(混淆器)的应用</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/143150" style="color:red;">http://muscle-liu.javaeye.com/blog/143150</a>&nbsp;
          发表时间: 2007年11月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: 14pt">我们知道在j2mepolish带有一个ant构件工具，且有一个build.xml文件。在build.xml里边定义了一个工程的编译（compile）、混淆（obfuscate）、打包（package）.....等命令。所以很多人都喜欢用j2mepolish来的ant来管理一个j2me工程的编译打包工作，即使他们没用到polish， 避免了用ant时写build文件的麻烦。<br /><br />build.xml:<br /><pre name="code" class="java">
&lt;build
     symbols="ExampleSymbol, AnotherExample"
     imageLoadStrategy="foreground"
     fullscreen="menu"
     usePolishGui="true"
     >
     &lt;!-- midlets definition -->
     &lt;midlet class="de.enough.polish.example.MenuMidlet" name="Example" />
     &lt;!-- project-wide variables - used for preprocessing  -->
     &lt;variables>
       &lt;variable name="update-url" value="http://www.enough.de/update" />
     &lt;/variables>
     &lt;!-- obfuscator settings -->
     &lt;obfuscator name="ProGuard"
                    useDefaultPacakge="true" 
                    unless="test"  />
     &lt;!-- debug settings -->
     &lt;debug showLogOnError="true" 
               verbose="true" 
               level="error"
	       if="test" 
	       >
        &lt;filter package="de.enough.polish.example" level="debug" />
        &lt;filter class="de.enough.polish.ui.Gauge" level="info" />
     &lt;/debug>
&lt;/build>
</pre><br /><br />         现在我主要谈谈polish中的obfuscator(混淆器)的应用。我们知道J2ME的应用开发极大地受到了设备的限制。通常可下载类应用限制在几百K左右，设备本身限制在64k、100k、128k等不等。尽管现在的手机的内存可以达到1G(有些可以用内存卡)，但一个应用程序的大小还是尽可能小好，因为这可能影响程序的性能。<br /><br />下边是网上关于j2me应用程序瘦身的办法：<br /><br /><div class="quote_title">引用</div><div class="quote_div"><br />1。 使用混扰obfuscate（正规减肥）<br /><br />Java语言采用按名索引链接。包名，类变量名被保留在class的常量表中，混扰后有意义的名称被短的无意义的字串所代替，从此减少程序大小。同时混扰同时去掉了行号等调试信息（如果编译选项中未去掉）。另外，通常的混扰工具还将从未用过的方法、变量删除，从而减少程序空间。<br /><br />特点：不涉及源程序，易于维护。瘦身率 10%-30%<br /><br /><br />2。“优化”包结构（常规减肥）<br /><br />一些混扰工具不改变包的结构，也不能减少包的层次，如“com.pip.kstock.util.Tools”可能被混扰成“b.a.a.b.t”；而“com_pip_kstock_util.Tools”则可能成为“b.t”.这是配合混扰工具的减肥措施。另外，要明确分离被保护的包，因为被保护的包的所有类的包名都被保护。<br /><br />特点：不改变类结构及源程序。瘦身率：3%-5%<br /><br />3。优化程序（专业减肥）<br /><br />此减肥方法是对源程序的调整，诸如“注释掉不用的方法”（若混扰工具不能做到的话）；去掉无用的赋值和语句；优化语句；针对空间优化算法等。<br /><br />如使用arraycopy替代for循环复制；<br /><br />再如双字符串联结：<br />String s = “abc” + strVar;<br />String s = “abc”.concat(strVar);<br />（有的编译器将语句1编译成构造StringBuffer，这时语句2将省空间）<br /><br /><br />特点：正规化瘦身，工作量大。瘦身率：依情况而定<br /><br />4。合并类（非常规减肥）<br /><br />将若干子类合并到父类中，或将若干个不冲突的类合并成一个类。通过type或classID来判别具体实例属于哪个类，再应用公有的方法使用switch()转接到更名后的方法。<br /><br />如public paint()可能会调用private paint4XXXVies()。<br /><br />设计时还可使用重名变量进一步节省空间，但代码可读性大大降低。<br /><br />特点：破坏面向对象设计、维护困难。瘦身率：高（合并一个类大约可瘦身1-3K）<br /><br />5。挤压实现（疯狂减肥）<br /><br />属于变态减肥方法，包括：<br /><br />用直接访问变量的方式取代getter/setter方法<br />废除常量定义（一些混扰工具可完成）；<br />减少变量和字符串。<br />特点：破坏面可读性、维护艰难。瘦身率：低（在临界值时使用）<br /><br />上述瘦身方法均是针对已经成型产品。而在程序开始设计时，瘦身的考虑也是相当重要的。下面根据实际情况举一些小例子：<br /><br />1。保留计算结果<br /><br />在前面提到的瘦身技术中包括getter/setter方法替换方式，而对一些类的属性可考虑固化变量法，即在初始化时将此属性值记录到类的成员变量中。但此属性必须是初始就确定、运行中不会改变或极少改变（改变的地方要重赋值）；另外，由于此方法不能实现lazy loading，故要求属性是被“必然访问”的属性。<br /><br />2。集中分支语句<br /><br />在CLDC规范中，有一个J2SE虚拟机之外的东西，即preverify，对应到类文件中是StackMap结构。如果你的一个函数代码中没有分支语句，包括没有异常处理，StackMap将缺席并使用缺省的内容。这在节省空间上有好处。<br /><br />另外，StackMap结构的单元尺寸和代码段长度有关，所以避免写太长的方法。<br /><br />3。关于变量初值<br /><br />java的成员变量的初值不象写起来那样简单，他们是在类的初始化函数块中被赋予的。如果你想赋的初值同缺省的值一致，那么请省下5-6个字节吧。（不要因程序风格而犹豫，写上你的注释）<br /><br />（该篇文章引用：<a href="http://clwu.bokee.com/1632798.html" target="_blank">http://clwu.bokee.com/1632798.html</a>）<br /></div><br /><br />可见混淆器（obfuscator）是优化一个j2me应用程序的主要利器。我们来看回polish中的obfuscator, 在polish中带有三个obfuscator: "ProGuard", "YGuard", "RetroGuard"， 其中默认是用"ProGuard"。在上边的build.xml里边我们看到有obfuscator setting 的部分， 在这里我们可以对工程的obfuscation设置。当然，如果你不想用obfuscator， 只要把这个settings 部分注释掉就行了。<br /><br />下边来看看obfuscator的设置：<br /><pre name="code" class="java">
&lt;obfuscator unless="test" enable="true" name="ProGuard" >
	&lt;keep class="com.company.dynamic.SomeDynamicClass" />
	&lt;keep class="com.company.dynamic.AnotherDynamicClass" />
	&lt;parameter name="scriptFile" value="../scripts/obfuscate.script" />
&lt;/obfuscator>
</pre><br />其主要属性与元素：<br />属性name: 指定当前obfuscator的名称，其中"ProGuard"是默认的，如果你想用其的的obfuscator,只要在build.xml中指定相应的classPath就可以了。<br /><br />元素&lt;keep/>: 保留你不想参与混淆的类，留给程序动态加载。这个很好用，当你混淆某个工程后，运行时却发现有部分的类找不到，显示java.lang.ClassNotFoundException, 这时你可以用&lt;keep/>把这个类保留下来，给程序动态加载。（我用polish混淆时碰过这情况，不知用其它混淆时（如JB）有没有？？^_^）<br /><br />元素&lt;parameter/>: 当你想合用第三方的混淆器时，指定第三方混淆的配置。还有的是，ProGuard 3.x 提供了一个字节代码优化器(默认是false)，当你用ProGuard混淆器时可以用此元素来优化代码：<br /><pre name="code" class="java">
&lt;obfuscator unless="test" enable="true" name="ProGuard" >
	&lt;parameter name="optimize" value="true" />
&lt;/obfuscator
</pre><br /><br />如果你想几个obfuscator一起用，也可以，只要连着写几个&lt;obfuscator/>就可以了。<br /></span>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/143150#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 23 Nov 2007 21:26:00 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/143150</link>
        <guid>http://muscle-liu.javaeye.com/blog/143150</guid>
      </item>
      <item>
        <title>甘日我台电脑被静电电到差吾多死机</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/142775" style="color:red;">http://muscle-liu.javaeye.com/blog/142775</a>&nbsp;
          发表时间: 2007年11月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: 16pt"><br />    天气逐渐冻了，广东甘年噶冬季有返的寒意了，所以人身体间更容易产生噶静电了。下午我噶同事过来问我问题，他噶手一碰到我肩膀，我全身有着触电噶感觉。我知道是他的手与我的衣服间产生了静电。而我噶右手正好在用紧鼠标，这时我发现鼠标动不了，更惊啊噶系整台电脑慢起来了，按一个键要过5-6秒电脑才有响应~~~<img src="/images/smiles/icon_sad.gif"/>晕啊...我重起系统且重新拨插过鼠标才能正常用..<br /></span>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/142775#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 22 Nov 2007 20:15:11 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/142775</link>
        <guid>http://muscle-liu.javaeye.com/blog/142775</guid>
      </item>
      <item>
        <title>对软件反破解的一个想法</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/142403" style="color:red;">http://muscle-liu.javaeye.com/blog/142403</a>&nbsp;
          发表时间: 2007年11月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: 16pt">甘日落班时在车上，突然脑中想着关于软件的版权噶问题。我地知道一个新<br />推出噶软件，无论算法如何高深的加密，在一定时期内定有人破解之。所以一个软件加密得好与坏系在乎于它让人破解出来噶时间。<br /><br />       我一想，而家网上存在甘多病毒，能吾能在软件中划分一个区出来放专病毒，加密软件时，set个关口，一但破解着就立即触发病毒，让软件不能用或让破解者噶电脑受到侵害，从而达到让人破解费时~~~<img src="/images/smiles/icon_smile.gif"/></span>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/142403#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 21 Nov 2007 19:02:48 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/142403</link>
        <guid>http://muscle-liu.javaeye.com/blog/142403</guid>
      </item>
      <item>
        <title>读写RMS 的两种方法</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/138275" style="color:red;">http://muscle-liu.javaeye.com/blog/138275</a>&nbsp;
          发表时间: 2007年11月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近在做项目中， 在客户端要创建一个RMS给服务端读取，服务端已经写好了。但因为不知道服务端是好何读取的， 而我又是一个新手，所以在网上找了许多关于读写RMS的方法。我们知道RMS的读写都是用byte[], 网上说的大部分都是用<br />ByteArrayOutputStream/DataOutputStream写数据，而用ByteArrayInputStream/DataInputStream 来读数据。其用法如下：<br /><br />假设要把String strHello = "Hello, string!";写入RMS,写数据的代码：<br /><pre name="code" class="java">
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeUTF(strHello);
byte[] rec = baos.toByteArray();
.......//把rec写入rms

baos.close();
dos.close();
</pre><br /><br />而读数据的代码：<br /><pre name="code" class="java">
......
ByteArrayInputStream bais = new ByteArrayInputStream(rec);
//rec是 从rms读取出来的byte[] 类型
DataInputStream dis = new  DataInputStream(bais);
strHello = dis.readUTF();

bais.close();
dis.close();
</pre><br /><br /><br />当我用这个方法写数据入RMS，项目运行时却发现服务返回是" {Hello,string!"。一时间我不知是错在哪里（很奇怪的，在output <br /><br />window里我想copy这个字符串时，是copy不了的，如果不copy ‘{’，就可以。）。<br /><br />后来我看了服务器读数据时的代码才知道，服务器读数据时直接用rec.toString();返回数据的。所以我把读写数据直接用String类<br /><br />的方法就可以了。<br /><br />写数据的代码：<br /><pre name="code" class="java">
byte[] rec = strHello.getBytes();
.....
</pre><br /><br />读数据：<br /><pre name="code" class="java">
.....
strHello = rec.toString();
</pre><br /><br />所以在读写RMS时的方法要用同一类型，不然就会得到意想不到的结果...
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/138275#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 06 Nov 2007 08:43:35 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/138275</link>
        <guid>http://muscle-liu.javaeye.com/blog/138275</guid>
      </item>
      <item>
        <title>mmapi 在j2me polish中的应用</title>
        <author>muscle-liu</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://muscle-liu.javaeye.com">muscle-liu</a>&nbsp;
          链接：<a href="http://muscle-liu.javaeye.com/blog/129113" style="color:red;">http://muscle-liu.javaeye.com/blog/129113</a>&nbsp;
          发表时间: 2007年10月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近日工作中，要在j2me polish项目里实现mmapi， 其中的视频的实现在j2me polish与一般j2me项目里是不同的，弄了一天都不能播放。后来在网上问了一个高手才知道，下面我们看看Video Play 在polish中的实现：<br /><br />j2me里实现mmapi的基本解释我不多说了，不了解的可以参考 <a href="http://hi.baidu.com/cobalt/blog/item/fdb457c25e4c0237e4dd3b71.html" target="_blank">http://hi.baidu.com/cobalt/blog/item/fdb457c25e4c0237e4dd3b71.html</a> 里边讲得很详细的，我们主要看看实现mmapi video的播放的代码：<br /><br />java 代码:<br /><br /><pre name="code" class="java">
try {
	InputStream is = getClass().getResourceAsStream("/3.mpg");
	Player p = Manager.createPlayer(is, "video/mpeg");
	p.realize();
	// Grab the video control and set it to the current display.
	VideoControl vc = (VideoControl)p.getControl("VideoControl");
	if (vc != null) {
		Form form = new Form("Video form");
		form.append((Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null));
		display.setCurrent(form);
	}
	p.start();
} catch (IOException ioe) {
} catch (MediaException me) { }

</pre><br /><br />当我在j2me polish工程中按这样实现的时候，老是出现下边的异常：<br /><br /><pre name="code" class="java">
Generic/DefaultColorPhone: startApp threw an Exception
Generic/DefaultColorPhone: java.lang.ClassCastException
Generic/DefaultColorPhone: java.lang.ClassCastException
Generic/DefaultColorPhone:  at com.protel.MM.UI.MMMidlet.startApp(+224)
Generic/DefaultColorPhone: [javac] C:\Documents and Settings\winxp\Desktop\mmapi\source\src\com\protel\MM\UI\MMMidlet.java:57: form.append((Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null));
Generic/DefaultColorPhone:  at javax.microedition.midlet.MIDletProxy.startApp(+7)
Generic/DefaultColorPhone:  at com.sun.midp.midlet.Scheduler.schedule(+270)
Generic/DefaultColorPhone:  at com.sun.midp.main.Main.runLocalClass(+28)
Generic/DefaultColorPhone:  at com.sun.midp.main.Main.main(+116)
</pre><br /><br />原来在j2me polish应用中所有的Screen或Item都经过preproceses（预处理），故所有新创建或返回的Screen/Item都默认是de.enough.polish.ui.*里边的，<br />所以直接调用上边的代码时会发生类型转换异常。所以要在j2me polish项目中正常播放video要直接引用javax.microedition.lcdui.*<br />的类，修改后的代码如下：<br /><br /><pre name="code" class="java">
try { 
         System.out.println("~~~~~~~~~~"+getClass().getResourceAsStream("/3.mpg"));
	InputStream is = getClass().getResourceAsStream("/3.mpg");
	Player p = Manager.createPlayer(is, "video/mpeg");
	p.realize();
	// Grab the video control and set it to the current display.
	VideoControl vc = (VideoControl)p.getControl("VideoControl");
	if (vc != null) {
		javax.microedition.lcdui.Form form = new javax.microedition.lcdui.Form("Video form");
		javax.microedition.lcdui.Item videoItem = (javax.microedition.lcdui.Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
		form.append(videoItem);
		
		display.setCurrent(form);
	}
	p.start();
} catch (IOException ioe) {
} catch (MediaException me) { }
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://muscle-liu.javaeye.com/blog/129113#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 04 Oct 2007 16:52:55 +0800</pubDate>
        <link>http://muscle-liu.javaeye.com/blog/129113</link>
        <guid>http://muscle-liu.javaeye.com/blog/129113</guid>
      </item>
  </channel>
</rss>