﻿<?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-liuyz2006-文章分类-java</title><link>http://www.blogjava.net/liuyz2006/category/50541.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 24 Mar 2016 17:45:26 GMT</lastBuildDate><pubDate>Thu, 24 Mar 2016 17:45:26 GMT</pubDate><ttl>60</ttl><item><title>java 父子类方法多态调用</title><link>http://www.blogjava.net/liuyz2006/articles/429800.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 24 Mar 2016 10:17:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/429800.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/429800.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/429800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/429800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/429800.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/liuyz2006/articles/429800.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/429800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2016-03-24 18:17 <a href="http://www.blogjava.net/liuyz2006/articles/429800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈Java中父类与子类的加载顺序详解（转）</title><link>http://www.blogjava.net/liuyz2006/articles/429798.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 24 Mar 2016 09:37:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/429798.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/429798.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/429798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/429798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/429798.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/liuyz2006/articles/429798.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/429798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2016-03-24 17:37 <a href="http://www.blogjava.net/liuyz2006/articles/429798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解析 Java 类和对象的初始化过程(转）</title><link>http://www.blogjava.net/liuyz2006/articles/429797.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 24 Mar 2016 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/429797.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/429797.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/429797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/429797.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/429797.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;只有注册用户登录后才能阅读该文。<a href='http://www.blogjava.net/liuyz2006/articles/429797.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/429797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2016-03-24 17:27 <a href="http://www.blogjava.net/liuyz2006/articles/429797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javap的基本用法(转）</title><link>http://www.blogjava.net/liuyz2006/articles/429702.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 17 Mar 2016 09:22:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/429702.html</guid><description><![CDATA[
 
<div id="article_details" class="details"><div class="article_title"><h1><span style="font-size: 12pt;"><u>&nbsp;转自</u></span><a href="http://blog.csdn.net/hantiannan/article/category/589614"><span style="font-size: 12pt;">http://blog.csdn.net/hantiannan/article/category/589614</span></a></h1></div><div id="article_content" class="article_content"><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);">是JDK自带的反汇编器，可以查看java编译器为我们生成的字节码。通过它，我们可以对照源代码和字节码，从而了解很多编译器内部的工作。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">语法：</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　</span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> [ 命令选项 ] class. . .</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　</span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> 命令用于解析类文件。其输出取决于所用的选项。若没有使用选项，</span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);">将输出传递给它的类的 public 域及方法。</span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> 将其输出到标准输出设备上。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">命令选项</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-help 输出 </span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> 的帮助信息。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-l 输出行及局部变量表。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-b 确保与 JDK 1.1 </span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> 的向后兼容性。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-public 只显示 public 类及成员。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-protected 只显示 protected 和 public 类及成员。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-package 只显示包、protected 和 public 类及成员。这是缺省设置。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-private 显示所有类和成员。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-J[flag] 直接将 flag 传给运行时系统。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-s 输出内部类型签名。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-c 输出类中各方法的未解析的代码，即构成 </span><span style="background-color: rgb(255, 255, 255);" class="channel_keylink">Java</span><span style="background-color: rgb(255, 255, 255);"> 字节码的指令。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-verbose 输出堆栈大小、各方法的 locals 及 args 数,以及class文件的编译版本</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);">　　-classpath[路径] 指定 </span><span style="color: black; background-color: rgb(255, 255, 255);">javap</span><span style="background-color: rgb(255, 255, 255);"> 用来查找类的路径。如果设置了该选项，则它将覆盖缺省值或 CLASSPATH 环境变量。目录用冒号分隔。</span><br style="background-color: rgb(255, 255, 255);" /><span style="background-color: rgb(255, 255, 255);"> 　 -bootclasspath[路径] 指定加载自举类所用的路径。缺省情况下，自举类是实现核心</span><span style="background-color: rgb(255, 255, 255);" class="channel_keylink">Java</span><span style="background-color: rgb(255, 255, 255);"> 平台的类，位于 jrelib</span>下面。<br style="background-color: rgb(255, 255, 255);" /><p><span style="background-color: rgb(255, 255, 255);">　　-extdirs[dirs] 覆盖搜索安装方式扩展的位置。扩展的缺省位置是 jrelibext。</span></p><p><br /></p><p>英文说明：</p><p>C:\&gt;javap -help<br />Usage: javap &lt;options&gt; &lt;classes&gt;...<br /><br />where options include:<br />&nbsp;&nbsp; -c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Disassemble the code<br />&nbsp;&nbsp; -classpath &lt;pathlist&gt;&nbsp;&nbsp;&nbsp;&nbsp; Specify where to find user class files<br />&nbsp;&nbsp; -extdirs &lt;dirs&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Override location of installed extensions<br />&nbsp;&nbsp; -help&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print this usage message<br />&nbsp;&nbsp; -J&lt;flag&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pass &lt;flag&gt; directly to the runtime system<br />&nbsp;&nbsp; -l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print line number and local variable tables<br />&nbsp;&nbsp; -public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Show only public classes and members<br />&nbsp;&nbsp; -protected&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Show protected/public classes and members<br />&nbsp;&nbsp; -package&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Show package/protected/public classes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and members (default)<br />&nbsp;&nbsp; -private&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Show all classes and members<br />&nbsp;&nbsp; -s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print internal type signatures<br />&nbsp;&nbsp; -bootclasspath &lt;pathlist&gt; Override location of class files loaded<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by the bootstrap class loader<br />&nbsp;&nbsp; -verbose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print stack size, number of locals and args for methods<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If verifying, print reasons for failure<br /><span style="background-color: rgb(255, 255, 255);"></span></p><p><br /></p><p>示例：</p><p>下面也经典的StringBuilder代替String做字符串的例子。</p><p><div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="#">view plain</a><span class="tracking-ad" data-mod="popu_168"> <a class="CopyToClipboard" title="copy" href="#">copy</a></span><span class=" target=" data-mod="popu_169"  _blank?tracking-ad?=""> <a class="PrintSource" title="print" href="#">print</a></span><a class=" target=" title="?" href="#"  _blank?About?="">?</a></div></div><ol class="dp-j"><li class="alt"><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> JAVAPTest {&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp; <span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">void</span><span> main(String[] args) {&nbsp; </span></span></li><li class="alt"><span>&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp; <span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String contactWithStringNoLoopNoPara() {&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = <span class="string">"This is "</span><span> + </span><span class="string">" my "</span><span> + </span><span class="string">"first JAVAP test code."</span><span>;&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">return</span><span> s;&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp; <span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String contactWithStringNoLoop(</span><span class="keyword">int</span><span> count) {&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = <span class="string">"This is "</span><span> + </span><span class="string">" my "</span><span> + count + </span><span class="string">"th JAVAP test code."</span><span>;&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">return</span><span> s;&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp; <span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String contactWithStringLoop(</span><span class="keyword">int</span><span> count) {&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = <span class="string">""</span><span>;&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> i = </span><span class="number">0</span><span>; i &lt; count; i++) {&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s += i;&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">return</span><span> s;&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp; <span class="keyword">public</span><span> </span><span class="keyword">static</span><span> String contactWithStringBufferLoop(</span><span class="keyword">int</span><span> count) {&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer sb = <span class="keyword">new</span><span> StringBuffer();&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> i = </span><span class="number">0</span><span>; i &lt; count; i++) {&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append(i);&nbsp; </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">return</span><span> sb.toString();&nbsp; </span></span></li><li><span>&nbsp;&nbsp;&nbsp; }&nbsp; </span></li><li class="alt"><span>}&nbsp; </span></li></ol></div><pre style="display: none;" class="java" name="code">public class JAVAPTest {
	public static void main(String[] args) {

	}

	public static String contactWithStringNoLoopNoPara() {
		String s = "This is " + " my " + "first JAVAP test code.";
		return s;
	}
	
	public static String contactWithStringNoLoop(int count) {
		String s = "This is " + " my " + count + "th JAVAP test code.";
		return s;
	}
	
	public static String contactWithStringLoop(int count) {
		String s = "";
		for (int i = 0; i &lt; count; i++) {
			s += i;
		}
		return s;
	}

	public static String contactWithStringBufferLoop(int count) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i &lt; count; i++) {
			sb.append(i);
		}
		return sb.toString();
	}
}
</pre><br /><br /><p>&nbsp;</p><p><br />先编译：javac JAVAPTest.java</p><p>执行反编译：javap -c JAVAPTest&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意这个地方不需要class后缀。</p><p>结果如下：</p><p><div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="#">view plain</a><span class="tracking-ad" data-mod="popu_168"> <a class="CopyToClipboard" title="copy" href="#">copy</a></span><span class=" target=" data-mod="popu_169"  _blank?tracking-ad?=""> <a class="PrintSource" title="print" href="#">print</a></span><a class=" target=" title="?" href="#"  _blank?About?="">?</a></div></div><ol class="dp-j"><li class="alt"><span>Compiled from </span><span class="string">"JAVAPTest.java"</span><span>&nbsp; </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> JAVAPTest </span><span class="keyword">extends</span><span> java.lang.Object{&nbsp; </span></li><li class="alt"><span class="keyword">public</span><span> JAVAPTest();&nbsp; </span></li><li><span>&nbsp; Code:&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; aload_0&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">1</span><span>:&nbsp;&nbsp; invokespecial&nbsp;&nbsp; #</span><span class="number">1</span><span>; </span><span class="comment">//Method java/lang/Object."&lt;init&gt;":()V</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">4</span><span>:&nbsp;&nbsp; </span><span class="keyword">return</span><span>&nbsp; </span></span></li><li><span>&nbsp; </span></li><li class="alt"><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">void</span><span> main(java.lang.String[]);&nbsp; </span></li><li><span>&nbsp; Code:&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; </span><span class="keyword">return</span><span>&nbsp; </span></span></li><li><span>&nbsp; </span></li><li class="alt"><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> java.lang.String contactWithStringNoLoopNoPara();&nbsp; </span></li><li><span>&nbsp; Code:&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">2</span><span>; </span><span class="comment">//String This is&nbsp; my first JAVAP test code.</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">2</span><span>:&nbsp;&nbsp; astore_0&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">3</span><span>:&nbsp;&nbsp; aload_0&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">4</span><span>:&nbsp;&nbsp; areturn&nbsp; </span></span></li><li class="alt"><span>&nbsp; </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> java.lang.String contactWithStringNoLoop(</span><span class="keyword">int</span><span>);&nbsp; </span></li><li class="alt"><span>&nbsp; Code:&nbsp; </span></li><li><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; </span><span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">3</span><span>; </span><span class="comment">//class java/lang/StringBuilder</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">3</span><span>:&nbsp;&nbsp; dup&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">4</span><span>:&nbsp;&nbsp; invokespecial&nbsp;&nbsp; #</span><span class="number">4</span><span>; </span><span class="comment">//Method java/lang/StringBuilder."&lt;init&gt;":()V</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">7</span><span>:&nbsp;&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">5</span><span>; </span><span class="comment">//String This is&nbsp; my</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">9</span><span>:&nbsp;&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">6</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">12</span><span>:&nbsp; iload_0&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">13</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">7</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">16</span><span>:&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">8</span><span>; </span><span class="comment">//String th JAVAP test code.</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">18</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">6</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">21</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">9</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">24</span><span>:&nbsp; astore_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">25</span><span>:&nbsp; aload_1&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">26</span><span>:&nbsp; areturn&nbsp; </span></span></li><li class="alt"><span>&nbsp; </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> java.lang.String contactWithStringLoop(</span><span class="keyword">int</span><span>);&nbsp; </span></li><li class="alt"><span>&nbsp; Code:&nbsp; </span></li><li><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">10</span><span>; </span><span class="comment">//String</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">2</span><span>:&nbsp;&nbsp; astore_1&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">3</span><span>:&nbsp;&nbsp; iconst_0&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">4</span><span>:&nbsp;&nbsp; istore_2&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">5</span><span>:&nbsp;&nbsp; iload_2&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">6</span><span>:&nbsp;&nbsp; iload_0&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">7</span><span>:&nbsp;&nbsp; if_icmpge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="number">35</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">10</span><span>:&nbsp; </span><span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">3</span><span>; </span><span class="comment">//class java/lang/StringBuilder</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">13</span><span>:&nbsp; dup&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">14</span><span>:&nbsp; invokespecial&nbsp;&nbsp; #</span><span class="number">4</span><span>; </span><span class="comment">//Method java/lang/StringBuilder."&lt;init&gt;":()V</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">17</span><span>:&nbsp; aload_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">18</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">6</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">21</span><span>:&nbsp; iload_2&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">22</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">7</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">25</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">9</span><span>; </span><span class="comment">//Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">28</span><span>:&nbsp; astore_1&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">29</span><span>:&nbsp; iinc&nbsp;&nbsp;&nbsp; </span><span class="number">2</span><span>, </span><span class="number">1</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">32</span><span>:&nbsp; </span><span class="keyword">goto</span><span>&nbsp;&nbsp;&nbsp; </span><span class="number">5</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">35</span><span>:&nbsp; aload_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">36</span><span>:&nbsp; areturn&nbsp; </span></span></li><li><span>&nbsp; </span></li><li class="alt"><span class="keyword">public</span><span> </span><span class="keyword">static</span><span> java.lang.String contactWithStringBufferLoop(</span><span class="keyword">int</span><span>);&nbsp; </span></li><li><span>&nbsp; Code:&nbsp; </span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">0</span><span>:&nbsp;&nbsp; </span><span class="keyword">new</span><span>&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">11</span><span>; </span><span class="comment">//class java/lang/StringBuffer</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">3</span><span>:&nbsp;&nbsp; dup&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">4</span><span>:&nbsp;&nbsp; invokespecial&nbsp;&nbsp; #</span><span class="number">12</span><span>; </span><span class="comment">//Method java/lang/StringBuffer."&lt;init&gt;":()V</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">7</span><span>:&nbsp;&nbsp; astore_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">8</span><span>:&nbsp;&nbsp; iconst_0&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">9</span><span>:&nbsp;&nbsp; istore_2&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">10</span><span>:&nbsp; iload_2&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">11</span><span>:&nbsp; iload_0&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">12</span><span>:&nbsp; if_icmpge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="number">27</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">15</span><span>:&nbsp; aload_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">16</span><span>:&nbsp; iload_2&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">17</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">13</span><span>; </span><span class="comment">//Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">20</span><span>:&nbsp; pop&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">21</span><span>:&nbsp; iinc&nbsp;&nbsp;&nbsp; </span><span class="number">2</span><span>, </span><span class="number">1</span><span>&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">24</span><span>:&nbsp; </span><span class="keyword">goto</span><span>&nbsp;&nbsp;&nbsp; </span><span class="number">10</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">27</span><span>:&nbsp; aload_1&nbsp; </span></span></li><li class="alt"><span>&nbsp;&nbsp; <span class="number">28</span><span>:&nbsp; invokevirtual&nbsp;&nbsp; #</span><span class="number">14</span><span>; </span><span class="comment">//Method java/lang/StringBuffer.toString:()Ljava/lang/String;</span><span>&nbsp; </span></span></li><li><span>&nbsp;&nbsp; <span class="number">31</span><span>:&nbsp; areturn&nbsp; </span></span></li><li class="alt"><span>&nbsp; </span></li><li><span>}&nbsp; </span></li></ol></div><pre style="display: none;" class="java" name="code">Compiled from "JAVAPTest.java"
public class JAVAPTest extends java.lang.Object{
public JAVAPTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."&lt;init&gt;":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   return

public static java.lang.String contactWithStringNoLoopNoPara();
  Code:
   0:   ldc     #2; //String This is  my first JAVAP test code.
   2:   astore_0
   3:   aload_0
   4:   areturn

public static java.lang.String contactWithStringNoLoop(int);
  Code:
   0:   new     #3; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #4; //Method java/lang/StringBuilder."&lt;init&gt;":()V
   7:   ldc     #5; //String This is  my
   9:   invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   12:  iload_0
   13:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   16:  ldc     #8; //String th JAVAP test code.
   18:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_1
   25:  aload_1
   26:  areturn

public static java.lang.String contactWithStringLoop(int);
  Code:
   0:   ldc     #10; //String
   2:   astore_1
   3:   iconst_0
   4:   istore_2
   5:   iload_2
   6:   iload_0
   7:   if_icmpge       35
   10:  new     #3; //class java/lang/StringBuilder
   13:  dup
   14:  invokespecial   #4; //Method java/lang/StringBuilder."&lt;init&gt;":()V
   17:  aload_1
   18:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  iload_2
   22:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   25:  invokevirtual   #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   28:  astore_1
   29:  iinc    2, 1
   32:  goto    5
   35:  aload_1
   36:  areturn

public static java.lang.String contactWithStringBufferLoop(int);
  Code:
   0:   new     #11; //class java/lang/StringBuffer
   3:   dup
   4:   invokespecial   #12; //Method java/lang/StringBuffer."&lt;init&gt;":()V
   7:   astore_1
   8:   iconst_0
   9:   istore_2
   10:  iload_2
   11:  iload_0
   12:  if_icmpge       27
   15:  aload_1
   16:  iload_2
   17:  invokevirtual   #13; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
   20:  pop
   21:  iinc    2, 1
   24:  goto    10
   27:  aload_1
   28:  invokevirtual   #14; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
   31:  areturn

}</pre><br />有这个结果我们可以知道。<p>&nbsp;</p><p>1。contactWithStringNoLoopNoPara方法中，代码里面是字符串拼接，貌似需要是用StringBuilder替换的好。其实在看了上面的反编译结果后，已经自动组合成一个固定字符串了。因此完全没有必要使用StringBuilder。</p><p><div style="width: 99%; height: 47px;" class="dp-highlighter bg_java"><div class="bar"><div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="#">view plain</a><span class="tracking-ad" data-mod="popu_168"> <a class="CopyToClipboard" title="copy" href="#">copy</a></span><span class=" target=" data-mod="popu_169"  _blank?tracking-ad?=""> <a class="PrintSource" title="print" href="#">print</a></span><a class=" target=" title="?" href="#"  _blank?About?="">?</a></div></div><ol class="dp-j"><li class="alt"><span class="number">0</span><span>:&nbsp;&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #</span><span class="number">2</span><span>; </span><span class="comment">//String This is&nbsp; my first JAVAP test code.</span><span>&nbsp; </span></li></ol></div><pre style="display: none;" class="java" name="code"> 0:   ldc     #2; //String This is  my first JAVAP test code.</pre><p>&nbsp;</p><p>2。contactWithStringNoLoop方法中，因为使用到了变量，貌似需要是用StringBuilder替换的好。其实在看了上面的反编译结果后，已经自动使用了StringBuilder。所以代码也没有必要使用StringBuilder。</p><p><br /></p><p>3. contactWithStringLoop方法中，是循环拼接字符串，貌似需要是用StringBuilder替换的好。看了反编译后，每个循环里面都各自生成了一个StringBuilder，并将StringBuilder.toString()防赋值给我们的Sring变量。而我们希望的是只生成一个StringBuilder对象。因此改为StringBuilder的好。循环的时候改为contactWithBufferLoop的方法最好。</p><p><br /></p><p>4.contactWithBufferLoop方法中，是循环拼接字符串。也是我们预想的步骤在执行。<br /></p></div></div> 
<img src ="http://www.blogjava.net/liuyz2006/aggbug/429702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2016-03-17 17:22 <a href="http://www.blogjava.net/liuyz2006/articles/429702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]java基础：父类与子类之间变量和方法的调用</title><link>http://www.blogjava.net/liuyz2006/articles/429596.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 10 Mar 2016 05:26:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/429596.html</guid><description><![CDATA[
 
[转]java基础：父类与子类之间变量和方法的调用<br /><br />1)父类构造函数<br />java中当调用某个类的构造方法的时候，系统总会调用父类的非静态初始化块进行初始化，这个调用是隐式的，而且父类的静态初始化代码<br />块总是会被执行，接着调用父类的一个或者多个构造器执行初始化，这个调用也可以通过super进行显式调用。<br />例如：<br />父类代码如下：<br />public class Creature {//父类<br />{//非静态代码块<br />System.out.println("creature的非静态代码块正在执行");<br />}<br /><br />public Creature(){<br />System.out.println("creature的构造函数正在执行");<br />}<br />}<br />子类代码如下：<br />public class Animal extends Creature {<br />{<br />System.out.println("animal的初始化代码块正在执行");<br />}<br />public Animal(){<br />System.out.println("animal的构造方法正在执行");<br />}<br /><br />public static void main(String[] args){<br />Animal a = new Animal()&nbsp; ;<br />}<br />}<br />则运行程序后的结果为：<br />creature的非静态代码块正在执行<br />creature的构造函数正在执行<br />animal的初始化代码块正在执行<br />animal的构造方法正在执行<br />从结果中可以看出：调用某个类的构造方法的时候总是会先执行父类的非静态代码块，然后执行父类的构造方法，最后才是执行当前类的<br />非静态代码块和构造方法。执行过程中有先后顺序。<br />若果想要显式调用父类的构造方法则可以使用super()，来调用，但是super关键字和this关键字都必须放在构造放的第一行，而且只能使<br />用一个，为什么要放在第一行呢？因为如果不放在第一行则先调用子类的初始化代码，再调用父类的初始化代码，则父类中的初始化后的值<br />会覆盖子类中的初始化的值。<br />注：super用于显式调用父类的构造器，this可以显式调用本类中的重载的构造器。<br /><br /><br />2）访问子类对象的实例变量<br />子类的方法可以访问父类中的实例变量，这是因为子类继承父类就会获得父类中的成员变量和方法，但是父类方法不能访问子类的实例变量<br />，因为父类根本无法知道它将被哪个类继承，它的子类将会增加怎么样的成员变量。但是，在极端的情况下，父类也可以访问子类中的变量。<br />例如：<br />父类代码如下：<br />public class Base {//父类<br />private int i = 2 ;<br />public Base(){<br />this.display() ;<br />}<br />public void display(){<br />System.out.println(i);<br />}<br />} <br />子类中代码如下：<br />public class Derived extends Base {<br />private int i = 22 ;<br />public Derived(){<br />i = 222 ;<br />}<br />public void display(){<br />System.out.println(i);<br />}<br />}<br />测试用例如下：<br />public class Test {<br />public static void main(String[] args) {<br />new Derived() ;<br />}<br />}<br />程序的执行结果为：<br />0<br />也许你会感到奇怪，为什么不是2？22？222？怎么会是0呢，下面我们看一下程序的执行过程。当我们调用new Derived() ;创建Derived<br />实例的时候，系统会为Derived对象分配内存空间，Derived会有两个i实例变量，会分配两个空间来保存i的值。分配完空间以后i的值为0<br />，如果有引用类型则引用类型的值为null。接下来程序在执行Derived的构造器之前会执行Base的构造器，表面上看Base的构造器中只有<br />一行代码，但是在父类中定义i的时候执行的初始值2，因此经过编译之后，该构造方法中应该包含如下两行代码：<br />i =2 ;<br />this.display() ;<br />程序先将Base中的i赋值为2，然后执行display方法。此处有一个关键字this，this到底代表谁呢？表面上看this代表的是Base的当前实例，<br />但是实际上代码是放在Derived的构造器中的，所以this最终代表的是Derived的当前实例（编译类型是Base而实际引用一个Derived对象），<br />所以如果在父类的构造方法中直接输出System.out.println(this.i) ;则输出的结果为2。但是调用this.display()方法，此时调用的是<br />子类中重写的display方法，输出的变量i也是子类中的i，但是此时子类中的变量i还没有赋值，所以输出结果为0。<br />为了详细的看清楚this变量到底代表什么实例，我们将Base的构造方法修改如下：<br />public Base(){<br />System.out.println(this.i);<br />System.out.println(this.getClass());<br />this.display() ;<br />}<br />再次运行程序，结果为：<br />2<br />class edu.qichao.chapter2.Derived<br />0<br />可以看到this代表的是Derived的实例，但是编译的时候类型为Base，所以输出this.i的值为2。<br /><br /><br />3）调用被子类重写的方法<br />默认情况下，子类可以调用父类的方法，但是父类不能调用子类的方法，因为父类不知道它将被哪个子类继承，也不知道子类将增加怎么<br />样的方法。<br />例如：<br />父类Animal的代码如下：<br />public class Animal {<br />private String desc ;<br /><br />public Animal(){<br />this.desc = getDesc() ;<br />}<br /><br />public String getDesc(){<br />return "Animal" ;<br />}<br /><br />public String toString(){<br />return desc ;<br />}<br />}<br />子类Wolf的代码如下：<br />public class Wolf extends Animal {<br />private String name ;<br />private double weight ;<br />public Wolf(String name , double weight){<br />this.name = name ;<br />this.weight = weight ;<br />}<br />public String getDesc(){<br />return "Wolf[name=" + name + ",weight=" + weight + "]" ;<br />}<br /><br />public static void main(String[] args){<br />System.out.println(new Wolf("灰太狼" , 3));<br />}<br />}<br />程序的运行结果为：<br />Wolf[name=null,weight=0.0]<br />现在我们分析一下程序执行的过程。在main方法中通过new Wolf("灰太狼" , 3)；来创建一个Wolf的实例，子类会隐式调用父类的构造方<br />法，在父类构造方法中初始化desc变量this.desc = getDesc() ;此处需要注意this变量，虽然这个this放在Animal的构造放中，但是是在<br />Wolf的构造方法中调用父类的构造方法，所以this编译时类型为Animal，运行时类型为Wolf，此处调用的getDesc方法是子类Wolf的方法，<br />但是子类中的name和weight变量都没有初始化，默认为null和0.0.所以程序的最终结果为：Wolf[name=null,weight=0.0]<br /><br /><br />4）继承成员变量和成员方法的区别<br />java中队成员变量的继承和成员方法的继承是不同的。<br />例如：<br />父类代码如下：<br />public class Base {<br />int count = 2 ;<br />public void display(){<br />System.out.println(this.count);<br />}<br />}<br />子类代码如下：<br />public class Derived extends Base {<br />int count = 20 ;<br />@Override<br />public void display(){<br />System.out.println(this.count);<br />}<br />}<br />测试用例如下：<br />public class Test {<br />public static void main(String[] args) {<br />Base b = new Base() ;<br />System.out.println(b.count);<br />b.display() ;<br />System.out.println("-----------------");<br />Derived d = new Derived() ;<br />System.out.println(d.count);<br />d.display() ;<br />System.out.println("-----------------");<br />Base bd = new Derived() ;<br />System.out.println(bd.count);<br />bd.display() ;<br />System.out.println("-----------------");<br />Base d2b = d ;<br />System.out.println(d2b.count);<br />}<br />}<br />程序运行结果为：<br />2<br />2<br />-----------------<br />20<br />20<br />-----------------<br />2<br />20<br />-----------------<br />2<br />在上面的程序中，不管是d变量、还是bd变量、还是都d2b变量。只要他们指向一个Derived对象，则不管他们声明时用了什么类型，当通过<br />这些变量调用方法时，方法的行为总是表现出他们的实际类型的行为，但是如果通过这些变量来访问他们所指向对象的实例变量的时候，<br />这些实例变量的值总是表现出声明这些变量所用类型的行为。由此可见，java处理成员变量和成员方法的继承时是有区别的。<img src ="http://www.blogjava.net/liuyz2006/aggbug/429596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2016-03-10 13:26 <a href="http://www.blogjava.net/liuyz2006/articles/429596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java指令详解（转）</title><link>http://www.blogjava.net/liuyz2006/articles/418243.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Wed, 24 Sep 2014 10:10:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/418243.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/418243.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/418243.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/418243.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/418243.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: class文件格式如下： Java代码 &nbsp;相信学java的人都对new&nbsp;&nbsp;Object();创建对象都很熟悉，但想要真正了解原理就没那么容易！以以下例子为例，解释class代码及执行过程，如有错误，还望各位高手多多指教！ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;class&nbsp;Dog&nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/liuyz2006/articles/418243.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/418243.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-09-24 18:10 <a href="http://www.blogjava.net/liuyz2006/articles/418243.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《深入理解Java虚拟机》笔记</title><link>http://www.blogjava.net/liuyz2006/articles/416473.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 02 Aug 2014 10:06:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/416473.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;在C里面我们想执行一段自己编写的机器指令的方法大概如下：typedef&nbsp;void(*FUNC)(int);char* str = "your code";FUNC f = (FUNC)str;(*f)(0);　　也就是说，我们完全可以做一个工具，从一个文件中读入指令，然后将这些指令运行起来。上面代码中&#8220;编...&nbsp;&nbsp;<a href='http://www.blogjava.net/liuyz2006/articles/416473.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/416473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-08-02 18:06 <a href="http://www.blogjava.net/liuyz2006/articles/416473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java堆栈方法区简单分析（转）</title><link>http://www.blogjava.net/liuyz2006/articles/410339.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Wed, 26 Feb 2014 09:50:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/410339.html</guid><description><![CDATA[<font face="Verdana">http://www.360doc.com/content/11/0504/12/3903749_114271703.shtml</font><img src ="http://www.blogjava.net/liuyz2006/aggbug/410339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-02-26 17:50 <a href="http://www.blogjava.net/liuyz2006/articles/410339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解JVM—字节码执行引擎(转）</title><link>http://www.blogjava.net/liuyz2006/articles/410168.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Fri, 21 Feb 2014 10:06:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/410168.html</guid><description><![CDATA[<a href="http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/">http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/410168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-02-21 18:06 <a href="http://www.blogjava.net/liuyz2006/articles/410168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java语言基础</title><link>http://www.blogjava.net/liuyz2006/articles/409487.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 02 Feb 2014 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/409487.html</guid><description><![CDATA[<a href="http://blog.csdn.net/linzhengqun/article/category/800320">http://blog.csdn.net/linzhengqun/article/category/800320<br /></a><br />java语音基础知识：<br />流类(1)<br />多线程<br />RTTI<br />异常机制<br />抽象类和接口<br />对象的初始化<br />基本数组类型<br />内部类<br />泛型<br />final和static<img src ="http://www.blogjava.net/liuyz2006/aggbug/409487.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-02-02 17:13 <a href="http://www.blogjava.net/liuyz2006/articles/409487.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java语言基础：对象的初始化 (转）</title><link>http://www.blogjava.net/liuyz2006/articles/409484.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 02 Feb 2014 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/409484.html</guid><description><![CDATA[<div id="body">
<div id="main">
<div class="main">
<div id="article_details" class="details">
<div class="article_title"><span class="ico ico_type_Original"></span>
<h3><span class="link_title"><a href="http://blog.csdn.net/linzhengqun/article/details/6279193">Java语言基础：对象的初始化 </a></span></h3></div>
<div class="tag2box"><a href="http://www.csdn.net/tag/java" target="_blank">java</a><a href="http://www.csdn.net/tag/%e8%af%ad%e8%a8%80" target="_blank">语言</a><a href="http://www.csdn.net/tag/class" target="_blank">class</a><a href="http://www.csdn.net/tag/string" target="_blank">string</a><a href="http://www.csdn.net/tag/c" target="_blank">c</a><a href="http://www.csdn.net/tag/%e5%ad%98%e5%82%a8" target="_blank">存储</a></div>
<div id="article_content" class="article_content">
<p>1. &nbsp;如果基类存在默认构造函数，则在子类构造之前，会先调用基类的默认构造函数：</p>
<p style="padding-left: 30px"><span style="font-family: monospace; font-size: x-small"><span style="white-space: pre-wrap"></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">view plain</font></u></a><a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">copy</font></u></a><a class="PrintSource" title="print" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">print</font></u></a><a class="About" title="?" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">class</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;A()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"A&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">class</span><span>&nbsp;B&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;B()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;会在这里先调用A的默认构造函数 </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"B&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">class</span><span>&nbsp;C&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;C(</span><span class="keyword">int</span><span>&nbsp;i)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;会在这里先调用A的默认构造函数 </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"C&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Main&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;c&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;C(</span><span class="number">10</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="comment">//&nbsp;输出为： </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>A&nbsp;create&nbsp;&nbsp;</span></li><li><span>B&nbsp;create&nbsp;&nbsp;</span></li><li class="alt"><span>A&nbsp;create&nbsp;&nbsp;</span></li><li><span>C&nbsp;create&nbsp;&nbsp;</span></li></ol></div><textarea style="display: none" class="java" rows="15" cols="50" name="code">class A {
    A() {
        System.out.println("A create");
    }
}
 
class B extends A {
    B() {
        // 会在这里先调用A的默认构造函数
        System.out.println("B create");
    }
}
 
class C extends A {
    C(int i) {
        // 会在这里先调用A的默认构造函数
        System.out.println("C create");
    }
}
 
public class Main {            
    public static void main(String[] args) {
        B b = new B();
        C c = new C(10);
    }
}
 
// 输出为：
A create
B create
A create
C create
</textarea> </span></span>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>2. &nbsp;如果基类只有带参数的构造函数，子类必须在自己的构造函数中通过super(...)显式调用该基类构造函数：</p>
<p>&nbsp;</p>
<p style="padding-left: 30px"><span style="font-family: monospace; font-size: x-small"><span style="white-space: pre-wrap"></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">view plain</font></u></a><a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">copy</font></u></a><a class="PrintSource" title="print" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">print</font></u></a><a class="About" title="?" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">class</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;A(</span><span class="keyword">int</span><span>&nbsp;i)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"A&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">class</span><span>&nbsp;B&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;B()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;必须在这里显式调用父类的非默认构造函数，否则编译不通过 </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;注意这调用只能放在最前面，否则编译不通过 </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>(</span><span class="number">20</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"B&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">class</span><span>&nbsp;C&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;C(</span><span class="keyword">int</span><span>&nbsp;i)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;必须在这里显式调用父类的非默认构造函数，否则编译不通过 </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;注意这调用只能放在最前面，否则编译不通过 </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>(</span><span class="number">30</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"C&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Main&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;c&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;C(</span><span class="number">10</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="comment">//&nbsp;输出为： </span><span>&nbsp;&nbsp;</span></span></li><li><span>A&nbsp;create&nbsp;&nbsp;</span></li><li class="alt"><span>B&nbsp;create&nbsp;&nbsp;</span></li><li><span>A&nbsp;create&nbsp;&nbsp;</span></li><li class="alt"><span>C&nbsp;create&nbsp;&nbsp;</span></li></ol></div><textarea style="display: none" class="java" rows="15" cols="50" name="code">class A {
    A(int i) {
        System.out.println("A create");
    }
}
 
class B extends A {
    B() {
        // 必须在这里显式调用父类的非默认构造函数，否则编译不通过
        // 注意这调用只能放在最前面，否则编译不通过
        super(20);
        System.out.println("B create");
    }
}
 
class C extends A {
    C(int i) {
        // 必须在这里显式调用父类的非默认构造函数，否则编译不通过
        // 注意这调用只能放在最前面，否则编译不通过
        super(30);
        System.out.println("C create");
    }
}
 
public class Main {            
    public static void main(String[] args) {
        B b = new B();
        C c = new C(10);
    }
}
// 输出为：
A create
B create
A create
C create
</textarea> </span></span>
<p>&nbsp;</p>
<p><span style="font-family: monospace">3. &nbsp;以上只讲了最简单的构造函数调用顺序，其实一个对象的真正的初始化过程应该是：</span></p>
<ol><li><span style="font-family: monospace">将对象的存储空间初始化为二进制的0.</span></li><li><span style="font-family: monospace">先递归到最上层的基类去，将最上层的基类作为当前类。</span></li><li><span style="font-family: monospace">对于当前类：</span> 
<ol><li><span style="font-family: monospace">按声明顺序调用成员变量的初始设置代码。</span></li><li><span style="font-family: monospace">调用构造函数。</span></li></ol></li><li><span style="font-family: monospace">接着将下一层继承类作为当前类，继续步骤3</span> 
<ol></ol></li></ol>
<p>&nbsp;</p>
<p style="padding-left: 30px">先看下面的代码：</p>
<p style="padding-left: 30px"></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">view plain</font></u></a><a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">copy</font></u></a><a class="PrintSource" title="print" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">print</font></u></a><a class="About" title="?" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">class</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;A()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"A&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">class</span><span>&nbsp;D&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;D()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"D&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">class</span><span>&nbsp;B&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;D&nbsp;d&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;D();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;B()&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"B&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">class</span><span>&nbsp;C&nbsp;</span><span class="keyword">extends</span><span>&nbsp;B&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;C(</span><span class="keyword">int</span><span>&nbsp;i)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"C&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Main&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;c&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;C(</span><span class="number">10</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><textarea style="display: none" class="java" rows="15" cols="50" name="code">class A {
    A() {
        System.out.println("A create");
    }
}
 
class D {
    D() {
        System.out.println("D create");
    }
}
 
class B extends A {
    private D d = new D();
    B() {
        System.out.println("B create");
    }
}
 
class C extends B {
    C(int i) {
        System.out.println("C create");
    }
}
 
public class Main {            
    public static void main(String[] args) {
        C c = new C(10);
    }
}
</textarea>&nbsp; 
<p>&nbsp;</p>
<p style="padding-left: 30px">初始化过程大概是这样的：</p>
<ol><li>&nbsp;先从C递归到B，再从B递归到A。</li><li>A没有成员变量，所以A的构造函数被调用。</li><li>接到回到B，B有一个D类的成员有初始化，因此D的构造函数被调用。</li><li>接着B的构造函数被调用。</li><li>最后回到C，C的构造函数被调用。</li></ol>
<ol></ol>
<p style="padding-left: 30px">所以输出应该是：</p>
<p style="padding-left: 30px">A create</p>
<p style="padding-left: 30px">D create</p>
<p style="padding-left: 30px">B create</p>
<p style="padding-left: 30px">C create</p>
<p style="padding-left: 30px">&nbsp;</p>
<p>4. &nbsp;必须小心在构造函数中调用虚函数(在JAVA里普通函数都是虚的)的隐患，特别是在基类的构造函数，因为此时继承类的成员可能还没有初始完毕：</p>
<p style="padding-left: 30px"></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a class="ViewSource" title="view plain" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">view plain</font></u></a><a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">copy</font></u></a><a class="PrintSource" title="print" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">print</font></u></a><a class="About" title="?" href="http://blog.csdn.net/linzhengqun/article/details/6279193#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">class</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;A()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"A&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proc();&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;proc()&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">class</span><span>&nbsp;B&nbsp;</span><span class="keyword">extends</span><span>&nbsp;A&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;i;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;B()&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"B&nbsp;create"</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;=&nbsp;</span><span class="number">10</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;proc(){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(i);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Main&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;B();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li><li><span>输出：&nbsp;&nbsp;</span></li><li class="alt"><span>A&nbsp;create&nbsp;&nbsp;</span></li><li><span></span><span class="number">0</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>B&nbsp;create&nbsp;&nbsp;</span></li></ol></div>&nbsp;<br /><textarea style="display: none" class="java" rows="15" cols="50" name="code">class A {
    A() {
        System.out.println("A create");
        proc();
    }
    public void proc() {
    }
}
 
class B extends A {
    private int i;
    B() {
        System.out.println("B create");
        i = 10;
    }
    public void proc(){
        System.out.println(i);
    }
}
 
public class Main {            
    public static void main(String[] args) {
        B b = new B();
    }
}
输出：
A create
0
B create
</textarea>A的构造函数调用了proc，此时B的构造函数还没有被调用，因此i还没有被赋为10，最终输出结果是0。 
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>5. &nbsp;由于Java对象都是通过垃圾回收机制清理对象，因此Java的类没有析构函数，遇到需要清理类中资源的问题时，可以自己声明一个函数，如Dispose，在适当的时候调用之。</p></div></div></div></div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/409484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-02-02 15:55 <a href="http://www.blogjava.net/liuyz2006/articles/409484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中覆盖和隐藏的问题(转）</title><link>http://www.blogjava.net/liuyz2006/articles/409423.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Wed, 29 Jan 2014 01:46:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/409423.html</guid><description><![CDATA[<font face="Verdana">
<div class="articalTitle">
<h2 class="titName SG_txta" id="t_4ac81de30100efxy">java中覆盖和隐藏的问题</h2></div><!-- 正文开始 -->

<div class="articalContent  " id="sina_keyword_ad_area2">
<p>近期复习java时，发觉了自己很多没掌握的知识点，现在每天总结一点点，一点点的积累，一点点的进步。</p>
<p>今天的解决问题&#8212;&#8212;java中覆盖和隐藏的问题（方法和变量）</p>
<p>参考网址：<a href="http://school.cnd8.com/java/jiaocheng/10836.htm">http://school.cnd8.com/java/jiaocheng/10836.htm</a></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://heisetoufa.javaeye.com/blog/227345">http://heisetoufa.javaeye.com/blog/227345</a></p>
<p>&nbsp;<wbr></p>
<p>1.先来总结java中方法的覆盖和隐藏</p>
<p>一个大的原则：静态方法不能被覆盖。实例方法被覆盖，静态方法被隐藏。被覆盖的方法只有覆盖它们的类才能访问它们，而访问被隐藏的方法是提供该方法的全局名。</p>
<p>例子：</p><pre>01: class Super</pre><pre>02: {</pre><pre>03: static String greeting()</pre><pre>04: {</pre><pre>05: return "Goodnight";</pre><pre>06: }</pre><pre>07:</pre><pre>08: String name()</pre><pre>09: {</pre><pre>10: return "Richard";</pre><pre>11: }</pre><pre>12: }</pre><pre>&nbsp;<wbr> </pre><pre>01: class Sub extends Super</pre><pre>02: {</pre><pre>03: static String greeting()</pre><pre>04: {</pre><pre>05: return "Hello";</pre><pre>06: }</pre><pre>07:</pre><pre>08: String name()</pre><pre>09: {</pre><pre>10: return "Dick";</pre><pre>11: }</pre><pre>12: }</pre><pre>&nbsp;<wbr> </pre><pre>01: class Test</pre><pre>02: {</pre><pre>03: public static void main(String[] args)</pre><pre>04: {</pre><pre>05: Super s = new Sub();</pre><pre>06: System.out.println(s.greeting() + ", " + s.name());</pre><pre>07: }</pre><pre>08: }</pre><pre>程序运行结果：Goodnight，Dick</pre><pre>分析：在main函数中，创建了一个子类sub对象实例，通过赋值号我们可以看成其被强制转换成父类super类型。由于greeting是静态方法，它仅仅是被子类sub隐藏，所以通过强制转换成父类super的对象实例s调用时，实际上调用的是父类的greeting方法；而name方法为实例方法，其被子类sub覆盖，所以s.name()是调用的子类name方法。</pre><pre>在继承时需要注意的几点原则：</pre><pre>1）试图用子类的静态方法隐藏父类中同样标识的实例方法不合法，编译器会报错；</pre><pre>2）试图用子类的实例方法覆盖父类中同样标识的静态方法也不合法，编译器会报错；</pre><pre>3）静态方法和最终方法不能被覆盖；</pre><pre>4）实例方法能够被覆盖；</pre><pre>5）抽象方法必须在具体类中被覆盖。</pre><pre>2.再来总结下变量的覆盖和隐藏</pre><pre>原网址的变量分的很详细，不仔细看还被绕的有点糊涂。总结了下，不管是静态变量还是非静态变量，只要是成员变量，它们被覆盖和被隐藏的原则一样。原则：成员变量能够被子类同名的成员变量隐藏，而局部变量和形参不会被隐藏。</pre><pre>例子：</pre><pre>class Base {</pre><pre> int x = 1;</pre><pre> static int y=2;</pre><pre> int z=3;</pre><pre> int method() {</pre><pre> return x;</pre><pre> }</pre><pre>}</pre><pre>&nbsp;<wbr> </pre><pre>class Subclass extends Base {</pre><pre> int x = 4;</pre><pre> int y=5;</pre><pre> static int z=6;</pre><pre> int method() {</pre><pre> return x;</pre><pre> }</pre><pre>}</pre><pre>&nbsp;<wbr> </pre><pre>public class Test {</pre><pre> public static void main(String[] args) {</pre><pre> Subclass s=new Subclass();</pre><pre> System.out.println(s.x + " " + s.y +" "+ s.z);</pre><pre> System.out.println(s.method());</pre><pre> </pre><pre> Base b = (Subclass)s;</pre><pre> System.out.println(b.x + " " + b.y +" "+ b.z);</pre><pre> System.out.println(b.method());</pre><pre> }</pre><pre>}</pre><pre></pre><pre>结果：4 5 6 <br />　　 4 <br />　　 1 2 3 <br />　　 4 <br />分析：在main方法中，开始创建了一个subclass对象实例，对于第一个输出很好理解；后将对象实例s强制转换成父类Base类型，由于父类的成员变量只是被隐藏，所以通过强制转换成父类类型的对象实例调用时，调用的是父类中的变量，而method方法是被子类同名方法所覆盖，所以调用时依然调用的子类method方法。<br />&nbsp;<wbr><br />3.最后变量和方法的隐藏及其覆盖的不同<br />一个类的实例无法通过使用全局名或者强制自己转换成父类型，来访问父类中被隐藏的方法，但是可以通过强制转换为父类型之后，访问父类型中被隐藏的变量。静态方法不能覆盖父类的实例方法，而静态变量却可以隐藏父类的一个同名实例变量。实例方法不能覆盖父类的同名静态方法，而变量却可以隐藏父类的同名成员变量。<br />&nbsp;<wbr><br />4.我最终发现和解决的问题<br />public class ClassA{<br />public void methodOne(int i){}<br />public void methodTwo(int i){}<br />public static void methodThree(int i){}<br />public static void methodFour(int i){}<br />}<br />&nbsp;<wbr><br />public class ClassB{<br />public static void methodOne(int i){}<br />public void methodTwo(int i){}<br />public void methodThree(int i){}<br />public static void methodFour(int i){}<br />}<br />a.哪些方法覆盖了超类中的方法？ methodTwo<br />b.哪些方法隐藏了超类中的方法？ methodFour<br />其他两个方法编译会报错，因为不能用子类的静态方法隐藏父类中同名的实例方法，不能用子类的实例方法覆盖父类中同名的静态方法。<br /> </pre><pre>&nbsp;<wbr> </pre></div></font><img src ="http://www.blogjava.net/liuyz2006/aggbug/409423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2014-01-29 09:46 <a href="http://www.blogjava.net/liuyz2006/articles/409423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Runnable和Thread的区别(转）</title><link>http://www.blogjava.net/liuyz2006/articles/408157.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 28 Dec 2013 08:54:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/408157.html</guid><description><![CDATA[<div class="article_title">在java中可有两种方式实现多线程，一种是继承Thread类，一种是实现Runnable接口；Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了，但是一个类只能继承一个父类，这是此方法的局限，</div>
<div class="article_content" id="article_content">
<p style="font-size: 14px; font-family: Simsun">　　下面看例子：</p>
<p style="font-size: 14px; font-family: Simsun">　　package org.thread.demo;</p>
<p style="font-size: 14px; font-family: Simsun">　　class MyThread extends Thread{</p>
<p style="font-size: 14px; font-family: Simsun">　　private String name;</p>
<p style="font-size: 14px; font-family: Simsun">　　public MyThread(String name) {</p>
<p style="font-size: 14px; font-family: Simsun">　　super();</p>
<p style="font-size: 14px; font-family: Simsun">　　this.name = name;</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　public void run(){</p>
<p style="font-size: 14px; font-family: Simsun">　　for(int i=0;i&lt;10;i++){</p>
<p style="font-size: 14px; font-family: Simsun">　　System.out.println("线程开始："+this.name+",i="+i);</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　package org.thread.demo;</p>
<p style="font-size: 14px; font-family: Simsun">　　public class ThreadDemo01 {</p>
<p style="font-size: 14px; font-family: Simsun">　　public static void main(String[] args) {</p>
<p style="font-size: 14px; font-family: Simsun">　　MyThread mt1=new MyThread("线程a");</p>
<p style="font-size: 14px; font-family: Simsun">　　MyThread mt2=new MyThread("线程b");</p>
<p style="font-size: 14px; font-family: Simsun">　　mt1.run();</p>
<p style="font-size: 14px; font-family: Simsun">　　mt2.run();</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　但是，此时结果很有规律，先第一个对象执行，然后第二个对象执行，并没有相互运行。在JDK的文档中可以发现，一旦调用start()方法，则会通过JVM找到run()方法。下面启动</p>
<p style="font-size: 14px; font-family: Simsun">　　start()方法启动线程：</p>
<p style="font-size: 14px; font-family: Simsun">　　package org.thread.demo;</p>
<p style="font-size: 14px; font-family: Simsun">　　public class ThreadDemo01 {</p>
<p style="font-size: 14px; font-family: Simsun">　　public static void main(String[] args) {</p>
<p style="font-size: 14px; font-family: Simsun">　　MyThread mt1=new MyThread("线程a");</p>
<p style="font-size: 14px; font-family: Simsun">　　MyThread mt2=new MyThread("线程b");</p>
<p style="font-size: 14px; font-family: Simsun">　　mt1.start();</p>
<p style="font-size: 14px; font-family: Simsun">　　mt2.start();</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　};这样程序可以正常完成交互式运行。那么为啥非要使用start();方法启动多线程呢？</p>
<p style="font-size: 14px; font-family: Simsun">　　在JDK的安装路径下，src.zip是全部的java源程序，通过此代码找到Thread中的start()方法的定义，可以发现此方法中使用了private native void start0();其中native关键字表示可以调用操作系统的底层函数，那么这样的技术成为JNI技术（java Native Interface）</p>
<p style="font-size: 14px; font-family: Simsun">　　&#183;Runnable接口</p>
<p style="font-size: 14px; font-family: Simsun">　　在实际开发中一个多线程的操作很少使用Thread类，而是通过Runnable接口完成。</p>
<p style="font-size: 14px; font-family: Simsun">　　public interface Runnable{</p>
<p style="font-size: 14px; font-family: Simsun">　　public void run();</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　例子：</p>
<p style="font-size: 14px; font-family: Simsun">　　package org.runnable.demo;</p>
<p style="font-size: 14px; font-family: Simsun">　　class MyThread implements Runnable{</p>
<p style="font-size: 14px; font-family: Simsun">　　private String name;</p>
<p style="font-size: 14px; font-family: Simsun">　　public MyThread(String name) {</p>
<p style="font-size: 14px; font-family: Simsun">　　this.name = name;</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　public void run(){</p>
<p style="font-size: 14px; font-family: Simsun">　　for(int i=0;i&lt;100;i++){</p>
<p style="font-size: 14px; font-family: Simsun">　　System.out.println("线程开始："+this.name+",i="+i);</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　}</p>
<p style="font-size: 14px; font-family: Simsun">　　};</p>
<p style="font-size: 14px; font-family: Simsun"></p>
<div class="Article_content" style="font-size: 14px; font-family: Simsun">
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>　　但是在使用Runnable定义的子类中没有start()方法，只有Thread类中才有。此时观察Thread类，有一个构造方法：public Thread(Runnable targer)此构造方法接受Runnable的子类实例，也就是说可以通过Thread类来启动Runnable实现的多线程。（start()可以协调系统的资源）:</p>
<p>　　package org.runnable.demo;</p>
<p>　　import org.runnable.demo.MyThread;</p>
<p>　　public class ThreadDemo01 {</p>
<p>　　public static void main(String[] args) {</p>
<p>　　MyThread mt1=new MyThread("线程a");</p>
<p>　　MyThread mt2=new MyThread("线程b");</p>
<p>　　new Thread(mt1).start();</p>
<p>　　new Thread(mt2).start();</p>
<p>　　}</p>
<p>　　}</p>
<p>　　&#183; 两种实现方式的区别和联系：</p>
<p>　　在程序开发中只要是多线程肯定永远以实现Runnable接口为主，因为实现Runnable接口相比</p>
<p>　　继承Thread类有如下好处：</p>
<p>　　-&gt;避免点继承的局限，一个类可以继承多个接口。</p>
<p>　　-&gt;适合于资源的共享</p>
<p>　　以卖票程序为例，通过Thread类完成：</p>
<p>　　package org.demo.dff;</p>
<p>　　class MyThread extends Thread{</p>
<p>　　private int ticket=10;</p>
<p>　　public void run(){</p>
<p>　　for(int i=0;i&lt;20;i++){</p>
<p>　　if(this.ticket&gt;0){</p>
<p>　　System.out.println("卖票：ticket"+this.ticket--);</p>
<p>　　}</p>
<p>　　}</p>
<p>　　}</p>
<p>　　};</p>
<p>　　下面通过三个线程对象，同时卖票：</p>
<p>　　package org.demo.dff;</p>
<p>　　public class ThreadTicket {</p>
<p>　　public static void main(String[] args) {</p>
<p>　　MyThread mt1=new MyThread();</p>
<p>　　MyThread mt2=new MyThread();</p>
<p>　　MyThread mt3=new MyThread();</p>
<p>　　mt1.start();//每个线程都各卖了10张，共卖了30张票</p>
<p>　　mt2.start();//但实际只有10张票，每个线程都卖自己的票</p>
<p>　　mt3.start();//没有达到资源共享</p>
<p>　　}</p>
<p>　　}</p>
<p>　　如果用Runnable就可以实现资源共享，下面看例子：</p>
<p>　　package org.demo.runnable;</p>
<p>　　class MyThread implements Runnable{</p>
<p>　　private int ticket=10;</p>
<p>　　public void run(){</p>
<p>　　for(int i=0;i&lt;20;i++){</p>
<p>　　if(this.ticket&gt;0){</p>
<p>　　System.out.println("卖票：ticket"+this.ticket--);</p>
<p>　　}</p>
<p>　　}</p>
<p>　　}</p>
<p>　　}</p>
<p>　　package org.demo.runnable;</p>
<p>　　public class RunnableTicket {</p>
<p>　　public static void main(String[] args) {</p>
<p>　　MyThread mt=new MyThread();</p>
<p>　　new Thread(mt).start();//同一个mt，但是在Thread中就不可以，如果用同一</p>
<p>　　new Thread(mt).start();//个实例化对象mt，就会出现异常</p>
<p>　　new Thread(mt).start();</p>
<p>　　}</p>
<p>　　};</p>
<p>　　虽然现在程序中有三个线程，但是一共卖了10张票，也就是说使用Runnable实现多线程可以达到资源共享目的。</p>
<p>　　Runnable接口和Thread之间的联系：</p>
<p>　　public class Thread extends Object implements Runnable</p>
<p>　　发现Thread类也是Runnable接口的子类。</p></div></div><!-- Baidu Button BEGIN --><img src ="http://www.blogjava.net/liuyz2006/aggbug/408157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-12-28 16:54 <a href="http://www.blogjava.net/liuyz2006/articles/408157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java对象的生命周期及回收（转）</title><link>http://www.blogjava.net/liuyz2006/articles/407924.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Mon, 23 Dec 2013 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/407924.html</guid><description><![CDATA[<div class="blog_title">
<h3>&nbsp;</h3></div>
<div class="blog_content" id="blog_content">
<div class="iteye-blog-content-contain" style="font-size: 14px">
<p>要理解java对象的生命周期，我们需要要明白两个问题，</p>
<p>&nbsp;</p>
<p>&nbsp;1、java是怎么分配内存的 ,2、java是怎么回收内存的。</p>
<p>&nbsp;</p>
<p>喜欢java的人，往往因为它的内存自动管理机制，不喜欢java的人，往往也是因为它的内存自动管理。我属于前者，这几年的coding经验让我认识到，要写好java程序，理解java的内存管理机制是多么的重要。任何语言，内存管理无外乎分配和回收，在C中我们可以用malloc动态申请内存，调用free释放申请的内存；在C++中，我们可以用new操作符在堆中动态申请内存，编写析构函数调用delete释放申请的内存；那么在java中究竟是内存怎样管理的呢？要弄清这个问题，我们首先要了解java内存的分配机制，在java虚拟机规范里，JVM被分为7个内存区域，但是规范这毕竟只是规范，就像我们编写的接口一样，虽然最终行为一致，但是个人的实现可能千差万别，各个厂商的JVM实现也不尽相同，在这里，我们只针对sun的Hotspot虚拟机讨论,该虚拟机也是目前应用最广泛的虚拟机。</p>
<p>&nbsp;</p>
<p>&nbsp; 虚拟器规范中的7个内存区域分别是三个线程私有的和四个线程共享的内存区,线程私有的内存区域与线程具有相同的生命周期，它们分别是： 指令计数器、 线程栈和本地线程栈，四个共享区是所有线程共享的，在JVM启动时就会分配,分别是：方法区、 常量池、直接内存区和堆（即我们通常所说的JVM的内存分为堆和栈中的堆，后者就是前面的线程栈）。接下来我们逐一了解这几个内存区域。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; 1 指令计数器。我们都知道java的多线程是通过JVM切换时间片运行的，因此每个线程在某个时刻可能在运行也可能被挂起，那么当线程挂起之后，JVM再次调度它时怎么知道该线程要运行那条字节码指令呢？这就需要一个与该线程相关的内存区域记录该线程下一条指令，而指令计数器就是实现这种功能的内存区域。有多少线程在编译时是不确定的，因此该区域也没有办法在编译时分配，只能在创建线程时分配，所以说该区域是线程私有的，该区域只是指令的计数，占用的空间非常少，所以虚拟机规范中没有为该区域规定OutofMemoryError。</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp;2 线程栈。先让我看以下一段代码:</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">class</span><span>&nbsp;Test{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{ &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;th&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Thread(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;th.start(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="0" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">class Test{
    public static void main(String[] args) {
        Thread th = new Thread();
        th.start();
    }
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 在运行以上代码时，JVM将分配一块栈空间给线程th，用于保存方法内的局部变量，方法的入口和出口等，这些局部变量包括基本类型和对象引用类型，这里可能有人会问，java的对象引用不是分配在堆上吗？有这样疑惑的人，可能是没有理解java中引用和对象之间的区别，当我们写出以下代码时:</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">public</span><span>&nbsp;Object&nbsp;test(){ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;obj; &nbsp;&nbsp;</span></span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="1" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">public Object test(){
    Object obj = new Object();
    return obj;
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 其中的Object obj就是我们所说的引用类型，这样的声明本身是要占用4个字节，而这4个字节在这里就是在栈空间里分配的，准确的说是在线程栈中为test方法分配的栈帧中分配的，当方法退出时，将会随栈帧的弹出而自动销毁，而new Object()则是在堆中分配的，由GC在适当的时间收回其占用的空间。每个栈空间的默认大小为0.5M，在1.7里调整为1M，每调用一次方法就会压入一个栈帧，如果压入的栈帧深度过大，即方法调用层次过深,就会抛出StackOverFlow,，SOF最常见的场景就是递归中，当递归没办法退出时，就会抛此异常，Hotspot提供了参数设置改区域的大小，使用-Xss：xxK，就可以修改默认大小。 3 本地线程栈.顾名思义，该区域主要是给调用本地方法的线程分配的，该区域和线程栈的最大区别就是，在该线程的申请的内存不受GC管理，需要调用者自己管理，JDK中的Math类的大部分方法都是本地方法，一个值得注意的问题是,在执行本地方法时，并不是运行字节码，所以之前所说的指令计数器是没法记录下一条字节码指令的，当执行本地方法时，指令计数器置为undefined。 接下来是四个线程共享区。 1 方法区。这块区域是用来存放JVM装载的class的类信息，包括：类的方法、静态变量、类型信息(接口/父类)，我们使用反射技术时，所需的信息就是从这里获取的。 2 常量池。当我们编写如下的代码时：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">class</span><span>&nbsp;Test1{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;size=</span><span class="number">50</span><span>; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="2" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">class Test1{
     private final int size=50;
 }</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 这个程序中size因为用final修饰，不能再修改它的值，所以就成为常量，而这常量将会存放在常量区，这些常量在编译时就知道占用空间的大小，但并不是说明该区域编译就固定了，运行期也可以修改常量池的大小，典型的场景是在使用String时，你可以调用String的 intern()，JVM会判断当前所创建的String对象是否在常量池中，若有，则从常量区取，否则把该字符放入常量池并返回,这时就会修改常量池的大小，比如JDK中java.io.ObjectStreamField的一段代码:</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>ObjectStreamField(Field&nbsp;field,&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;unshared,&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;showType)&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.field&nbsp;=&nbsp;field; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.unshared&nbsp;=&nbsp;unshared; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;=&nbsp;field.getName(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;ftype&nbsp;=&nbsp;field.getType(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;=&nbsp;(showType&nbsp;||&nbsp;ftype.isPrimitive())&nbsp;?&nbsp;ftype&nbsp;:&nbsp;Object.</span><span class="keyword">class</span><span>; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;signature&nbsp;=&nbsp;ObjectStreamClass.getClassSignature(ftype).intern(); &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="3" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">ObjectStreamField(Field field, boolean unshared, boolean showType) {
    this.field = field;
    this.unshared = unshared;
    name = field.getName();
    Class ftype = field.getType();
    type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
    signature = ObjectStreamClass.getClassSignature(ftype).intern();
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 这段代码将获取的类的签名放入常量池。HotSpot中并没有单独为该区域分配，而是合并到方法区中。 3 直接内存区。直接内存区并不是JVM可管理的内存区。在JDK1.4中提供的NIO中，实现了高效的R/W操作，这种高效的R/W操作就是通过管道机制实现的，而管道机制实际上使用了本地内存，这样就避免了从本地源文件复制JVM内存，再从JVM复制到目标文件的过程，直接从源文件复制到目标文件，JVM通过DirectByteBuffer操作直接内存。 4 堆。主角总是最后出场，堆绝对是JVM中的一等公民，绝对的主角，我们通常所说的GC主要就是在这块区域中进行的，所有的java对象都在这里分配，这也是JVM中最大的内存区域，被所有线程共享，成千上万的对象在这里创建，也在这里被销毁。 java内存分配到这就算是一个完结了，接下来我们将讨论java内存的回收机制， 内存回收主要包含以下几个方面理解： 第一，局部变量占用内存的回收，所谓局部变量，就是指在方法内创建的变量，其中变量又分为基本类型和引用类型。如下代码:</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;test(){ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;x=</span><span class="number">1</span><span>; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">char</span><span>&nbsp;y=</span><span class="string">'a'</span><span>; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">long</span><span>&nbsp;z=10L; &nbsp;&nbsp;</span></span></li><li><span>}&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="4" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">public void test(){
    int x=1;
    char y='a';
    long z=10L;
} </pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 变量x y z即为局部变量，占用的空间将在test()所在的线程栈中分配，test()执行完了后会自动从栈中弹出，释放其占用的内存，再来看一段代码：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;test2(){ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;d&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Date(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"Now&nbsp;is&nbsp;"</span><span>+d); &nbsp;&nbsp;</span></span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="5" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">public void test2(){
    Date d = new Date();
    System.out.println("Now is "+d);
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; 我们都知道上述代码会创建两个对象，一个是Date d另一个是new Date。Date d叫做声明了一个date类型的引用，引用就是一种类型，和int x一样，它表明了这种类型要占用多少空间，在java中引用类型和int类型一样占用4字节的空间，如果只声明引用而不赋值，这4个字节将指向JVM中地址为0的空间，表示未初始化，对它的任何操作都会引发空指针异常。 如果进行赋值如d = new Date()那么这个d就保存了new Date（）这个对象的地址，通过之前的内存分配策略，我知道new Date（）是在jvm的heap中分配的，其占用的空间的回收我们将在后面着重分析，这里我们要知道的是这个Date d所占用的空间是在test2()所在的线程栈分配的，方法执行完后同样会被弹出栈，释放其占用的空间。 第二.非局部变量的内存回收,在上面的代码中new Date()就和C++里的new创建的对象一样，是在heap中分配，其占用的空间不会随着方法的结束而自动释放需要一定的机制去删除，在C++中必须由程序员在适当时候delete掉，在java中这部分内存是由GC自动回收的，但是要进行内存回收必须解决两问题：那些对象需要回收、怎么回收。判定那些对象需要回收，我们熟知的有以下方法： 一，引用计数法，这应是绝大数的的java 程序员听说的方法了，也是很多书上甚至很多老师讲的方法，该方法是这样描述的，为每个对象维护一个引用计数器，当有引用时就加1，引用解除时就减1，那些长时间引用为0的对象就判定为回收对象，理论上这样的判定是最准确的，判定的效率也高，但是却有一个致命的缺陷，请看以下代码：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://shuaijie506.iteye.com/blog/1779651#"><img alt="复制代码" src="http://shuaijie506.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://shuaijie506.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://shuaijie506.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">package</span><span>&nbsp;tmp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">import</span><span>&nbsp;java.util.ArrayList; &nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;java.util.List; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Test&nbsp;{ &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;buffer; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;List&nbsp;ls; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Test()&nbsp;{ &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.buffer&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">byte</span><span>[</span><span class="number">4</span><span>&nbsp;*&nbsp;</span><span class="number">1024</span><span>&nbsp;*&nbsp;</span><span class="number">1024</span><span>]; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.ls&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ArrayList(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;List&nbsp;getList()&nbsp;{ &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;ls; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;{ &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;t1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Test(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;t2&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Test(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.getList().add(t2); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.getList().add(t1); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;=&nbsp;t2&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;t3&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Test(); &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(t3); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="java对象的生命周期及回收" style="display: none" pre_index="6" source_url="http://shuaijie506.iteye.com/blog/1779651" codeable_type="Blog" codeable_id="1779651" name="code">package tmp;

import java.util.ArrayList;
import java.util.List;

public class Test {

	private byte[] buffer;
	private List ls;

	public Test() {
		this.buffer = new byte[4 * 1024 * 1024];
		this.ls = new ArrayList();
	}

	private List getList() {
		return ls;
	}

	public static void main(String[] args) {
		Test t1 = new Test();
		Test t2 = new Test();
		t1.getList().add(t2);
		t2.getList().add(t1);
		t1 = t2 = null;
		Test t3 = new Test();
		System.out.println(t3);
	}

}
</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;我们用以下参数运行：-Xmx10M -Xms10M M 将jvm的大小设置为10M，不允许扩展，按引用计数法，t1和t2相互引用，他们的引用计数都不可能为0，那么他们将永远不会回收，在我们的环境中JVM共10M，t1 t2占用8m，那么剩下的2M，是不足以创建t3的，理论上应该抛出OOM。但是，程序正常运行了，这说明JVM应该是回收了t1和t2的我们加上-XX:+PrintGCDetails运行，将打印GC的回收日记:</p>
<p>[GC [DefNew: 252K-&gt;64K(960K), 0.0030166 secs][Tenured: 8265K-&gt;137K(9216K), 0.0109869 secs] 8444K-&gt;137K(10176K), [Perm : 2051K-&gt;2051K(12288K)], 0.0140892 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]&nbsp;</p>
<p>&nbsp;</p><pre>[GC [DefNew: 252K-&gt;64K(960K), 0.0030166 secs][Tenured: 8265K-&gt;137K(9216K), 0.0109869 secs] 8444K-&gt;137K(10176K), [Perm : 2051K-&gt;2051K(12288K)], 0.0140892 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 
com.mail.czp.Test@2ce908
Heap
 def new generation   total 960K, used 27K [0x029e0000, 0x02ae0000, 0x02ae0000)
  eden space 896K,   3% used [0x029e0000, 0x029e6c40, 0x02ac0000)
  from space 64K,   0% used [0x02ad0000, 0x02ad0000, 0x02ae0000)
  to   space 64K,   0% used [0x02ac0000, 0x02ac0000, 0x02ad0000)
 tenured generation   total 9216K, used 4233K [0x02ae0000, 0x033e0000, 0x033e0000)
   the space 9216K,  45% used [0x02ae0000, 0x02f02500, 0x02f02600, 0x033e0000)
 compacting perm gen  total 12288K, used 2077K [0x033e0000, 0x03fe0000, 0x073e0000)
   the space 12288K,  16% used [0x033e0000, 0x035e74d8, 0x035e7600, 0x03fe0000)
No shared spaces configured.</pre>
<p>&nbsp;</p>
<p>从打印的日志我们可以看出，GC照常回收了t1 t2,这就从侧面证明jvm不是采用这种策略判定对象是否可以回收的。</p>
<p>&nbsp;</p>
<p>二，根搜索算法，这是当前的大部分虚拟机采用的判定策略，GC线程运行时，它会以一些特定的引用作为起点称为GCRoot，从这些起点开始搜索，把所用与这些起点相关联的对象标记，形成几条链路，扫描完时，那些没有与任何链路想连接的对象就会判定为可回收对象。具体那些引用作为起点呢，一种是类级别的引用：静态变量引用、常量引用，另一种是方法内的引用，如之前的test()方法中的Date d对new Date()的引用，在我们的测试代码中，在创建t3时，jvm发现当前的空间不足以创建对象，会出发一次GC，虽然t1和t2相互引用，但是执行t1=t2=null后，他们不和上面的3个根引用中的任何一个相连接，所以GC会判定他们是可回收对象，并在随后将其回收，从而为t3的创建创造空间，当进行回收后发现空间还是不够时，就会抛出OOM。</p>
<p>&nbsp;</p>
<p>接下来我们就该讨论GC 是怎么回收的了，目前版本的Hotspot虚拟机采用分代回收算法，它把heap分为新生代和老年代两块区域,如下图:</p>
<p>&nbsp;</p>
<p><img alt="" src="http://dl.iteye.com/upload/attachment/0080/0672/5d5cc78c-73b0-3ba5-a69e-1a228c3c8998.jpg" /><br />&nbsp;</p>
<p>&nbsp;默认的配置中老年代占90% 新生代占10%，其中新生代又被分为一个eden区和两个survivor区，每次使用eden和其中的一个survivor区，一般对象都在eden和其中的一个survivor区分配，但是那些占用空间较大的对象，就会直接在老年代分配，比如我们在进行文件操作时设置的缓冲区，如byte[] buffer = new byte[1024*1024],这样的对象如果在新生代分配将会导致新生代的内存不足而频繁的gc，GC运行时首先会进行会在新生代进行，会把那些标记还在引用的对象复制到另一块survivor空间中，然后把整个eden区和另一个survivor区里所有的对象进行清除，但也并不是立即清除，如果这些对象重写了finalize方法，那么GC会把这些对象先复制到一个队列里，以一个低级别的线程去触发finalize方法，然后回收该对象，而那些没有覆写finalize方法的对象，将会直接被回收。在复制存活对象到另一个survivor空间的过程中可能会出现空间不足的情况，在这种情况下GC回直接把这些存活对象复制到老年代中，如果老年代的空间也不够时，将会触发一次Full GC,Full gc会回收老年代中那些没有和任何GC Root相连的对象，如果Full GC后发现内存还是不足，将会出现OutofMemoryError。</p>
<p>&nbsp;</p>
<p>Hotspot虚拟机下java对象内存的分配和回收到此就算完结了</p></div></div>
<div class="attachments">
<ul style="display: none"><li><a href="http://dl2.iteye.com/upload/attachment/0080/0672/5d5cc78c-73b0-3ba5-a69e-1a228c3c8998.jpg" target="_blank"><img class="magplus" title="点击查看原始大小图片" src="http://dl2.iteye.com/upload/attachment/0080/0672/5d5cc78c-73b0-3ba5-a69e-1a228c3c8998-thumb.jpg"  alt="" /></a></li><li>大小: 11.1 KB </li></ul></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/407924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-12-23 16:52 <a href="http://www.blogjava.net/liuyz2006/articles/407924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析JVM内存结构和6大区域(转）</title><link>http://www.blogjava.net/liuyz2006/articles/401543.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 14 Jul 2013 02:13:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/401543.html</guid><description><![CDATA[<h1>浅析JVM内存结构和6大区域</h1>
<div class="msg">内存作为系统中重要的资源，对于系统稳定运行和高效运行起到了关键的作用，Java和C之类的语言不同，不需要开发人员来分配内存和回收内存，而是由JVM来管理对象内存的分配以及对象内存的回收（又称为垃圾回收、GC），这对于开发人员来说确实大大降低了编写程序的难度，但带来的一个副作用就是，当系统运行过程中出现JVM抛出的内存异常（例如OutOfMemoryError）的时候，很难知道原因是什么，另外一方面，要编写高性能的程序，通常需要借助内存来提升性能，因此如何才能合理的使用内存以及让JVM合理的进行内存的回收是必须掌握的，本文将主</div>
<div class="brieftext">
<p class="ad">AD： <a style="text-decoration: none" href="http://wot.51cto.com/cloud2013/" target="_blank">2013云计算架构师峰会超低价抢票中</a> </p></div>
<div style="display: none" id="indexlist" class="tag bgF8F8F8">
<ul id="indexliststr"></ul><br class="dle" /></div>
<div class="content bgF8F8F8 f14">
<div id="content">
<p>
<p>其实对于我们一般理解的计算机内存，它算是CPU与计算机打交道最频繁的区域，所有数据都是先经过硬盘至内存，然后由CPU再从内存中获取数据进行处理，又将数据保存到内存，通过分页或分片技术将内存中的数据再flush至硬盘。那JVM的内存结构到底是如何呢？JVM做为一个运行在操作系统上，但又独立于os运行的平台，它的内存至少应该包括象寄存器、堆栈等区域。</p>
<p>JVM在运行时将数据划分为了6个区域来存储，而不仅仅是大家熟知的Heap区域，这6个区域图示如下：</p>
<p style="text-align: center"><img class="fit-image" alt="" src="http://images.51cto.com/files/uploadimg/20130329/1111080.jpg" width="498" /></p>
<p style="text-align: center">&nbsp;JVM内存的分配结构示意图</p>
<p>下面将逐一介绍下各个区域所做的工作及其充当的功能。</p>
<p>PC Register(PC寄存器)</p>
<p>PC寄存器是一块很小的内存区域，主要作用是记录当前线程所执行的字节码的行号。字节码解释器工作时就是通过改变当前线程的程序计数器选取下一条字节码指令来工作的。任何分支，循环，方法调用，判断，异常处理，线程等待以及恢复线程，递归等等都是通过这个计数器来完成的。</p>
<p>由于Java多线程是通过交替线程轮流切换并分配处理器时间的方式来实现的，在任何一个确定的时间里，在处理器的一个内核只会执行一条线程中的指令。因此为了线程等待结束需要恢复到正确的位置执行，每条线程都会有一个独立的程序计数器来记录当前指令的行号。计数器之间相互独立互不影响，我们称这块内存为&#8220;线程私有&#8221;的内存。</p>
<p>如果所调用的方法为native的，则PC寄存器中不存储任何信息。</p>
<p>l&nbsp; JVM栈</p>
<p>JVM栈是线程私有的，每个线程创建的同时都会创建JVM栈，JVM栈中存放的为当前线程中局部基本类型的变量（java中定义的八种基本类型：boolean、char、byte、short、int、long、float、double）、部分的返回结果以及Stack Frame，非基本类型的对象在JVM栈上仅存放一个指向堆上的地址，因此Java中基本类型的变量是值传递，而非基本类型的变量是引用传递，Sun &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JDK的实现中JVM栈的空间是在物理内存上分配的，而不是从堆上分配。</p>
<p>由于JVM栈是线程私有的，因此其在内存分配上非常高效，并且当线程运行完毕后，这些内存也就被自动回收。</p>
<p>当JVM栈的空间不足时，会抛出StackOverflowError的错误，在Sun JDK中可以通过-Xss来指定栈的大小，例如如下代码：</p><pre><ol class="dp-c"><li class="alt"><span class="keyword">new</span><span>&nbsp;Thread(</span><span class="keyword">new</span><span>&nbsp;Runnable(){&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;run()&nbsp;{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop(0);&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;loop&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i){&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(i!=1000){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;&nbsp;</span></li><li><span>loop&nbsp;(i);&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>{&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}).start();&nbsp;</span></li></ol></pre>
<p>当JVM参数设置为-Xss1K，运行后会报出类似下面的错误：</p>
<p>Exception in thread "Thread-0"java.lang.StackOverflowError</p>
<p>l&nbsp; 堆（Heap）</p>
<p>Heap是大家最为熟悉的区域，它是JVM用来存储对象实例以及数组值的区域，可以认为Java中所有通过new创建的对象的内存都在此分配，Heap中的对象的内存需要等待GC进行回收，Heap在32位的操作系统上最大为2G，在64位的操作系统上则没有限制，其大小通过-Xms和-Xmx来控制，-Xms为JVM启动时申请的最小Heap内存，默认为物理内存的1/64但小于1G，-Xmx为JVM可申请的最大Heap内存，默认为物理内存的1/4，默认当空余堆内存小于40%时，JVM会增大Heap的大小到-Xmx指定的大小，可通过-XX:MinHeapFreeRatio=来指定这个比例，当空余堆内存大于70%时，JVM会将Heap的大小往-Xms指定的大小调整，可通过-XX:MaxHeapFreeRatio=来指定这个比例，但对于运行系统而言，为了避免频繁的Heap Size的大小，通常都会将-Xms和-Xmx的值设成一样，因此这两个用于调整比例的参数通常是没用的。其实jvm中对于堆内存的分配、使用、管理、收集等有更为精巧的设计，具体可以在JVM堆内存分析中进行详细介绍。</p>
<p>当堆中需要使用的内存超过其允许的大小时，会抛出OutOfMemory的错误信息。</p>
<p>l&nbsp; 方法区域（MethodArea）</p>
<p>方法区域存放了所加载的类的信息（名称、修饰符等）、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息，当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时，这些数据都来源于方法区域，可见方法区域的重要性。同样，方法区域也是全局共享的，它在虚拟机启动时在一定的条件下它也会被GC，当方法区域需要使用的内存超过其允许的大小时，会抛出OutOfMemory的错误信息。</p>
<p>在Sun JDK中这块区域对应的为PermanetGeneration，又称为持久代，默认为64M，可通过-XX:PermSize以及-XX:MaxPermSize来指定其大小。</p>
<p>l&nbsp; 运行时常量池（RuntimeConstant Pool）</p>
<p>类似C中的符号表，存放的为类中的固定的常量信息、方法和Field的引用信息等，其空间从方法区域中分配。类或接口的常量池在该类的class文件被java虚拟机成功装载时分配。</p>
<p>l&nbsp; 本地方法堆栈（NativeMethod Stacks）</p>
<p>JVM采用本地方法堆栈来支持native方法的执行，此区域用于存储每个native方法调用的状态。</p>
<p>例如有这么一段代码：</p><pre><ol class="dp-j"><li class="alt"><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;A&nbsp;{&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]args){&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;a=<span class="string">"a"</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;b=<span class="string">"b"</span><span>;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;ab=<span class="string">"ab"</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println((a+b)==ab);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;false</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println((<span class="string">"a"</span><span>+</span><span class="string">"b"</span><span>)==ab);&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;true</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;String&nbsp;afinal=</span><span class="string">"a"</span><span>;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;result=afinal+<span class="string">"b"</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(result==ab);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;true</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;plus=a+<span class="string">"b"</span><span>;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(plus==ab);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;false</span><span>&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(plus.intern()==ab);&nbsp;&nbsp;<span class="comment">//&nbsp;true</span><span>&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li></ol></pre>
<p>&nbsp;</p>
<p>分析下上面代码执行的结果，可通过javap &#8211;verbose A来辅助理解分析。</p>
<p>l&nbsp; (a+b)==ab</p>
<p>a+b是两个变量相加，需要到运行时才能确定其值，到运行时后JVM会为两者相加后产生一个新的对象，因此a+b==ab的结果为false。</p>
<p>l&nbsp; (&#8220;a&#8221;+&#8221;b&#8221;)==ab</p>
<p>&#8220;a&#8221;+&#8221;b&#8221;是常量，在编译时JVM已经将其变为&#8221;ab&#8221;字符串了，而ab=&#8221;ab&#8221;也是常量，这两者在常量池即为同一地址，因此(&#8220;a&#8221;+&#8221;b&#8221;)==ab为true。</p>
<p>l&nbsp; result==ab</p>
<p>result=afinal+&#8221;b&#8221;，afinal是个final的变量， result在编译时也已经被转变为了&#8221;ab&#8221;，和&#8221;ab&#8221;在常量池中同样为同一地址，因此result==ab为true。</p>
<p>l&nbsp; plus=ab</p>
<p>plus和a+b的情况是相同的，因此plus==ab为false。</p>
<p>l&nbsp; plus.intern()==ab</p>
<p>这里的不同点在于调用了plus.intern()方法，这个方法的作用是获取plus指向的常量池地址，因此plus.intern()==ab为true。</p>
<p>在掌握了JVM对象内存分配的机制后，接下来看看JVM是如何做到自动的对象内存回收的，这里指的的是Heap以及Method Area的回收，其他几个区域的回收都由JVM简单的按生命周期来进行管理</p>
<p>原文链接：http://blog.csdn.net/zhaozheng7758/article/details/8623562</p></div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/401543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-07-14 10:13 <a href="http://www.blogjava.net/liuyz2006/articles/401543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详解JVM工作原理和特点（转）</title><link>http://www.blogjava.net/liuyz2006/articles/401541.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 13 Jul 2013 15:11:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/401541.html</guid><description><![CDATA[<h1>详解JVM工作原理和特点</h1>
<div class="msg">在我们运行和调试Java程序的时候,经常会提到一个JVM的概念。本文将为大家讲解JVM工作原理和特点，希望对大家有所帮助。</div>
<div class="brieftext">
<p class="ad">AD： <a style="text-decoration: none" href="http://wot.51cto.com/cloud2013/" target="_blank">2013云计算架构师峰会超低价抢票中</a> </p></div>
<div style="display: none" id="indexlist" class="tag bgF8F8F8">
<ul id="indexliststr"></ul><br class="dle" /></div>
<div class="content bgF8F8F8 f14">
<div id="content">
<p>
<p>JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 
<p>1.创建JVM装载环境和配置 
<p>2.装载JVM.dll 
<p>3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 
<p>4.调用JNIEnv实例装载并处理class类。 </p>
<p>
<p>在我们运行和调试Java程序的时候,经常会提到一个JVM的概念.JVM是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间. 
<p>首先来说一下JVM工作原理中的jdk这个东西,不管你是初学者还是高手,是j2ee程序员还是j2se程序员,jdk总是在帮我们做一些事情.我们在了解Java之前首先大师们会给我们提供说jdk这个东西.它在Java整个体系中充当着什么角色呢?我很惊叹sun大师们设计天才,能把一个如此完整的体系结构化的如此完美.jdk在这个体系中充当一个生产加工中心,产生所有的数据输出,是所有指令和战略的执行中心.本身它提供了Java的完整方案,可以开发目前Java能支持的所有应用和系统程序.这里说一个问题,大家会问,那为什么还有j2me,j2ee这些东西,这两个东西目的很简单,分别用来简化各自领域内的开发和构建过程.jdk除了JVM之外,还有一些核心的API,集成API,用户工具,开发技术,开发工具和API等组成 
<p>好了,废话说了那么多,来点于主题相关的东西吧.JVM在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机. 操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 
<p>1.创建JVM装载环境和配置 
<p>2.装载JVM.dll 
<p>3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 
<p>4.调用JNIEnv实例装载并处理class类。 
<p><strong>一．JVM装入环境，JVM提供的方式是操作系统的动态连接文件．</strong>既然是文件那就一个装入路径的问题，Java是怎么找这个路径的呢？当你在调用Java test的时候，操作系统会在path下在你的Java.exe程序，Java.exe就通过下面一个过程来确定JVM的路径和相关的参数配置了．下面基于Windows的实现的分析． 
<p>首先查找jre路径，Java是通过GetApplicationHome api来获得当前的Java.exe绝对路径，c:\j2sdk1.4.2_09\bin\Java.exe,那么它会截取到绝对路径c:\j2sdk1.4.2_09\，判断c:\j2sdk1.4.2_09\bin\Java.dll文件是否存在，如果存在就把c:\j2sdk1.4.2_09\作为jre路径，如果不存在则判断c:\j2sdk1.4.2_09\jre\bin\Java.dll是否存在，如果存在这c:\j2sdk1.4.2_09\jre作为jre路径．如果不存在调用GetPublicJREHome查HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\&#8220;当前JRE版本号&#8221;\JavaHome的路径为jre路径。 
<p>然后装载JVM.cfg文件JRE路径+\lib+\ARCH（CPU构架）+\JVM.cfgARCH（CPU构架）的判断是通过Java_md.c中GetArch函数判断的，该函数中windows平台只有两种情况：WIN64的&#8216;ia64&#8217;，其他情况都为&#8216;i386&#8217;。以我的为例：C:\j2sdk1.4.2_09\jre\lib\i386\JVM.cfg.主要的内容如下： </p><pre><ol class="dp-xml"><li class="alt"><span>-client&nbsp;KNOWN&nbsp; &nbsp;</span></li><li><span>-server&nbsp;KNOWN&nbsp; &nbsp;</span></li><li class="alt"><span>-hotspot&nbsp;ALIASED_TO&nbsp;-client&nbsp; &nbsp;</span></li><li><span>-classic&nbsp;WARN&nbsp; &nbsp;</span></li><li class="alt"><span>-native&nbsp;ERROR&nbsp; &nbsp;</span></li><li><span>-green&nbsp;ERROR&nbsp;&nbsp;</span></li></ol></pre>
<p>在我们的jdk目录中jre\bin\server和jre\bin\client都有JVM.dll文件存在，而Java正是通过JVM.cfg配置文件来管理这些不同版本的JVM.dll的．通过文件我们可以定义目前jdk中支持那些JVM,前面部分（client）是JVM名称，后面是参数，KNOWN表示JVM存在，ALIASED_TO表示给别的JVM取一个别名，WARN表示不存在时找一个JVM替代，ERROR表示不存在抛出异常．在运行Java XXX是，Java.exe会通过CheckJVMType来检查当前的JVM类型，Java可以通过两种参数的方式来指定具体的JVM类型，一种按照JVM.cfg文件中的JVM名称指定，第二种方法是直接指定，它们执行的方法分别是&#8220;Java -J&#8221;、&#8220;Java -XXaltJVM=&#8221;或&#8220;Java -J-XXaltJVM=&#8221;。如果是第一种参数传递方式，CheckJVMType函数会取参数&#8216;-J&#8217;后面的JVM名称，然后从已知的JVM配置参数中查找如果找到同名的则去掉该JVM名称前的&#8216;-&#8217;直接返回该值；而第二种方法，会直接返回&#8220;-XXaltJVM=&#8221;或&#8220;-J-XXaltJVM=&#8221;后面的JVM类型名称；如果在运行Java时未指定上面两种方法中的任一一种参数，CheckJVMType会取配置文件中第一个配置中的JVM名称，去掉名称前面的&#8216;-&#8217;返回该值。CheckJVMType函数的这个返回值会在下面的函数中汇同jre路径组合成JVM.dll的绝对路径。如果没有指定这会使用JVM.cfg中第一个定义的JVM.可以通过set _Java_LAUNCHER_DEBUG=1在控制台上测试． 
<p>最后获得JVM.dll的路径，JRE路径+\bin+\JVM类型字符串+\JVM.dll就是JVM的文件路径了，但是如果在调用Java程序时用-XXaltJVM=参数指定的路径path,就直接用path+\JVM.dll文件做为JVM.dll的文件路径． 
<p><strong>二：装载JVM.dll</strong> 
<p>通过第一步已经找到了JVM的路径，Java通过LoadJavaVM来装入JVM.dll文件．装入工作很简单就是调用Windows API函数： 
<p>LoadLibrary装载JVM.dll动态连接库．然后把JVM.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。JVM.dll的装载工作宣告完成。 
<p><strong>三：初始化JVM，获得本地调用接口，</strong>这样就可以在Java中调用JVM的函数了．调用InvocationFunctions－&gt;CreateJavaVM也就是JVM中JNI_CreateJavaVM方法获得JNIEnv结构的实例． 
<p><strong>四：运行Java程序．</strong> 
<p>Java程序有两种方式一种是jar包，一种是class. 运行jar,Java -jar XXX.jar运行的时候，Java.exe调用GetMainClassName函数，该函数先获得JNIEnv实例然后调用Java类Java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值即jar包中文件：META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用Java.c中LoadClass方法装载该主类（使用JNIEnv实例的FindClass）。main函数直接调用Java.c中LoadClass方法装载该类。如果是执行class方法。main函数直接调用Java.c中LoadClass方法装载该类。 </p>
<p>然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中 
<p>&#8220;public static void main(String[] args)&#8221;方法，并判断该方法是否为public方法，然后调用JNIEnv实例的 
<p>CallStaticVoidMethod方法调用该Java类的main方法。&nbsp; </p>
<p>JVM工作原理和特点介绍到这里。</p></div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/401541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-07-13 23:11 <a href="http://www.blogjava.net/liuyz2006/articles/401541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入Java虚拟机：JVM中的Stack和Heap(转）</title><link>http://www.blogjava.net/liuyz2006/articles/401540.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 13 Jul 2013 15:00:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/401540.html</guid><description><![CDATA[<h1>深入Java虚拟机：JVM中的Stack和Heap</h1>
<div class="msg">在JVM中，静态属性保存在Stack指令内存区，动态属性保存在Heap数据内存区。本文将从JVM的角度来讲解Java虚拟机的这一机制。</div>
<div class="brieftext">
<div style="display: none" id="indexlist" class="tag bgF8F8F8">
<ul id="indexliststr"></ul><br class="dle" /></div></div>
<div class="content bgF8F8F8 f14">
<div id="content">
<p>
<p>在JVM中，内存分为两个部分，Stack（栈）和Heap（堆），这里，我们从JVM的内存管理原理的角度来认识Stack和Heap，并通过这些原理认清Java中静态方法和静态属性的问题。</p>
<p>一般，<a href="http://developer.51cto.com/art/201001/176550.htm" target="_blank"><strong>JVM</strong></a>的内存分为两部分：Stack和Heap。</p>
<p><strong>Stack</strong>（栈）是JVM的内存指令区。Stack管理很简单，push一定长度字节的数据或者指令，Stack指针压栈相应的字节位移；pop一定字节长度数据或者指令，Stack指针弹栈。Stack的速度很快，管理很简单，并且每次操作的数据或者指令字节长度是已知的。所以Java 基本数据类型，Java 指令代码，常量都保存在Stack中。</p>
<p><strong>Heap</strong>（堆）是JVM的内存数据区。Heap 的管理很复杂，每次分配不定长的内存空间，专门用来保存对象的实例。在Heap 中分配一定的内存来保存对象实例，实际上也只是保存对象实例的属性值，属性的类型和对象本身的类型标记等，并不保存对象的方法（方法是指令，保存在Stack中）,在Heap 中分配一定的内存保存对象实例和对象的序列化比较类似。而对象实例在Heap 中分配好以后，需要在Stack中保存一个4字节的Heap 内存地址，用来定位该对象实例在Heap 中的位置，便于找到该对象实例。</p>
<p>由于Stack的内存管理是顺序分配的，而且定长，不存在内存回收问题；而Heap 则是随机分配内存，不定长度，存在内存分配和回收的问题；因此在JVM中另有一个GC进程，定期扫描Heap ，它根据Stack中保存的4字节对象地址扫描Heap ，定位Heap 中这些对象，进行一些优化（例如合并空闲内存块什么的），并且假设Heap 中没有扫描到的区域都是空闲的，统统refresh（实际上是把Stack中丢失了对象地址的无用对象清除了），这就是垃圾收集的过程；关于垃圾收集的更深入讲解请参考51CTO之前的文章《<a href="http://developer.51cto.com/art/201002/184385.htm" target="_blank">JVM内存模型及垃圾收集策略解析</a>》。</p>
<p style="text-align: center"><a href="http://images.51cto.com/files/uploadimg/20100315/1435440.gif" target="_blank"><img class="fit-image" border="0" alt="JVM的体系结构" src="http://images.51cto.com/files/uploadimg/20100315/1435440.gif" width="498" height="299" /></a>&nbsp;<br /><strong><span style="font-size: smaller">JVM的体系结构</span></strong></p>
<p>我们首先要搞清楚的是什么是数据以及什么是指令。然后要搞清楚对象的方法和对象的属性分别保存在哪里。</p>
<p>1）方法本身是指令的操作码部分，保存在Stack中；</p>
<p>2）方法内部变量作为指令的操作数部分，跟在指令的操作码之后，保存在Stack中（实际上是简单类型保存在Stack中，对象类型在Stack中保存地址，在Heap 中保存值）；上述的指令操作码和指令操作数构成了完整的Java 指令。</p>
<p>3）对象实例包括其属性值作为数据，保存在数据区Heap 中。</p>
<p>非静态的对象属性作为对象实例的一部分保存在Heap 中，而对象实例必须通过Stack中保存的地址指针才能访问到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在Stack中的地址指针。</p>
<p><strong>非静态方法和静态方法的区别： </strong></p>
<p><strong>非静态方法</strong>有一个和静态方法很重大的不同：非静态方法有一个隐含的传入参数，该参数是JVM给它的，和我们怎么写代码无关，这个隐含的参数就是对象实例在Stack中的地址指针。因此非静态方法（在Stack中的指令代码）总是可以找到自己的专用数据（在Heap 中的对象属性值）。当然非静态方法也必须获得该隐含参数，因此非静态方法在调用前，必须先new一个对象实例，获得Stack中的地址指针，否则JVM将无法将隐含参数传给非静态方法。</p>
<p><strong>静态方法</strong>无此隐含参数，因此也不需要new对象，只要class文件被ClassLoader load进入JVM的Stack，该静态方法即可被调用。当然此时静态方法是存取不到Heap 中的对象属性的。</p>
<p>总结一下该过程：当一个class文件被ClassLoader load进入JVM后，方法指令保存在Stack中，此时Heap 区没有数据。然后程序技术器开始执行指令，如果是静态方法，直接依次执行指令代码，当然此时指令代码是不能访问Heap 数据区的；如果是非静态方法，由于隐含参数没有值，会报错。因此在非静态方法执行前，要先new对象，在Heap 中分配数据，并把Stack中的地址指针交给非静态方法，这样程序技术器依次执行指令，而指令代码此时能够访问到Heap 数据区了。</p>
<p><strong>静态属性和动态属性</strong>：</p>
<p>前面提到对象实例以及动态属性都是保存在Heap 中的，而Heap 必须通过Stack中的地址指针才能够被指令（类的方法）访问到。因此可以推断出：静态属性是保存在Stack中的，而不同于动态属性保存在Heap 中。正因为都是在Stack中，而Stack中指令和数据都是定长的，因此很容易算出偏移量，也因此不管什么指令（类的方法），都可以访问到类的静态属性。也正因为静态属性被保存在Stack中，所以具有了全局属性。</p>
<p>在JVM中，静态属性保存在Stack指令内存区，动态属性保存在Heap数据内存区。</p></div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/401540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-07-13 23:00 <a href="http://www.blogjava.net/liuyz2006/articles/401540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）JDBC中驱动加载的过程分析（下）</title><link>http://www.blogjava.net/liuyz2006/articles/400871.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 23 Jun 2013 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/400871.html</guid><description><![CDATA[<h2>JDBC<span style="font-family: 黑体">中驱动加载的过程分析（下）</span></h2>
<p align="right"><strong><span style="font-size: 12pt; font-family: 宋体"></span></strong><strong><span style="font-size: 12pt"></span></strong>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">本篇主要用几个开源数据库的驱动讲述驱动是如何加载的，以及&#8220;可插拔&#8221;机制等。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">由于文章篇幅有限，本文章并不是专门研究开源源代码！因此我们仅研究那些与数据库驱动加载直接相关的方法。在下面的几个开源软件的驱动中，我们主要关注驱动类的</span><span style="font-family: 'Arial Narrow'">getConnection()</span><span style="font-family: 宋体">方法。</span></p>
<h3><span style="font-family: 宋体">一、几个开源数据库的驱动类</span></h3>
<p style="text-indent: 21pt"><span style="font-family: 宋体">以下第一个是</span><span style="font-family: 'Arial Narrow'">smallsql</span><span style="font-family: 宋体">中驱动类</span><span style="font-family: 'Arial Narrow'">SSDriver</span><span style="font-family: 宋体">的源代码：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">package smallsql.database;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import java.sql.*;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import java.util.Properties;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">public class SSDriver implements Driver {</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static SSDriver drv;</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; static {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drv = new SSDriver();</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.sql.DriverManager.registerDriver(drv);</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Throwable e){}</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; public Connection connect(String url, Properties info) throws SQLException {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!acceptsURL(url)) return null;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new SSConnection( (idx &gt; 0) ? url.substring(idx+1) : null);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">}</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">从上面红色的部分可以看到：这是一个静态语句块（</span><span style="font-family: 'Arial Narrow'">static block</span><span style="font-family: 宋体">），这意味着该语句是在类构造完成前完成的（关于语句块的加载请阅读《</span><span style="font-family: 'Arial Narrow'">Think in java</span><span style="font-family: 宋体">》）。即调用</span><span style="font-family: 'Arial Narrow'">class.forName(&#8220;smallsql.database.SSDriver&#8221;)</span><span style="font-family: 宋体">语句时，会首先创建一个</span><span style="font-family: 'Arial Narrow'">SSDriver</span><span style="font-family: 宋体">的实例，并且将其向驱动管理器</span><span style="font-family: 'Arial Narrow'">(DriverManager)</span><span style="font-family: 宋体">注册。这样就完成驱动的注册了。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">从上面的蓝色的代码可以看出：驱动的连接方法返回的是一个具体的</span><span style="font-family: 'Arial Narrow'">SSConnection</span><span style="font-family: 宋体">对象。而在前面研究的</span><span style="font-family: 'Arial Narrow'">Driver</span><span style="font-family: 宋体">接口中返回的是</span><span style="font-family: 'Arial Narrow'">Connection</span><span style="font-family: 宋体">接口，这是不茅盾的，</span><span style="font-family: 'Arial Narrow'">SSConnection</span><span style="font-family: 宋体">对象实现了</span><span style="font-family: 'Arial Narrow'">Connection</span><span style="font-family: 宋体">接口。</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">再下面一个是</span><span style="font-family: 'Arial Narrow'">HSqlD</span><span style="font-family: 宋体">中的驱动类的源代码：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">package org.hsqldb;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import java.sql.*;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import java.util.Properties;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import org.hsqldb.jdbc.jdbcConnection;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import org.hsqldb.persist.HsqlDatabaseProperties;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">import org.hsqldb.persist.HsqlProperties;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">public class jdbcDriver implements Driver {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; public Connection connect(String url, Properties info) throws SQLException {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getConnection(url, info);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; public static Connection getConnection(String url, Properties info) throws SQLException {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HsqlProperties props = DatabaseURL.parseURL(url, true);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (props == null) {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new SQLException(Trace.getMessage(Trace.INVALID_JDBC_ARGUMENT));</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (props.isEmpty()) {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;return null;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.addProperties(info);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new jdbcConnection(props);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; static {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DriverManager.registerDriver(new jdbcDriver());</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {}</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">}</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">蓝色的依然是建立连接的部分，依然返回某个具体的实现</span>java.sql.Connection<span style="font-family: 宋体">接口的对象。是设计模式中的哪个工厂啊（一般工厂、抽象工厂、工厂方法还是什么都不是啊）！</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">红色的同样是一个静态语句块，同样完成该驱动的注册。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">两个开源数据库的驱动竟然如此相似，是不是其它的就不一样呢！看下面是</span>mckoi<span style="font-family: 宋体">中的驱动类：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">package com.mckoi;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">public class JDBCDriver extends com.mckoi.database.jdbc.MDriver {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;static {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; com.mckoi.database.jdbc.MDriver.register();</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;}</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;public JDBCDriver() {</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; super();</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; // Or we could move driver registering here...</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;}</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">}</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">红色的部分又是完成相同的工作&#8213;&#8213;在类装载完成前向驱动管理器注册驱动，只不过这次是调用</span>MDriver<span style="font-family: 宋体">的</span>register<span style="font-family: 宋体">方法罢了。那么该驱动建立连接是否也一样呢，当然一样啦！不信你看下面的代码：</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">package com.mckoi.database.jdbc;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">public class MDriver implements Driver {</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;private static boolean registered = false;</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;public synchronized static void register() {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; if (registered == false) {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.sql.DriverManager.registerDriver(new MDriver());</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;registered = true;</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (SQLException e) {</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="color: red; font-family: 'Arial Narrow'">&nbsp;}</span></p>
<p style="text-indent: 21pt">&nbsp;</p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;public Connection connect(String url, Properties info) throws SQLException {</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; if (!acceptsURL(url)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; DatabaseInterface db_interface;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; int row_cache_size;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; int max_row_cache_size;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; MConnection connection = new MConnection(url, db_interface, row_cache_size, max_row_cache_size);</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;&nbsp;&nbsp; return connection;</span></p>
<p style="text-indent: 21pt"><span style="color: blue; font-family: 'Arial Narrow'">&nbsp;}</span></p>
<p style="text-indent: 21pt"><span style="font-family: 'Arial Narrow'">}</span></p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">从以上三个开源数据库驱动的源代码可以看出：在调用</span>Class.forName(<span style="font-family: 'Arial Narrow'">&#8220;XXXDriver&#8221;</span>)<span style="font-family: 宋体">时，完成了将具体的驱动程序向</span>JDBC API<span style="font-family: 宋体">中驱动管理器的注册，该注册方法在类构造完成前完成，一般使用静态语句块。在调用</span>DriverManager<span style="font-family: 宋体">的</span>getConnection<span style="font-family: 宋体">方法时，一般先在已注册的驱动中查找可以了解此</span>URL<span style="font-family: 宋体">的驱动，然后调用该驱动的</span>connect<span style="font-family: 宋体">方法，从而建立连接，返回的连接都是一个实现</span>java.sql.Connection<span style="font-family: 宋体">接口的具体类。下面是该过程的时序图。</span></p>
<h3><span style="font-family: 宋体">二、</span>JDBC<span style="font-family: 宋体">中驱动加载的时序图</span></h3>
<h3><span style="font-family: 宋体"><a href="http://miaoxiaodong78.blog.163.com/album/prevPhoto.do?photoId=_fks_5SWRilyvY0iT8jlNEorvz-EKVaMU4HG-" target="_blank"><img src="http://blog.163.com/photo/s39frsU8y1i5XNS89arBcQ==/2834171540499687780.jpg" __1371967003265__="ev_3429604912"  alt="" /></a><a href="http://miaoxiaodong78.blog.163.com/album/prevPhoto.do?photoId=_fks_UrE5FMwN4hWr4QCUdFr6ZH0293IAOJxa" target="_blank"></a></span></h3>
<p align="center"></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">以上是</span>JDBC<span style="font-family: 宋体">中驱动加载的时序图。时序图主要有以下</span>7<span style="font-family: 宋体">个动作：</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">客户调用</span>Class.forName(&#8220;XXXDriver&#8221;)<span style="font-family: 宋体">加载驱动。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">此时此驱动类首先在其静态语句块中初始化此驱动的实例，</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">再向驱动管理器注册此驱动。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">客户向驱动管理器</span>DriverManager<span style="font-family: 宋体">调用</span>getConnection<span style="font-family: 宋体">方法，</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>DriverManager<span style="font-family: 宋体">调用注册到它上面的能够理解此</span>URL<span style="font-family: 宋体">的驱动建立一个连接，</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span>6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体">在该驱动中建立一个连接，一般会创建一个对应于数据库提供商的</span>XXXConnection<span style="font-family: 宋体">连接对象，</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt"><span style="color: blue">7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="color: blue; font-family: 宋体">驱动向客户返回此连接对象，不过在客户调用的</span><span style="color: blue">getConnection</span><span style="color: blue; font-family: 宋体">方法中返回的为一个</span><span style="color: blue">java.sql.Connection</span><span style="color: blue; font-family: 宋体">接口，而具体的驱动返回一个实现</span><span style="color: blue">java.sql.Connection</span><span style="color: blue; font-family: 宋体">接口的具体类。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">以上就是驱动加载的全过程。由此过程我们可以看出</span>JDBC<span style="font-family: 宋体">的其它一些特点。</span></p>
<h3><span style="font-family: 宋体">三、</span>JDBC<span style="font-family: 宋体">的架构</span></h3>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">在《教你建立简单</span>JDBC<span style="font-family: 宋体">程序》一篇中，讲述了一般</span>JDBC<span style="font-family: 宋体">的几个步骤。通过本篇的介绍，我将此程序分为以下几部分：</span></p>
<p align="center"></p>
<p align="center"><a href="http://miaoxiaodong78.blog.163.com/album/prevPhoto.do?photoId=_fks_UrE5FMwN4hWr4QCUdFr6ZH0293IAOJxa" target="_blank"><img src="http://blog.163.com/photo/rAakrpO8wFDjrRykuj1LGw==/2834171540499687789.jpg" __1371967003265__="ev_7341017316"  alt="" /></a>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">上图中，蓝色的即为本章前面介绍的</span>JDBC<span style="font-family: 宋体">驱动加载的细节部分。看看下面的部分：左面的很明显吧！是</span>java.sql<span style="font-family: 宋体">包中的接口吧！它是抽象的！右边呢？通过驱动管理器</span>DriverManager<span style="font-family: 宋体">得到的是一个实现</span>java.sql.Connection<span style="font-family: 宋体">接口的具体类吧！（不知道啊！前面不是讲过了吗！）因此我们可以可以注意到左右分别是抽象的和具体的。（这种抽象和具体的连接是由</span>java<span style="font-family: 宋体">的</span>RTTI<span style="font-family: 宋体">支持的，不懂可以阅读《</span>Think in java<span style="font-family: 宋体">》）。在接下来的结果集的处理</span>rs<span style="font-family: 宋体">也是抽象的吧！</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">因此，在写</span>JDBC<span style="font-family: 宋体">程序时，即使我们使用不同数据库提供商的数据库我们只要改变驱动类的地址，和具体连接的</span>URL<span style="font-family: 宋体">及其用户名和密码，其它几乎不用任何修改，就可以完成同样的工作！方便吧！</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">这意味着什么呢？我们其实是在针对抽象接口编程，只要知道接口的调用顺序，以及其中的主要方法，我们就可以迅速学会</span>JDBC<span style="font-family: 宋体">编程了！</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">同时，我们只要对不同数据库提供商的驱动类使用</span>Class.forName(&#8220;XXXDriver&#8221;)<span style="font-family: 宋体">就可以加载驱动，其细节你根本不用关注&#8213;&#8213;</span>JDBC Framework<span style="font-family: 宋体">已经全为你搞定了！应用程序对于不同提供商的数据库是无需太多改动的，因而其是&#8220;可插拔&#8221;的！整个</span>J2EE<span style="font-family: 宋体">就是一个高层的</span>API<span style="font-family: 宋体">&#8213;&#8213;抽象接口，用户可以使用不同的产品提供商提供的产品，使用统一的</span>API<span style="font-family: 宋体">，从而便于程序员学习！</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">谢谢大家！到此结束！</span></p><img src ="http://www.blogjava.net/liuyz2006/aggbug/400871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-06-23 14:13 <a href="http://www.blogjava.net/liuyz2006/articles/400871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转）JDBC中驱动加载的过程分析（上）</title><link>http://www.blogjava.net/liuyz2006/articles/400870.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 23 Jun 2013 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/400870.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JDBC中驱动加载的过程分析（上）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本篇从java.sql.Driver接口、java.sql.DriveManager类以及其它开源数据库的驱动类讨论JDBC中驱动加载的全过程以及JDBC的Framework如何做到&#8220;可插拔&#8221;的细节。&nbsp;&nbsp;&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/liuyz2006/articles/400870.html'>阅读全文</a><img src ="http://www.blogjava.net/liuyz2006/aggbug/400870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2013-06-23 14:11 <a href="http://www.blogjava.net/liuyz2006/articles/400870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 字符串编码总结 </title><link>http://www.blogjava.net/liuyz2006/articles/385770.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 19 Aug 2012 07:10:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/385770.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/385770.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/385770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/385770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/385770.html</trackback:ping><description><![CDATA[<div class="blog_title">
<h3><a href="http://technique-digest.iteye.com/blog/1065442">JAVA 字符串编码总结</a> <em class="actions"></em></h3>
<div class="news_tag"><a href="http://www.iteye.com/blogs/tag/Java">Java</a><a href="http://www.iteye.com/blogs/tag/JVM">JVM</a><a href="http://www.iteye.com/blogs/tag/%E6%B5%8F%E8%A7%88%E5%99%A8">浏览器</a><a href="http://www.iteye.com/blogs/tag/JSP">JSP</a><a href="http://www.iteye.com/blogs/tag/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8">应用服务器</a>&nbsp;</div></div>
<div class="blog_content" id="blog_content">
<p>String newStr = new String(oldStr.getBytes(), "UTF-8"); <br /><br />java中的String类是按照unicode进行编码的，当使用String(byte[] bytes, String encoding)构造字符串时，encoding所指的是bytes中的数据是按照那种方式编码的，而不是最后产生的String是什么编码方式，换句话说，是让系统把bytes中的数据由encoding编码方式转换成unicode编码。如果不指明，bytes的编码方式将由jdk根据操作系统决定。 <br /><br />当我们从文件中读数据时，最好使用InputStream方式，然后采用String(byte[] bytes, String encoding)指明文件的编码方式。不要使用Reader方式，因为Reader方式会自动根据jdk指明的编码方式把文件内容转换成unicode 编码。 <br /><br />当我们从数据库中读文本数据时，采用ResultSet.getBytes()方法取得字节数组，同样采用带编码方式的字符串构造方法即可。 <br /><br />ResultSet rs; <br />bytep[] bytes = rs.getBytes(); <br />String str = new String(bytes, "gb2312"); <br /><br />不要采取下面的步骤。 <br /><br />ResultSet rs; <br />String str = rs.getString(); <br />str = new String(str.getBytes("iso8859-1"), "gb2312"); <br /><br />这种编码转换方式效率底。之所以这么做的原因是，ResultSet在getString()方法执行时，默认数据库里的数据编码方式为 iso8859-1。系统会把数据依照iso8859-1的编码方式转换成unicode。使用str.getBytes("iso8859-1")把数据还原，然后利用new String(bytes, "gb2312")把数据从gb2312转换成unicode，中间多了好多步骤。 <br /><br />从HttpRequest中读参数时，利用reqeust.setCharacterEncoding()方法设置编码方式，读出的内容就是正确的了。 </p>
<p><br />先说Java。 <br />JVM里面的任何字符串资源都是Unicode，就是说，任何String类型的数据都是Unicode编码。没有例外。既然只有一种编码，那么，我们可以这么说，JVM里面的String是不带编码的。String相当于 char[]。 <br />JVM里面的 byte[] 数据是带编码的。比如，Big5，GBK，GB2312，UTF-8之类的。 <br />一个GBK编码的byte[] 转换成 String，其实就是从GBK编码向Unicode编码转换。 <br />一个String转换成一个Big5编码的byte[]，其实就是从Unicode编码向Big5编码转换。 <br />所以，Unicode是所有编码转换的中间介质。所有的编码都有一个转换器可以转换到Unicode，而Unicode也可以转换到其他所有的编码。这样构成了一个总线结构。 <br />比如，如果总共有10种编码，那么只需要 10 + 10 = 20个转换器就够了。如果要是两两直接转换，那么，需要的转换器数量是一个组合数字，需要90个转换器。 <br /><br />一个系统的不同部分，都有自己的编码。比如，数据库，文件，JVM，浏览器这4个部分。 <br />在这些部分之间数据交换的地方，就会出现编码问题。比如，数据库和JVM之间，文件和JVM之间，浏览器和JVM之间。这些问题的原理都是相通的。 <br /><br />编码问题最容易处理的地方是文件和JVM之间。文件IO API带有encoding 参数，请自行查阅。 <br />最不容易出现编码问题的地方是数据库和JVM之间。这应该是数据库JDBC连接的基本功能。本文不专门进行讨论。 <br />最容易出问题的地方是浏览器和服务器JVM之间（其实，代码里面的字符串更容易出问题，不过，我已经事先声明，本文不讨论代码中的字符串编码）。下面主要讨论这块浏览器和服务器JVM之间的编码问题。 <br /><br />我们把浏览器编码叫做 Browser_Charset，把JVM编码叫做JVM_Charset（通常等于服务器系统编码）。 <br />当浏览器的数据过来的时候，是一个带有Browser_Charset的byte[]。 <br />如果用户处理程序需要一个String类型的数据，那么JVM会好心好意地把这个byte[]转换成String。使用的转换器是 JVM_Charset -&gt; Unicode。 <br />注意，如果这个时候，Browser_Charset 和 JVM_Charset并不相等。那么，这个自动转换是错误的。 <br />为了弥补这个错误。我们需要做两步工作。 <br />(1) Unicode -&gt; JVM_Charset，把这个String 转换回到原来的 byte[]。 <br />(2) Browser_Charset -&gt; Unicode，把这个还原的byte[]转换成 String。 <br /><br />这个效果，和直接从HTTP Request取得byte[]，然后执行 (2) Browser_Charset -&gt; Unicode 的效果是一样的。 <br /><br />如果在Request里面设置了CharacterEncoding，那么POST Data参数就不需要自己手工转换了，web server的自动转换就是正确的。URL的参数编码还涉及到URL编码，需要考虑的问题多一些，没有这么简单。 <br /><br />JVM把数据发到浏览器的时候。也需要考虑编码问题。可以在Response里面设置。另外，HTML Meta Header里面也可以设置编码，提醒Browser选择正确编码。 <br /><br />有些语言的VM或者解释器的字符串编码可能不同。比如，Ruby。不过，编码转换原理都是一样的。 <br /><br />That is all. <br /></p>
<p>JAVA字符编码 <br /><br />一、概要 <br />在JAVA应用程序特别是基于WEB的程序中，经常遇到字符的编码问题。为了防止出现乱码，首先需要了解JAVA是如何处理字符的，这样就可以有目的地在输入/输出环节中增加必要的转码。其次，由于各种服务器有不同的处理方式，还需要多做试验，确保使用中不出现乱码。 <br />二、基本概念 <br />2．1 JAVA中字符的表达 <br />JAVA 中有char、byte、String这几个概念。char 指的是一个UNICODE字符，为16位的整数。byte 是字节，字符串在网络传输或存储前需要转换为byte数组。在从网络接收或从存储设备读取后需要将byte数组转换成String。String是字符串，可以看成是由char组成的数组。String 和 char 为内存形式，byte是网络传输或存储的序列化形式。 <br />举例： <br />英 <br />String ying = &#8220;英&#8221;; <br />char ying = ying.charAt(0); <br />String yingHex = Integer.toHexString(ying); <br />82 F1 <br />byte yingGBBytes = ying.getBytes(&#8220;GBK&#8221;); <br />GB编码的字节数值 <br />D3 A2 <br />2．2 编码方式的简介 <br />String序列化成byte数组或反序列化时需要选择正确的编码方式。如果编码方式不正确，就会得到一些0x3F的值。常用的字符编码方式有ISO8859_1、GB2312、GBK、UTF-8/UTF-16/UTF-32。 <br />ISO8859_1用来编码拉丁文，它由单字节（0－255）组成。 <br />GB2312、GBK用来编码简体中文，它有单字节和双字节混合组成。最高位为1的字节和下一个字节构成一个汉字，最高位为0的字节是ASCII码。 <br />UTF-8/UTF-16/UTF-32是国际标准UNICODE的编码方式。 用得最多的是UTF-8，主要是因为它在对拉丁文编码时节约空间。 <br />UNICODE值 UTF-8编码 <br />U-00000000 - U-0000007F: 0xxxxxxx <br />U-00000080 - U-000007FF: 110xxxxx 10xxxxxx <br />U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx <br />U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx <br />U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx <br />U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx <br />三、J2SE中相关的函数 <br />String str =&#8221;英&#8221;; <br />//取得GB2312编码的字节 <br />byte[] bytesGB2312 = str.getBytes(&#8220;GB2312&#8221;); <br />//取得平台缺省编码的字节(solaris为ISO8859_1,windows为GB2312) <br />byte[] bytesDefault = str.getBytes(); <br />//用指定的编码将字节转换成字符串 <br />String newStrGB = new String(bytesGB2312, &#8220;GB2312&#8221;); <br /><br />//用平台缺省的编码将字节转换成字符串(solaris为ISO8859_1,windows为GB2312) <br />String newStrDefault = new String(bytesDefault); <br />//用指定的编码从字节流里面读取字符 <br />InputStream in = xxx; <br />InputStreamReader reader = InputStreamReader( in, &#8220;GB2312&#8221;); <br />char aChar = reader.read(); <br />四、JSP、数据库的编码 <br />4．1 JSP中的编码 <br />(1) 静态声明: <br />CHARSET有两个作用： <br />JSP文件的编码方式：在读取JSP文件、生成JAVA类时，源JSP文件中汉字的编码 <br />JSP输出流的编码方式：在执行JSP时，往response流里面写入数据的编码方式 <br />(2) 动态改变:在往response流里面写数据前可以调用response.setContentType()，设定正确的编码类型。 <br />(3) 在TOMCAT中，由Request.getParameter() 得到的参数，编码方式都是ISO8859_1。所以如果在浏览器输入框内输入一个汉字&#8220;英&#8221;，在服务器端就得到一个ISO8859_1编码的（0x00,0xD3,0x00,0xA2）。所以通常在接收参数时转码： <br />String wrongStr = response.getParameter(&#8220;name&#8221;); <br />String correctStr = new String(wrongStr.getBytes(&#8220;ISO8859_1&#8221;),&#8221;GB2312&#8221;); <br />在最新的SERVLET规范里面，也可以在获取参数之前执行如下代码： <br />request.setCharacterEncoding(&#8220;GB2312&#8221;); <br />4．2 数据库的编码 <br />(1) 数据库使用UTF-16 <br />如果String中是UNICODE字符，写入读出时不需要转码 <br />(2) 数据库使用ISO8859_1 <br />如果String中是UNICODE字符，写入读出时需要转码 <br />写入：String newStr = new String(oldStr.getByte(&#8220;GB2312&#8221;), &#8220;ISO8859_1&#8221;); <br />读出：String newStr = new String(oldStr.getByte(&#8220;ISO8859_1&#8221;),&#8221;GB2312&#8221;); <br />五、源文件的编码 <br />5．1 资源文件 <br />资源文件的编码方式和编辑平台相关。在WINDOWS平台下编写的资源文件，以GB2312方式编码。在编译时需要转码，以确保在各个平台上的正确性： <br />native2ascii ?encoding GB2312 source.properties <br />这样从资源文件中读出的就是正确的UNICODE字符串。 <br />5．2 源文件 <br />源文件的编码方式和编辑平台相关。在WINDOWS平台下开发的源文件，以GB2312方式编码。在编译的时候，需要指定源文件的编码方式： <br />javac ?encoding GB2312 <br />JAVA编译后生成的字节文件的编码为UTF-8。 <br /><br />&#9312;最新版TOMCAT4.1.18支持request.setCharacterEncoding(String enc) <br />&#9313;资源文件转码成company.name=u82f1u65afu514b <br />&#9314;如果数据库使用utf-16则不需要这部分转码 <br />&#9315;页面上应有 <br />转码?: <br />String s = new String <br />(request.getParameter(&#8220;name&#8221;).getBytes(&#8220;ISO8859_1&#8221;),&#8221;GB2312&#8221;); <br />转码?: <br />String s = new String(name.getBytes(&#8220;GB2312&#8221;),&#8221;ISO8859_1&#8221;); <br />转码?: <br />String s = new String(name.getBytes(&#8220;ISO8859_1&#8221;),&#8221; GB2312&#8221;); <br /></p></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/385770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-08-19 15:10 <a href="http://www.blogjava.net/liuyz2006/articles/385770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java几种常见的编码格式 </title><link>http://www.blogjava.net/liuyz2006/articles/385768.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 19 Aug 2012 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/385768.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/385768.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/385768.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/385768.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/385768.html</trackback:ping><description><![CDATA[<div class="news_tag" id="topic_tags" style="width: 567px"><a href="http://www.iteye.com/forums/tag/Java%E7%BB%BC%E5%90%88">Java综合</a> </div>几种常见的编码格式 <br />为什么要编码 <br />不知道大家有没有想过一个问题，那就是为什么要编码？我们能不能不编码？要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的，这些符号也就是我们人类使用的语言。由于人类的语言有太多，因而表示这些语言的符号太多，无法用计算机中一个基本的存储单元&#8212;&#8212; byte 来表示，因而必须要经过拆分或一些翻译工作，才能让计算机能理解。我们可以把计算机能够理解的语言假定为英语，其它语言要能够在计算机中使用必须经过一次翻译，把它翻译成英语。这个翻译的过程就是编码。所以可以想象只要不是说英语的国家要能够使用计算机就必须要经过编码。这看起来有些霸道，但是这就是现状，这也和我们国家现在在大力推广汉语一样，希望其它国家都会说汉语，以后其它的语言都翻译成汉语，我们可以把计算机中存储信息的最小单位改成汉字，这样我们就不存在编码问题了。 <br />所以总的来说，编码的原因可以总结为： <br />计算机中存储信息的最小单元是一个字节即 8 个 bit，所以能表示的字符范围是 0~255 个 <br />人类要表示的符号太多，无法用一个字节来完全表示 <br />要解决这个矛盾必须需要一个新的数据结构 char，从 char 到 byte 必须编码 <br />如何&#8220;翻译&#8221; <br />明白了各种语言需要交流，经过翻译是必要的，那又如何来翻译呢？计算中提拱了多种翻译方式，常见的有 ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16 等。它们都可以被看作为字典，它们规定了转化的规则，按照这个规则就可以让计算机正确的表示我们的字符。目前的编码格式很多，例如 GB2312、GBK、UTF-8、UTF-16 这几种格式都可以表示一个汉字，那我们到底选择哪种编码格式来存储汉字呢？这就要考虑到其它因素了，是存储空间重要还是编码的效率重要。根据这些因素来正确选择编码格式，下面简要介绍一下这几种编码格式。 <br />ASCII 码 <br />学过计算机的人都知道 ASCII 码，总共有 128 个，用一个字节的低 7 位表示，0~31 是控制字符如换行回车删除等；32~126 是打印字符，可以通过键盘输入并且能够显示出来。 <br />ISO-8859-1 <br />128 个字符显然是不够用的，于是 ISO 组织在 ASCII 码基础上又制定了一些列标准用来扩展 ASCII 编码，它们是 ISO-8859-1~ISO-8859-15，其中 ISO-8859-1 涵盖了大多数西欧语言字符，所有应用的最广泛。ISO-8859-1 仍然是单字节编码，它总共能表示 256 个字符。 <br />GB2312 <br />它的全称是《信息交换用汉字编码字符集 基本集》，它是双字节编码，总的编码范围是 A1-F7，其中从 A1-A9 是符号区，总共包含 682 个符号，从 B0-F7 是汉字区，包含 6763 个汉字。 <br />GBK <br />全称叫《汉字内码扩展规范》，是国家技术监督局为 windows95 所制定的新的汉字内码规范，它的出现是为了扩展 GB2312，加入更多的汉字，它的编码范围是 8140~FEFE（去掉 XX7F）总共有 23940 个码位，它能表示 21003 个汉字，它的编码是和 GB2312 兼容的，也就是说用 GB2312 编码的汉字可以用 GBK 来解码，并且不会有乱码。 <br />GB18030 <br />全称是《信息交换用汉字编码字符集》，是我国的强制标准，它可能是单字节、双字节或者四字节编码，它的编码与 GB2312 编码兼容，这个虽然是国家标准，但是实际应用系统中使用的并不广泛。 <br />UTF-16 <br />说到 UTF 必须要提到 Unicode（Universal Code 统一码），ISO 试图想创建一个全新的超语言字典，世界上所有的语言都可以通过这本字典来相互翻译。可想而知这个字典是多么的复杂，关于 Unicode 的详细规范可以参考相应文档。Unicode 是 Java 和 XML 的基础，下面详细介绍 Unicode 在计算机中的存储形式。 <br />UTF-16 具体定义了 Unicode 字符在计算机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式，这个是定长的表示方法，不论什么字符都可以用两个字节表示，两个字节是 16 个 bit，所以叫 UTF-16。UTF-16 表示字符非常方便，每两个字节表示一个字符，这个在字符串操作时就大大简化了操作，这也是 Java 以 UTF-16 作为内存的字符存储格式的一个很重要的原因。 <br />UTF-8 <br />UTF-16 统一采用两个字节表示一个字符，虽然在表示上非常简单方便，但是也有其缺点，有很大一部分字符用一个字节就可以表示的现在要两个字节表示，存储空间放大了一倍，在现在的网络带宽还非常有限的今天，这样会增大网络传输的流量，而且也没必要。而 UTF-8 采用了一种变长技术，每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成。 <br />UTF-8 有以下编码规则： <br />如果一个字节，最高位（第 8 位）为 0，表示这是一个 ASCII 字符（00 - 7F）。可见，所有 ASCII 编码已经是 UTF-8 了。 <br />如果一个字节，以 11 开头，连续的 1 的个数暗示这个字符的字节数，例如：110xxxxx 代表它是双字节 UTF-8 字符的首字节。 <br />如果一个字节，以 10 开始，表示它不是首字节，需要向前查找才能得到当前字符的首字节 <br />Java 中需要编码的场景 <br />前面描述了常见的几种编码格式，下面将介绍 Java 中如何处理对编码的支持，什么场合中需要编码。 <br />I/O 操作中存在的编码 <br />我们知道涉及到编码的地方一般都在字符到字节或者字节到字符的转换上，而需要这种转换的场景主要是在 I/O 的时候，这个 I/O 包括磁盘 I/O 和网络 I/O，关于网络 I/O 部分在后面将主要以 Web 应用为例介绍。下图是 Java 中处理 I/O 问题的接口： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image002.png"  alt="" /> <br />Reader 类是 Java 的 I/O 中读字符的父类，而 InputStream 类是读字节的父类，InputStreamReader 类就是关联字节到字符的桥梁，它负责在 I/O 过程中处理读取字节到字符的转换，而具体字节到字符的解码实现它由 StreamDecoder 去实现，在 StreamDecoder 解码过程中必须由用户指定 Charset 编码格式。值得注意的是如果你没有指定 Charset，将使用本地环境中的默认字符集，例如在中文环境中将使用 GBK 编码。 <br />写的情况也是类似，字符的父类是 Writer，字节的父类是 OutputStream，通过 OutputStreamWriter 转换字符到字节。如下图所示： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image004.png"  alt="" /> <br />同样 StreamEncoder 类负责将字符编码成字节，编码格式和默认编码规则与解码是一致的。 <br />如下面一段代码，实现了文件的读写功能： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>String&nbsp;file&nbsp;=&nbsp;</span><span class="string">"c:/stream.txt"</span><span>;&nbsp; &nbsp;&nbsp;</span></li><li><span>String&nbsp;charset&nbsp;=&nbsp;</span><span class="string">"UTF-8"</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">//&nbsp;写字符换转成字节流 </span><span>&nbsp;&nbsp;</span></span></li><li><span>FileOutputStream&nbsp;outputStream&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;FileOutputStream(file);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>OutputStreamWriter&nbsp;writer&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;OutputStreamWriter(&nbsp; &nbsp;&nbsp;</span></span></li><li><span>outputStream,&nbsp;charset);&nbsp; &nbsp;&nbsp;</span></li><li><span></span><span class="keyword">try</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;writer.write(</span><span class="string">"这是要保存的中文字符"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>}&nbsp;</span><span class="keyword">finally</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;writer.close();&nbsp; &nbsp;&nbsp;</span></li><li><span>}&nbsp; &nbsp;&nbsp;</span></li><li><span></span><span class="comment">//&nbsp;读取字节转换成字符 </span><span>&nbsp;&nbsp;</span></span></li><li><span>FileInputStream&nbsp;inputStream&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;FileInputStream(file);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>InputStreamReader&nbsp;reader&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;InputStreamReader(&nbsp; &nbsp;&nbsp;</span></span></li><li><span>inputStream,&nbsp;charset);&nbsp; &nbsp;&nbsp;</span></li><li><span>StringBuffer&nbsp;buffer&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;StringBuffer();&nbsp; &nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">char</span><span>[]&nbsp;buf&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">char</span><span>[</span><span class="number"><font color="#c00000">64</font></span><span>];&nbsp; &nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">int</span><span>&nbsp;count&nbsp;=&nbsp;</span><span class="number"><font color="#c00000">0</font></span><span>;&nbsp; &nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">try</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">while</span><span>&nbsp;((count&nbsp;=&nbsp;reader.read(buf))&nbsp;!=&nbsp;-</span><span class="number"><font color="#c00000">1</font></span><span>)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer.append(buffer,&nbsp;</span><span class="number"><font color="#c00000">0</font></span><span>,&nbsp;count);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;</span></li><li><span>}&nbsp;</span><span class="keyword">finally</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;reader.close();&nbsp; &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="0" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code"> String file = "c:/stream.txt"; 
 String charset = "UTF-8"; 
 // 写字符换转成字节流
 FileOutputStream outputStream = new FileOutputStream(file); 
 OutputStreamWriter writer = new OutputStreamWriter( 
 outputStream, charset); 
 try { 
    writer.write("这是要保存的中文字符"); 
 } finally { 
    writer.close(); 
 } 
 // 读取字节转换成字符
 FileInputStream inputStream = new FileInputStream(file); 
 InputStreamReader reader = new InputStreamReader( 
 inputStream, charset); 
 StringBuffer buffer = new StringBuffer(); 
 char[] buf = new char[64]; 
 int count = 0; 
 try { 
    while ((count = reader.read(buf)) != -1) { 
        buffer.append(buffer, 0, count); 
    } 
 } finally { 
    reader.close(); 
 } </pre><br />在我们的应用程序中涉及到 I/O 操作时只要注意指定统一的编解码 Charset 字符集，一般不会出现乱码问题，有些应用程序如果不注意指定字符编码，中文环境中取操作系统默认编码，如果编解码都在中文环境中，通常也没问题，但是还是强烈的不建议使用操作系统的默认编码，因为这样，你的应用程序的编码格式就和运行环境绑定起来了，在跨环境下很可能出现乱码问题。 <br />内存中操作中的编码 <br />在 Java 开发中除了 I/O 涉及到编码外，最常用的应该就是在内存中进行字符到字节的数据类型的转换，Java 中用 String 表示字符串，所以 String 类就提供转换到字节的方法，也支持将字节转换为字符串的构造函数。如下代码示例： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>String&nbsp;s&nbsp;=&nbsp;</span><span class="string">"这是一段中文字符串"</span><span>;&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;b&nbsp;=&nbsp;s.getBytes(</span><span class="string">"UTF-8"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;String&nbsp;n&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;String(b,</span><span class="string">"UTF-8"</span><span>);&nbsp;&nbsp;&nbsp;</span></span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="1" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">String s = "这是一段中文字符串"; 
 byte[] b = s.getBytes("UTF-8"); 
 String n = new String(b,"UTF-8"); </pre><br />另外一个是已经被被废弃的 ByteToCharConverter 和 CharToByteConverter 类，它们分别提供了 convertAll 方法可以实现 byte[] 和 char[] 的互转。如下代码所示： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>ByteToCharConverter&nbsp;charConverter&nbsp;=&nbsp;ByteToCharConverter.getConverter(</span><span class="string">"UTF-8"</span><span>);&nbsp; &nbsp;&nbsp;</span></li><li><span></span><span class="keyword">char</span><span>&nbsp;c[]&nbsp;=&nbsp;charConverter.convertAll(byteArray);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>CharToByteConverter&nbsp;byteConverter&nbsp;=&nbsp;CharToByteConverter.getConverter(</span><span class="string">"UTF-8"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">byte</span><span>[]&nbsp;b&nbsp;=&nbsp;byteConverter.convertAll(c);&nbsp;&nbsp;&nbsp;</span></span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="2" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code"> ByteToCharConverter charConverter = ByteToCharConverter.getConverter("UTF-8"); 
 char c[] = charConverter.convertAll(byteArray); 
 CharToByteConverter byteConverter = CharToByteConverter.getConverter("UTF-8"); 
 byte[] b = byteConverter.convertAll(c); </pre><br />这两个类已经被 Charset 类取代，Charset 提供 encode 与 decode 分别对应 char[] 到 byte[] 的编码和 byte[] 到 char[] 的解码。如下代码所示： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>Charset&nbsp;charset&nbsp;=&nbsp;Charset.forName(</span><span class="string">"UTF-8"</span><span>);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;ByteBuffer&nbsp;byteBuffer&nbsp;=&nbsp;charset.encode(string);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;CharBuffer&nbsp;charBuffer&nbsp;=&nbsp;charset.decode(byteBuffer);&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="3" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">Charset charset = Charset.forName("UTF-8"); 
 ByteBuffer byteBuffer = charset.encode(string); 
 CharBuffer charBuffer = charset.decode(byteBuffer); </pre><br />编码与解码都在一个类中完成，通过 forName 设置编解码字符集，这样更容易统一编码格式，比 ByteToCharConverter 和 CharToByteConverter 类更方便。 <br />Java 中还有一个 ByteBuffer 类，它提供一种 char 和 byte 之间的软转换，它们之间转换不需要编码与解码，只是把一个 16bit 的 char 格式，拆分成为 2 个 8bit 的 byte 表示，它们的实际值并没有被修改，仅仅是数据的类型做了转换。如下代码所以： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>ByteBuffer&nbsp;heapByteBuffer&nbsp;=&nbsp;ByteBuffer.allocate(</span><span class="number"><font color="#c00000">1024</font></span><span>);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;ByteBuffer&nbsp;byteBuffer&nbsp;=&nbsp;heapByteBuffer.putChar(c);&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="4" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">ByteBuffer heapByteBuffer = ByteBuffer.allocate(1024); 
 ByteBuffer byteBuffer = heapByteBuffer.putChar(c); </pre><br />以上这些提供字符和字节之间的相互转换只要我们设置编解码格式统一一般都不会出现问题。 <br />Java 中如何编解码 <br />前面介绍了几种常见的编码格式，这里将以实际例子介绍 Java 中如何实现编码及解码，下面我们以&#8220;I am 君山&#8221;这个字符串为例介绍 Java 中如何把它以 ISO-8859-1、GB2312、GBK、UTF-16、UTF-8 编码格式进行编码的。 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;encode()&nbsp;{&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name&nbsp;=&nbsp;</span><span class="string">"I&nbsp;am&nbsp;君山"</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(name.toCharArray());&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;iso8859&nbsp;=&nbsp;name.getBytes(</span><span class="string">"ISO-8859-1"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(iso8859);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;gb2312&nbsp;=&nbsp;name.getBytes(</span><span class="string">"GB2312"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(gb2312);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;gbk&nbsp;=&nbsp;name.getBytes(</span><span class="string">"GBK"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(gbk);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;utf16&nbsp;=&nbsp;name.getBytes(</span><span class="string">"UTF-16"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(utf16);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;utf8&nbsp;=&nbsp;name.getBytes(</span><span class="string">"UTF-8"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHex(utf8);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(UnsupportedEncodingException&nbsp;e)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;}&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="5" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">public static void encode() { 
        String name = "I am 君山"; 
        toHex(name.toCharArray()); 
        try { 
            byte[] iso8859 = name.getBytes("ISO-8859-1"); 
            toHex(iso8859); 
            byte[] gb2312 = name.getBytes("GB2312"); 
            toHex(gb2312); 
            byte[] gbk = name.getBytes("GBK"); 
            toHex(gbk); 
            byte[] utf16 = name.getBytes("UTF-16"); 
            toHex(utf16); 
            byte[] utf8 = name.getBytes("UTF-8"); 
            toHex(utf8); 
        } catch (UnsupportedEncodingException e) { 
            e.printStackTrace(); 
        } 
 } 
</pre><br />我们把 name 字符串按照前面说的几种编码格式进行编码转化成 byte 数组，然后以 16 进制输出，我们先看一下 Java 是如何进行编码的。 <br />下面是 Java 中编码需要用到的类图 <br /><br />图 1. Java 编码类图 <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image007.jpg"  alt="" /> <br />首先根据指定的 charsetName 通过 Charset.forName(charsetName) 设置 Charset 类，然后根据 Charset 创建 CharsetEncoder 对象，再调用 CharsetEncoder.encode 对字符串进行编码，不同的编码类型都会对应到一个类中，实际的编码过程是在这些类中完成的。下面是 String. getBytes(charsetName) 编码过程的时序图 <br /><br />图 2.Java 编码时序图 <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image009.jpg"  alt="" /> <br />从上图可以看出根据 charsetName 找到 Charset 类，然后根据这个字符集编码生成 CharsetEncoder，这个类是所有字符编码的父类，针对不同的字符编码集在其子类中定义了如何实现编码，有了 CharsetEncoder 对象后就可以调用 encode 方法去实现编码了。这个是 String.getBytes 编码方法，其它的如 StreamEncoder 中也是类似的方式。下面看看不同的字符集是如何将前面的字符串编码成 byte 数组的？ <br />如字符串&#8220;I am 君山&#8221;的 char 数组为 49 20 61 6d 20 541b 5c71，下面把它按照不同的编码格式转化成相应的字节。 <br />按照 ISO-8859-1 编码 <br />字符串&#8220;I am 君山&#8221;用 ISO-8859-1 编码，下面是编码结果： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image011.gif"  alt="" /> <br />从上图看出 7 个 char 字符经过 ISO-8859-1 编码转变成 7 个 byte 数组，ISO-8859-1 是单字节编码，中文&#8220;君山&#8221;被转化成值是 3f 的 byte。3f 也就是&#8220;？&#8221;字符，所以经常会出现中文变成&#8220;？&#8221;很可能就是错误的使用了 ISO-8859-1 这个编码导致的。中文字符经过 ISO-8859-1 编码会丢失信息，通常我们称之为&#8220;黑洞&#8221;，它会把不认识的字符吸收掉。由于现在大部分基础的 Java 框架或系统默认的字符集编码都是 ISO-8859-1，所以很容易出现乱码问题，后面将会分析不同的乱码形式是怎么出现的。 <br />按照 GB2312 编码 <br />字符串&#8220;I am 君山&#8221;用 GB2312 编码，下面是编码结果： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image013.gif"  alt="" /> <br />GB2312 对应的 Charset 是 sun.nio.cs.ext. EUC_CN 而对应的 CharsetDecoder 编码类是 sun.nio.cs.ext. DoubleByte，GB2312 字符集有一个 char 到 byte 的码表，不同的字符编码就是查这个码表找到与每个字符的对应的字节，然后拼装成 byte 数组。查表的规则如下： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span>c2b[c2bIndex[</span><span class="keyword">char</span><span>&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">8</font></span><span>]&nbsp;+&nbsp;(</span><span class="keyword">char</span><span>&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0xff</font></span><span>)]&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="6" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code"> c2b[c2bIndex[char &gt;&gt; 8] + (char &amp; 0xff)] </pre><br />如果查到的码位值大于 oxff 则是双字节，否则是单字节。双字节高 8 位作为第一个字节，低 8 位作为第二个字节，如下代码所示： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">if</span><span>&nbsp;(bb&nbsp;&gt;&nbsp;</span><span class="number"><font color="#c00000">0xff</font></span><span>)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;DoubleByte&nbsp; </span><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dl&nbsp;-&nbsp;dp&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">2</font></span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;CoderResult.OVERFLOW;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)&nbsp;(bb&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">8</font></span><span>);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)&nbsp;bb;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;SingleByte&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dl&nbsp;-&nbsp;dp&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">1</font></span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;CoderResult.OVERFLOW;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)&nbsp;bb;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;}&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="7" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">if (bb &gt; 0xff) {    // DoubleByte 
            if (dl - dp &lt; 2) 
                return CoderResult.OVERFLOW; 
            da[dp++] = (byte) (bb &gt;&gt; 8); 
            da[dp++] = (byte) bb; 
 } else {                      // SingleByte 
            if (dl - dp &lt; 1) 
                return CoderResult.OVERFLOW; 
            da[dp++] = (byte) bb; 
 } </pre><br />从上图可以看出前 5 个字符经过编码后仍然是 5 个字节，而汉字被编码成双字节，在第一节中介绍到 GB2312 只支持 6763 个汉字，所以并不是所有汉字都能够用 GB2312 编码。 <br />按照 GBK 编码 <br />字符串&#8220;I am 君山&#8221;用 GBK 编码，下面是编码结果： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image015.gif"  alt="" /> <br />你可能已经发现上图与 GB2312 编码的结果是一样的，没错 GBK 与 GB2312 编码结果是一样的，由此可以得出 GBK 编码是兼容 GB2312 编码的，它们的编码算法也是一样的。不同的是它们的码表长度不一样，GBK 包含的汉字字符更多。所以只要是经过 GB2312 编码的汉字都可以用 GBK 进行解码，反过来则不然。 <br />按照 UTF-16 编码 <br />字符串&#8220;I am 君山&#8221;用 UTF-16 编码，下面是编码结果： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image017.gif"  alt="" /> <br />用 UTF-16 编码将 char 数组放大了一倍，单字节范围内的字符，在高位补 0 变成两个字节，中文字符也变成两个字节。从 UTF-16 编码规则来看，仅仅将字符的高位和地位进行拆分变成两个字节。特点是编码效率非常高，规则很简单，由于不同处理器对 2 字节处理方式不同，Big-endian（高位字节在前，低位字节在后）或 Little-endian（低位字节在前，高位字节在后）编码，所以在对一串字符串进行编码是需要指明到底是 Big-endian 还是 Little-endian，所以前面有两个字节用来保存 BYTE_ORDER_MARK 值，UTF-16 是用定长 16 位（2 字节）来表示的 UCS-2 或 Unicode 转换格式，通过代理对来访问 BMP 之外的字符编码。 <br />按照 UTF-8 编码 <br />字符串&#8220;I am 君山&#8221;用 UTF-8 编码，下面是编码结果： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image019.gif"  alt="" /> <br />UTF-16 虽然编码效率很高，但是对单字节范围内字符也放大了一倍，这无形也浪费了存储空间，另外 UTF-16 采用顺序编码，不能对单个字符的编码值进行校验，如果中间的一个字符码值损坏，后面的所有码值都将受影响。而 UTF-8 这些问题都不存在，UTF-8 对单字节范围内字符仍然用一个字节表示，对汉字采用三个字节表示。它的编码规则如下： <br /><br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/1117615#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a>&nbsp;<a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img class="spinner" style="display: none" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">private</span><span>&nbsp;CoderResult&nbsp;encodeArrayLoop(CharBuffer&nbsp;src,&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;ByteBuffer&nbsp;dst){&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">char</span><span>[]&nbsp;sa&nbsp;=&nbsp;src.array();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;sp&nbsp;=&nbsp;src.arrayOffset()&nbsp;+&nbsp;src.position();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;sl&nbsp;=&nbsp;src.arrayOffset()&nbsp;+&nbsp;src.limit();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;da&nbsp;=&nbsp;dst.array();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;dp&nbsp;=&nbsp;dst.arrayOffset()&nbsp;+&nbsp;dst.position();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;dl&nbsp;=&nbsp;dst.arrayOffset()&nbsp;+&nbsp;dst.limit();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;dlASCII&nbsp;=&nbsp;dp&nbsp;+&nbsp;Math.min(sl&nbsp;-&nbsp;sp,&nbsp;dl&nbsp;-&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;ASCII&nbsp;only&nbsp;loop&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">while</span><span>&nbsp;(dp&nbsp;&lt;&nbsp;dlASCII&nbsp;&amp;&amp;&nbsp;sa[sp]&nbsp;&lt;&nbsp;</span><span class="string">'\u0080'</span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)&nbsp;sa[sp++];&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">while</span><span>&nbsp;(sp&nbsp;&lt;&nbsp;sl)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">char</span><span>&nbsp;c&nbsp;=&nbsp;sa[sp];&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(c&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">0x80</font></span><span>)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Have&nbsp;at&nbsp;most&nbsp;seven&nbsp;bits&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dp&nbsp;&gt;=&nbsp;dl)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;overflow(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)c;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(c&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">0x800</font></span><span>)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;2&nbsp;bytes,&nbsp;11&nbsp;bits&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dl&nbsp;-&nbsp;dp&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">2</font></span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;overflow(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0xc0</font></span><span>&nbsp;|&nbsp;(c&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">6</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;(c&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(Character.isSurrogate(c))&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Have&nbsp;a&nbsp;surrogate&nbsp;pair&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(sgp&nbsp;==&nbsp;</span><span class="keyword">null</span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sgp&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Surrogate.Parser();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;uc&nbsp;=&nbsp;sgp.parse(c,&nbsp;sa,&nbsp;sp,&nbsp;sl);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(uc&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">0</font></span><span>)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updatePositions(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;sgp.error();&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dl&nbsp;-&nbsp;dp&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">4</font></span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;overflow(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0xf0</font></span><span>&nbsp;|&nbsp;((uc&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">18</font></span><span>)));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;((uc&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">12</font></span><span>)&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;((uc&nbsp;&gt;&gt;&nbsp;&nbsp;</span><span class="number"><font color="#c00000">6</font></span><span>)&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;(uc&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp++;&nbsp;&nbsp;</span><span class="comment">//&nbsp;2&nbsp;chars&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;3&nbsp;bytes,&nbsp;16&nbsp;bits&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(dl&nbsp;-&nbsp;dp&nbsp;&lt;&nbsp;</span><span class="number"><font color="#c00000">3</font></span><span>)&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;overflow(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0xe0</font></span><span>&nbsp;|&nbsp;((c&nbsp;&gt;&gt;&nbsp;</span><span class="number"><font color="#c00000">12</font></span><span>)));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;((c&nbsp;&gt;&gt;&nbsp;&nbsp;</span><span class="number"><font color="#c00000">6</font></span><span>)&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;da[dp++]&nbsp;=&nbsp;(</span><span class="keyword">byte</span><span>)(</span><span class="number"><font color="#c00000">0x80</font></span><span>&nbsp;|&nbsp;(c&nbsp;&amp;&nbsp;</span><span class="number"><font color="#c00000">0x3f</font></span><span>));&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp++;&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updatePositions(src,&nbsp;sp,&nbsp;dst,&nbsp;dp);&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;CoderResult.UNDERFLOW;&nbsp; &nbsp;&nbsp;</span></span></li><li><span>&nbsp;}&nbsp;&nbsp;&nbsp;</span></li></ol></div><pre class="java" title="深入分析 Java 中的中文编码问题(1)" style="display: none" pre_index="8" source_url="http://www.iteye.com/topic/1117615#2272937" codeable_id="2272937" codeable_type="Post" name="code">private CoderResult encodeArrayLoop(CharBuffer src, 
 ByteBuffer dst){ 
            char[] sa = src.array(); 
            int sp = src.arrayOffset() + src.position(); 
            int sl = src.arrayOffset() + src.limit(); 
            byte[] da = dst.array(); 
            int dp = dst.arrayOffset() + dst.position(); 
            int dl = dst.arrayOffset() + dst.limit(); 
            int dlASCII = dp + Math.min(sl - sp, dl - dp); 
            // ASCII only loop 
            while (dp &lt; dlASCII &amp;&amp; sa[sp] &lt; '\u0080') 
                da[dp++] = (byte) sa[sp++]; 
            while (sp &lt; sl) { 
                char c = sa[sp]; 
                if (c &lt; 0x80) { 
                    // Have at most seven bits 
                    if (dp &gt;= dl) 
                        return overflow(src, sp, dst, dp); 
                    da[dp++] = (byte)c; 
                } else if (c &lt; 0x800) { 
                    // 2 bytes, 11 bits 
                    if (dl - dp &lt; 2) 
                        return overflow(src, sp, dst, dp); 
                    da[dp++] = (byte)(0xc0 | (c &gt;&gt; 6)); 
                    da[dp++] = (byte)(0x80 | (c &amp; 0x3f)); 
                } else if (Character.isSurrogate(c)) { 
                    // Have a surrogate pair 
                    if (sgp == null) 
                        sgp = new Surrogate.Parser(); 
                    int uc = sgp.parse(c, sa, sp, sl); 
                    if (uc &lt; 0) { 
                        updatePositions(src, sp, dst, dp); 
                        return sgp.error(); 
                    } 
                    if (dl - dp &lt; 4) 
                        return overflow(src, sp, dst, dp); 
                    da[dp++] = (byte)(0xf0 | ((uc &gt;&gt; 18))); 
                    da[dp++] = (byte)(0x80 | ((uc &gt;&gt; 12) &amp; 0x3f)); 
                    da[dp++] = (byte)(0x80 | ((uc &gt;&gt;  6) &amp; 0x3f)); 
                    da[dp++] = (byte)(0x80 | (uc &amp; 0x3f)); 
                    sp++;  // 2 chars 
                } else { 
                    // 3 bytes, 16 bits 
                    if (dl - dp &lt; 3) 
                        return overflow(src, sp, dst, dp); 
                    da[dp++] = (byte)(0xe0 | ((c &gt;&gt; 12))); 
                    da[dp++] = (byte)(0x80 | ((c &gt;&gt;  6) &amp; 0x3f)); 
                    da[dp++] = (byte)(0x80 | (c &amp; 0x3f)); 
                } 
                sp++; 
            } 
            updatePositions(src, sp, dst, dp); 
            return CoderResult.UNDERFLOW; 
 } </pre><br />UTF-8 编码与 GBK 和 GB2312 不同，不用查码表，所以在编码效率上 UTF-8 的效率会更好，所以在存储中文字符时 UTF-8 编码比较理想。 <br />几种编码格式的比较 <br />对中文字符后面四种编码格式都能处理，GB2312 与 GBK 编码规则类似，但是 GBK 范围更大，它能处理所有汉字字符，所以 GB2312 与 GBK 比较应该选择 GBK。UTF-16 与 UTF-8 都是处理 Unicode 编码，它们的编码规则不太相同，相对来说 UTF-16 编码效率最高，字符到字节相互转换更简单，进行字符串操作也更好。它适合在本地磁盘和内存之间使用，可以进行字符和字节之间快速切换，如 Java 的内存编码就是采用 UTF-16 编码。但是它不适合在网络之间传输，因为网络传输容易损坏字节流，一旦字节流损坏将很难恢复，想比较而言 UTF-8 更适合网络传输，对 ASCII 字符采用单字节存储，另外单个字符损坏也不会影响后面其它字符，在编码效率上介于 GBK 和 UTF-16 之间，所以 UTF-8 在编码效率上和编码安全性上做了平衡，是理想的中文编码方式。 <br />Java Web 涉及到的编码 <br />对于使用中文来说，有 I/O 的地方就会涉及到编码，前面已经提到了 I/O 操作会引起编码，而大部分 I/O 引起的乱码都是网络 I/O，因为现在几乎所有的应用程序都涉及到网络操作，而数据经过网络传输都是以字节为单位的，所以所有的数据都必须能够被序列化为字节。在 Java 中数据被序列化必须继承 Serializable 接口。 <br />这里有一个问题，你是否认真考虑过一段文本它的实际大小应该怎么计算，我曾经碰到过一个问题：就是要想办法压缩 Cookie 大小，减少网络传输量，当时有选择不同的压缩算法，发现压缩后字符数是减少了，但是并没有减少字节数。所谓的压缩只是将多个单字节字符通过编码转变成一个多字节字符。减少的是 String.length()，而并没有减少最终的字节数。例如将&#8220;ab&#8221;两个字符通过某种编码转变成一个奇怪的字符，虽然字符数从两个变成一个，但是如果采用 UTF-8 编码这个奇怪的字符最后经过编码可能又会变成三个或更多的字节。同样的道理比如整型数字 1234567 如果当成字符来存储，采用 UTF-8 来编码占用 7 个 byte，采用 UTF-16 编码将会占用 14 个 byte，但是把它当成 int 型数字来存储只需要 4 个 byte 来存储。所以看一段文本的大小，看字符本身的长度是没有意义的，即使是一样的字符采用不同的编码最终存储的大小也会不同，所以从字符到字节一定要看编码类型。 <br />另外一个问题，你是否考虑过，当我们在电脑中某个文本编辑器里输入某个汉字时，它到底是怎么表示的？我们知道，计算机里所有的信息都是以 01 表示的，那么一个汉字，它到底是多少个 0 和 1 呢？我们能够看到的汉字都是以字符形式出现的，例如在 Java 中&#8220;淘宝&#8221;两个字符，它在计算机中的数值 10 进制是 28120 和 23453，16 进制是 6bd8 和 5d9d，也就是这两个字符是由这两个数字唯一表示的。Java 中一个 char 是 16 个 bit 相当于两个字节，所以两个汉字用 char 表示在内存中占用相当于四个字节的空间。 <br />这两个问题搞清楚后，我们看一下 Java Web 中那些地方可能会存在编码转换？ <br />用户从浏览器端发起一个 HTTP 请求，需要存在编码的地方是 URL、Cookie、Parameter。服务器端接受到 HTTP 请求后要解析 HTTP 协议，其中 URI、Cookie 和 POST 表单参数需要解码，服务器端可能还需要读取数据库中的数据，本地或网络中其它地方的文本文件，这些数据都可能存在编码问题，当 Servlet 处理完所有请求的数据后，需要将这些数据再编码通过 Socket 发送到用户请求的浏览器里，再经过浏览器解码成为文本。这些过程如下图所示： <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image021.gif"  alt="" /> <br />如上图所示一次 HTTP 请求设计到很多地方需要编解码，它们编解码的规则是什么？下面将会重点阐述一下： <br />URL 的编解码 <br />用户提交一个 URL，这个 URL 中可能存在中文，因此需要编码，如何对这个 URL 进行编码？根据什么规则来编码？有如何来解码？如下图一个 URL： <br /><br />图 4.URL 的几个组成部分 <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image023.gif"  alt="" /> <br />上图中以 Tomcat 作为 Servlet Engine 为例，它们分别对应到下面这些配置文件中： <br />Port 对应在 Tomcat 的 &lt;Connector port="8080"/&gt; 中配置，而 Context Path 在 &lt;Context path="/examples"/&gt; 中配置，Servlet Path 在 Web 应用的 web.xml 中的 <br />&lt;servlet-mapping&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;junshanExample&lt;/servlet-name&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/servlets/servlet/*&lt;/url-pattern&gt; <br />&lt;/servlet-mapping&gt; <br /><br />&lt;url-pattern&gt; 中配置，PathInfo 是我们请求的具体的 Servlet，QueryString 是要传递的参数，注意这里是在浏览器里直接输入 URL 所以是通过 Get 方法请求的，如果是 POST 方法请求的话，QueryString 将通过表单方式提交到服务器端，这个将在后面再介绍。 <br />上图中 PathInfo 和 QueryString 出现了中文，当我们在浏览器中直接输入这个 URL 时，在浏览器端和服务端会如何编码和解析这个 URL 呢？为了验证浏览器是怎么编码 URL 的我们选择 FireFox 浏览器并通过 HTTPFox 插件观察我们请求的 URL 的实际的内容，以下是 URL：HTTP://localhost:8080/examples/servlets/servlet/ 君山 ?author= 君山在中文 FireFox3.6.12 的测试结果 <br /><img src="http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/image025.jpg"  alt="" />&nbsp;<img src ="http://www.blogjava.net/liuyz2006/aggbug/385768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-08-19 14:38 <a href="http://www.blogjava.net/liuyz2006/articles/385768.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>myeclipse derby</title><link>http://www.blogjava.net/liuyz2006/articles/382774.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Wed, 11 Jul 2012 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/382774.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/382774.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/382774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/382774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/382774.html</trackback:ping><description><![CDATA[<div><p>环境:</p> <p>MyEclipse Enterprise Workbench</p> <p>Version: 8.5<br />Build id: 8.5-20100319</p> <p>WindowsXp </p> <p>1.切换到数据库视图.在DB Browser窗口中找到 MyEclipse Derby 单击右件选择new.</p> <p>2.</p> <p>Driver template: 选择derby;</p> <p>Driver name: 随便比如 MyDB;</p> <p>Connection URL : jdbc:derby://localhost:1527/MyDb;create=true</p> <p>说明:create=true 表示创建</p> <p>Username:zhangsan Password:123456</p> <p>Driver JARs:</p> <p>C:/Program Files/Genuitec/MyEclipse 8.5/configuration/org.eclipse.osgi/bundles/13/1/.cp/lib/derbyclient.jar;(成功)</p> <p>Driver classname = org.apache.derby.jdbc.ClientDriver</p> <p>或者</p> <p>C:/Program Files/Genuitec/MyEclipse 8.5/configuration/org.eclipse.osgi/bundles/13/1/.cp/lib/derby.jar;(我测试没有成功)</p> Driver class<br /><br /><br /><div><p>3.测试一下</p> <div bg_java"=""><div><div><strong>[java]</strong> <a href="http://blog.csdn.net/gudong2945/article/details/5440725#" title="view plain">view plain</a><a href="http://blog.csdn.net/gudong2945/article/details/5440725#" title="copy">copy</a></div></div><span>drop&nbsp;table&nbsp;guestbook;&nbsp;&nbsp;</span><br />create&nbsp;table&nbsp;guestbook&nbsp;(&nbsp;&nbsp;<br />id&nbsp;<span>int&nbsp;primary&nbsp;key&nbsp;generated&nbsp;by&nbsp;default&nbsp;as&nbsp;identity&nbsp;(START&nbsp;WITH&nbsp;1,&nbsp;INCREMENT&nbsp;BY&nbsp;1),&nbsp;&nbsp;</span><br />name&nbsp;varchar(<span>20)&nbsp;not&nbsp;null,&nbsp;&nbsp;&nbsp;</span><br />email&nbsp;varchar(<span>20),&nbsp;&nbsp;&nbsp;</span><br />phone&nbsp;varchar(<span>20),&nbsp;&nbsp;&nbsp;</span><br />title&nbsp;varchar(<span>50)&nbsp;not&nbsp;null,&nbsp;&nbsp;&nbsp;</span><br />content&nbsp;varchar(<span>2000)&nbsp;not&nbsp;null,&nbsp;&nbsp;&nbsp;</span><br />time&nbsp;date&nbsp;not&nbsp;<span>null&nbsp;&nbsp;&nbsp;</span><br />);&nbsp;&nbsp;<br />insert&nbsp;into&nbsp;guestbook&nbsp;(id,name,email,phone,title,content,time)&nbsp;&nbsp;&nbsp;&nbsp;<br />values(DEFAULT,<span>'lala','gudong@163.com','13991736400','ok','okcontent',CURRENT&nbsp;DATE);&nbsp;&nbsp;</span><br />select&nbsp;*&nbsp;from&nbsp;guestbook;&nbsp; <br /><br /><div>4.java中调用(如果出现不能侦听1527的错误,请重新启动Derby);</div><div>&nbsp;&nbsp;&nbsp; package webbook.chapter5; &nbsp;<br />&nbsp;&nbsp;&nbsp; import java.sql.Connection; &nbsp;<br />&nbsp;&nbsp;&nbsp; import java.sql.DriverManager; &nbsp;<br />&nbsp;&nbsp;&nbsp; import java.sql.PreparedStatement; &nbsp;<br />&nbsp;&nbsp;&nbsp; import java.sql.ResultSet; &nbsp;<br />&nbsp;&nbsp;&nbsp; import java.sql.SQLException; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp; public class JDBCExample { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String driver = "org.apache.derby.jdbc.ClientDriver"; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = "jdbc:derby://localhost:1527/MyDB"; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String username = "zhangsan"; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password = "123456"; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String sql = "insert into guestbook (id,name,email,phone,title,content,time)"&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +"values(DEFAULT,?,?,?,?,?,CURRENT DATE)"; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp; /*DEFAULT Derby中的自动增长 CURRENT DATE当前时间*/ &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection conn = null; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{ &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName(driver);&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = DriverManager.getConnection(url, username, password); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PreparedStatement pstmt = conn.prepareStatement(sql); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.setString(1, "gudong"); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.setString(2, "ZhangFei@163.com"); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.setString(3, "110"); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.setString(4, "title"); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.setString(5, "content"); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.executeUpdate(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sql="select * from guestbook "; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt = conn.prepareStatement(sql); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSet rs = pstmt.executeQuery(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(rs.next()){ &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("id:"+rs.getInt("ID")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("name:"+rs.getString("NAME")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("email:"+rs.getString("EMAIL")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("phone:"+rs.getString("PHONE")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("title:"+rs.getString("TITLE")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("content:"+rs.getString("content")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("date:"+rs.getString("time")); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (rs != null) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs.close(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pstmt != null) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pstmt.close(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (ClassNotFoundException e) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (SQLException e) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (conn != null) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn.close(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (SQLException e) { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp; } <br /><br />-----------------------------------------<br /><div>Myeclipse Derby使用指南【转】<br /><br /><br />一．Derby介绍<br />Apache Derby是开源的，100% Java编写的，容易管理的关系数据库管理系统，它可以和一些商业产品的特性进行交付。<br />Apache Derby 是一个与平台无关的数据库引擎，它以 Java 类库的形式对外提供服务。与其他难以部署的数据库不同，安装 Derby 非常简单，只需要将其 .jar 文件复制到系统中并为您的项目添加该 .jar 文件即可。<br /><br />Derby拥有一个令人惊奇的特性列表。它可以支持关系数据库中的所有企业级的特性，包括崩溃恢复、事务回滚和提交、行/表级锁、视图、主键/外键约束、触发器、子查询表达式，等等。一部分的列表特性使Derby从其他的Java 关系数据库管理系统中分离出来，包括：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 100% Java实现<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 100% Java类型4 JDBC驱动<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQL92E标准支持大部分SQL 99特性<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACID完全的事务独立的事务支持<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; J2EE支持JNDI，连接池和XA<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 视图，临时表和保存<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BLOB和CLOB数据类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 行和表锁定<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有价值的基本查询优化<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务器端指示约束<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 触发器和存储过程<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为服务器端函数，触发器或存储过程等操作在数据库里存储Java代码<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 能排除CD-ROM里的只读数据库<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据的导入和导出<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 快速数据库加密选项<br />您可以采用两种模式来部署和运行Derby：<br />&nbsp;&nbsp; 在嵌入式模式（embedded mode）中，Derby只处理来自与应用程序使用的JVM相同的JVM的请求。在采用嵌入式模式来使用Derby时，应用程序会在启动和关闭时分别自动启动或停止关系引擎。Derby包的derby.jar文件（2MB）包含了Derby 数据库引擎和嵌入式JDBC驱动程序。嵌入式模式的主要优点是不需要进行网络 和服务器设置。因为你的应用程序包含了Derby引擎，使用者并不知道你使用了一个关系数据库。这点很适合我们现在桌面工具的使用要求。<br />在网络服务器模式（network server mode）中，Derby会处理来自不同JVM的应用程序请求。或者，如果您喜欢使用Perl、PHP、Python或C来编写程序，那么您也可以部署一个Derby网络服务器，并通过各种语言特有的模块连接到这个服务器上，例如Perl的DBI（Database Interface）和PHP的ODBC（Open Database Connectivity）。Derby的derbynet.jar文件（0.2MB）包含了Derby Network Server。<br /><br />另外，Derby提供了Eclipse的插件供开发人员使用，下面将介绍插件的安装及使用。<br /><br />二．Derby安装与使用<br />1.软件的下载<br />你可以在Derby的官方网站下载，同时也可以下载Derby的两个Eclipse插件：derby_core_plugin和derby_ui_plugin；在下面使用前，请安装好JVM 1.4.x或更高版本；以及Eclipse 3.x。<br />2. Derby的Eclipse的插件安装与使用。<br />安装插件<br />&nbsp;&nbsp;&nbsp; Derby插件的安装与其他Eclipse插件安装类似，只需要将之前下载的两个插件解压到Eclipse plugins目录下，然后重新启动Eclipse即可。&nbsp;&nbsp; ：<br />使用插件<br />&nbsp;&nbsp;&nbsp; 在使用该插件前，我们先创建一个Java项目，取名为DerbyDemo，然后在Package Explorer视图选择该项目，单击右键选择菜单[Apache Derby]-&gt;[Add Apache Derby Nature]，如图：<br /><br /><br />接下来是配置Derby相关属性，在Package Explorer视图选择项目单击[Properties]在左边的属性列表中选择Apache Derby；并将 Derby 的主目录设为不同于项目根目录的某个目录，例如D:/derbyDB，如图：<br /><br />配置完毕后，我们就可以启动Derby服务器了，在Package Explorer视图选择项目单击[Apache Derby]-&gt;[Start Derby Network Server]；控制台将输出Derby的启动信息，启动就完成。<br />同样的，Derby 服务器的关闭也是类似的，在Package Explorer视图选择项目单击[Apache Derby]-&gt;[Stop Derby Network Server]。<br /><br />2．嵌入运行模式<br />&nbsp;&nbsp; 将derby.jar 和derbytools.jar导入工程<br />&nbsp;&nbsp; 下面是连接数据库的代码片断，create=true表示创建一个新数据库<br />import java.sql.Connection;<br />&nbsp;import java.sql.DriverManager;<br />&nbsp;import java.sql.ResultSet;<br />&nbsp;import java.sql.Statement;<br /><br />&nbsp;public class TestDerbyBaisc {<br />&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();//加载驱动<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection conn = DriverManager.getConnection("dbc:derby:TESTDB;create=true");//连接数据库<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Statement st = conn.createStatement();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; st.execute("create table USER_INFO (ID INT NOT NULL,NAME VARCHAR(10) NOT NULL)");//建表<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; st.executeUpdate("insert into USER_INFO(ID,NAME) values (1,'hermit')");//插入数据<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; st.executeUpdate("insert into USER_INFO(ID,NAME) values (2,'test')");//插入数据<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSet rs = st.executeQuery("select * from USER_INFO");//读取刚插入的数据<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(rs.next()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int id = rs.getInt(1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name = rs.getString(2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("ID="+id);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("NAME="+name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(Exception e){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;}</div><br /></div></div>  </div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/382774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-07-11 10:08 <a href="http://www.blogjava.net/liuyz2006/articles/382774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse的web工程转myeclipse的web工程(转)</title><link>http://www.blogjava.net/liuyz2006/articles/382480.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 07 Jul 2012 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/382480.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/382480.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/382480.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/382480.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/382480.html</trackback:ping><description><![CDATA[<div class="postTitle">　　eclipse的web工程转myeclipse的web工程<br /></div>
<div id="cnblogs_post_body"><pre class="reply-text mb10">1.原eclipse工程叫netschool 
2.在myeclipse中新建一个工程叫netschool 并在新建的时修改 web root folder为WebContent 
3.备份在myeclipse新建的netschool工程下的.classpath 和.mymetadata和.project以及.myeclipse文件夹 
4.删除在myeclipse新建的netschool工程 
5.通过svn 或cvs checkout 原eclipse工程netschool  拷贝第三步备份的文件到netschool工程根目录下 
6.刷新工程即可&nbsp;</pre><pre class="reply-text mb10">　　myeclipse的web工程转eclipse的web工程</pre><pre class="reply-text mb10">1.先在eclipse里创建一个同名项目,eg:pjt,然后将pjt改名为pjt.bak.<br />2.从svn上check out这个项目pjt。<br />3.打开pjt.bak,复制.settings文件夹、.classpath、.project这个三个文件覆盖pjt项目下的同名文件。</pre></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/382480.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-07-07 22:27 <a href="http://www.blogjava.net/liuyz2006/articles/382480.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java控制台程序访问oracle方法</title><link>http://www.blogjava.net/liuyz2006/articles/368563.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 15 Jan 2012 12:02:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/368563.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/368563.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/368563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/368563.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/368563.html</trackback:ping><description><![CDATA[<div><strong style="color: red">方法1：通过纯java数据库驱动程序</strong><strong><br /></strong><br />一、java 环境变量<br />
<p>java_home&nbsp; C:\java\jdk1.6.0_30</p>
<p>classpath&nbsp;&nbsp; .;C:\Java\jdk1.6.0_30\lib\tool.jar;C:\Java\jdk1.6.0_26\lib\dt.jar<br />path C:\java\jdk1.6.0_30\bin<br /><br />二、把ojdbc14.jar 拷贝到 c:\java\jre6\lib\ext下<br /><br />三、程序1,2放于c:\下，编译生成to_oracle2.class和to_oracle22.class也在c:\ 都能成功访问<br />运行java to_oracle2 java to_oracle22 都能成功访问<br /><br />程序1: to_oracle2.java<br />import java.sql.*; <br />public class to_oracle2 { <br />static Connection conn = null; <br />static ResultSet rs = null; </p>
<p>static {<br />try{ Class.forName("oracle.jdbc.driver.OracleDriver");}<br />&nbsp;&nbsp; catch(ClassNotFoundException e)<br />&nbsp;&nbsp; { e.printStackTrace();}<br />}</p>
<p>public static ResultSet executeQuery(String sql) { <br />rs = null; <br />try { <br />conn=DriverManager.getConnection("jdbc:oracle:thin:@10.77.48.9:1521:zlj","lyz","lyz");</p>
<p>Statement stmt = conn.createStatement(); <br />rs = stmt.executeQuery(sql); <br />}catch(SQLException ex) { <br />System.err.println("aq.executeQuery: " + ex.getMessage()); <br />} <br />return rs; <br />} </p>
<p>public static void main (String[] args)<br />{<br />try<br />{<br />String sql="select * from work_log";<br />ResultSet rs1=executeQuery(sql);<br />while (rs1.next())<br />{System.out.println(rs1.getString(1));}<br />}<br />catch (SQLException e) { }<br />}</p>
<p>} </p>
<p>--------程序2: to_oracle22.java<br /><br /></p>
<p>import java.sql.*;</p>
<p>public class to_oracle22{<br />Connection con =null;<br />Statement sql=null;<br />ResultSet rs=null;</p>
<p>{<br />try{ Class.forName("oracle.jdbc.driver.OracleDriver");}<br />&nbsp;&nbsp; catch(ClassNotFoundException e)<br />&nbsp;&nbsp; { e.printStackTrace();}</p>
<p><br />try {con=DriverManager.getConnection("jdbc:oracle:thin:@10.77.48.9:1521:zlj","lyz","lyz");}</p>
<p>&nbsp;&nbsp; catch(SQLException e)<br />&nbsp;&nbsp; { e.printStackTrace();}</p>
<p>&nbsp;}</p>
<p>public void query() {<br />try{<br />sql=con.createStatement();<br />rs=sql.executeQuery("select * from work_log");</p>
<p>while(rs.next())<br />{<br />System.out.println(rs.getString(1));<br />}<br />con.close();<br />}<br />catch (SQLException e)<br />{<br />}</p>
<p>}<br />public static void main(String args[]){<br />to_oracle22 o= new to_oracle22();<br />o.query();<br />}</p>
<p>}</p>
<p><br /><span style="color: red"><strong>&nbsp;方法2：通过odbc数据源<br /></strong></span><br /><span style="color: #000000">-</span>程序3,程序4放于c:\下，编译后的class文件也位于c:\下<br />java to_oracle0<br />java to_oracle1<br />正常访问数据库<br /><br />程序3：to_oracle0.java<br />import java.sql.*; <br />public class to_oracle0 { <br />static String&nbsp; sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; <br />static String sConnStr = "jdbc:odbc:zlj"; <br />static Connection conn = null; <br />static ResultSet rs = null; </p>
<p>public to_oracle0() { </p>
<p>try { Class.forName(sDBDriver); }<br />catch(java.lang.ClassNotFoundException e) <br />{ System.err.println("faq(): " + e.getMessage()); } </p>
<p>} </p>
<p><br />public static ResultSet executeQuery(String sql) { <br />rs = null; <br />try { </p>
<p>conn = DriverManager.getConnection(sConnStr,"lyz","lyz"); </p>
<p>Statement stmt = conn.createStatement(); <br />rs = stmt.executeQuery(sql); <br />}catch(SQLException ex) { <br />System.err.println("aq.executeQuery: " + ex.getMessage()); <br />} <br />return rs; <br />} </p>
<p>public static void main (String[] args)<br />{<br />try<br />{<br />String sql="select * from work_log";<br />ResultSet rs1=executeQuery(sql);<br />while (rs1.next())<br />{System.out.println(rs1.getString(1));}<br />}<br />catch (SQLException e) { }<br />}</p>
<p>} </p>
<p><br />程序4：to_oracle1.java<br />import java.sql.*; <br />public class to_oracle1 { <br />static String&nbsp; sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; <br />static String sConnStr = "jdbc:odbc:zlj"; <br />static Connection conn = null; <br />static ResultSet rs = null; </p>
<p>public to_oracle1() { </p>
<p>&nbsp;</p>
<p>try { Class.forName(sDBDriver); }<br />catch(java.lang.ClassNotFoundException e) <br />{ System.err.println("faq(): " + e.getMessage()); } </p>
<p>} </p>
<p>public static ResultSet executeQuery(String sql) { <br />rs = null; <br />try { </p>
<p>conn = DriverManager.getConnection(sConnStr,"lyz","lyz"); </p>
<p>Statement stmt = conn.createStatement(); <br />rs = stmt.executeQuery(sql); <br />}catch(SQLException ex) { <br />System.err.println("aq.executeQuery: " + ex.getMessage()); <br />} <br />return rs; <br />} </p>
<p>public static void main (String[] args)<br />{<br />try<br />{<br />String sql="select * from work_log";<br />ResultSet rs1=executeQuery(sql);<br />while (rs1.next())<br />{System.out.println(rs1.getString(1));}<br />}<br />catch (SQLException e) { }<br />}</p>
<p>} </p>
<p><br /><br /><br />&nbsp;</p></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/368563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-01-15 20:02 <a href="http://www.blogjava.net/liuyz2006/articles/368563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java通过JDBC连接oracle(转)</title><link>http://www.blogjava.net/liuyz2006/articles/368554.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sun, 15 Jan 2012 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/368554.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/368554.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/368554.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/368554.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/368554.html</trackback:ping><description><![CDATA[<h2>java通过JDBC连接oracle</h2>
<div class="content">
<p>Oracle provides drivers that enable users to make JDBC connections to Oracle databases. The two most common methods of connecting to Oracle databases via JDBC are the Oracle Thin JDBC driver and the Oracle OCI JDBC driver.</p>
<p>The Oracle Thin driver requires no software other than the driver jar file. This driver connects to Oracle databases via TCP/IP.</p>
<p>The Oracle OCI (Oracle Call Interface) driver requires Oracle client software to be installed on the user&#8217;s machine in order to connect to the database. This driver uses native methods and is platform specific.</p>
<p>The Java classes to connect to Oracle are contained in the Oracle JDBC driver jar file. For recent releases, these are numbered based on the Java version they are compiled for, such as ojdbc14.jar (for Java 1.4), ojdbc15.jar (for Java 1.5), etc. These drivers can be freely downloaded from Oracle&#8217;s site (free registration is required).</p>
<p>You can tell the Oracle driver which method you wish to use to connect to the database (OCI or Thin) via the JDBC connection URL. Listed below are some example connection URL formats:</p>
<p>Oracle JDBC Thin Driver Formats</p>
<p>第一种方式：推荐使用服务名连接，Oracle JDBC Thin using a Service Name:</p>
<p>jdbc:oracle:thin:@//&lt;host&gt;:&lt;port&gt;/&lt;service_name&gt;</p>
<p>Example: jdbc:oracle:thin:@//192.168.2.1:1521/XE</p>
<p>第二种方式：适合单机的sid，Oracle JDBC Thin using an SID:</p>
<p>jdbc:oracle:thin:@&lt;host&gt;:&lt;port&gt;:&lt;SID&gt;</p>
<p>Example: jdbc:oracle:thin:192.168.2.1:1521:X01A</p>
<p>Note: Support for SID is being phased out. Oracle recommends that users switch over to using service names.</p>
<p>Oracle JDBC Thin using a TNSName:</p>
<p>jdbc:oracle:thin:@&lt;TNSName&gt;</p>
<p>Example: jdbc:oracle:thin:@GL</p>
<p>Note: Support for TNSNames was added in the driver release 10.2.0.1</p>
<p>Oracle JDBC OCI Driver Format</p>
<p>jdbc:oracle:oci:@&lt;database_name&gt;</p>
<p>Example: jdbc:oracle:oci:@HR</p>
<p>The Oracle JDBC driver provides properties that can be specified when connecting to the database. Listed below are some examples of these properties.</p>
<p>To specify properties in the JDBC connection, you can use a Java Properties object, and pass that object into the JDBC getConnection method. For example:</p>
<p>java.util.Properties info = new java.util.Properties();</p>
<p>info.put(&#8220;internal_logon&#8221;, &#8220;sysdba&#8221;);</p>
<p>Connection conn = DriverManager.getConnection (url, info);</p>
<p>Connection Properties</p>
<p>internal_logon: Use this property to connect as a sysoper or sysdba role. When using this property, the user and password properties must be included in the properties object. For example:</p>
<p>Properties props = new Properties();</p>
<p>props.put(&#8220;user&#8221;, &#8220;scott&#8221;);</p>
<p>props.put(&#8220;password&#8221;, &#8220;tiger&#8221;);</p>
<p>props.put(&#8220;internal_logon&#8221;, &#8220;sysoper&#8221;);</p>
<p>Connection conn = DriverManager.getConnection (url, props);</p>
<p>defaultRowPrefetch: Oracle JDBC drivers allow you to set the number of rows to prefetch from the server while the result set is being populated during a query. Prefetching row data into the client reduces the number of round trips to the server. A typical value for this property is 10.</p>
<p>defaultBatchValue: Oracle JDBC drivers allow you to accumulate inserts and updates of prepared statements and send them to the server in batches once it reaches a specified batch value. This feature reduces round trips to the server. Use the value 1 if you don&#8217;t want to use this feature.</p>
<p>processEscapes: &#8220;false&#8221; to disable escape processing for statements (Statement or PreparedStatement) created from this connection. Set this to &#8220;false&#8221; if you want to avoid many calls to Statement.setEscapeProcessing(false);. This is espcially usefull for PreparedStatement where a call to setEscapeProcessing(false) would have no effect. The default is &#8220;true&#8221;.</p>
<p>No related posts.</p>
<div class="fixed"></div></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/368554.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-01-15 15:37 <a href="http://www.blogjava.net/liuyz2006/articles/368554.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据的传值与引用(转)</title><link>http://www.blogjava.net/liuyz2006/articles/368517.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Sat, 14 Jan 2012 14:04:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/368517.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/368517.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/368517.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/368517.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/368517.html</trackback:ping><description><![CDATA[<div class="articalTitle">
<h2 class="titName SG_txta" id="t_62b7c2210100fhao">数据的传值与引用(转)</h2></div><!-- 正文开始 -->

<div class="articalContent  " id="sina_keyword_ad_area2">
<p>数据的传值与引用主要体现在函数调用时候，通过参数来实现。</p>
<p>&nbsp;<wbr></p>
<p>当数据在传递时，内存为实际参数开辟内存地址及内存空间，存放数据变为形式参数（非同于实际参数的内存地址和内存空间）。当调用函数完后，定义函数相应的执行并没有改变实际参数。</p>
<p>&nbsp;<wbr></p>
<p>当数据（数组在引用时），内存只开辟内存地址而并不开辟内存空间，开辟的内存地址相同，决定了同一个地址位置。函数调用时，实际参数在定义函数的执行过程中，发生改变，因而成为引用。有点类似与浅拷贝，用的是同一个地址。</p>
<p>&nbsp;<wbr></p>
<p>总之：</p>
<p>数据的传递，内存不仅开辟存放数据的内存地址，还开辟存放数据的内存空间，数据传递到定义函数时候，实际参数到形式参数后，内存自动清空数据，数据在定义函数执行后不发生任何变化；数组在引用时，尽开辟了内存地址，并没有开辟存放数据的空间，数组在函数调用后，引用的是同一内存地址，必然数组经过定义函数后，实际参数发生改变。</p></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/368517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-01-14 22:04 <a href="http://www.blogjava.net/liuyz2006/articles/368517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java访问oracle 返回json 实践（一）</title><link>http://www.blogjava.net/liuyz2006/articles/367954.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 05 Jan 2012 14:00:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/367954.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/367954.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/367954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/367954.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/367954.html</trackback:ping><description><![CDATA[<p>&nbsp;------------建一个javabean 类 WorkRecord 用于保存访问数据库记录的内容</p>
<p>public class WorkRecord<br />{<br />private long do_seq;<br />private String proc_name;<br />private String sql_desc;<br />private String work_status;</p>
<p>public void setdo_seq(long do_seq)<br />{<br />this.do_seq=do_seq;<br />}</p>
<p>public void setproc_name(String proc_name)<br />{<br />this.proc_name=proc_name;<br />}</p>
<p>public void setsql_desc(String sql_desc)<br />{<br />this.sql_desc=sql_desc;<br />}</p>
<p>public void setwork_status(String work_status)<br />{<br />this.work_status=work_status;<br />}</p>
<p>&nbsp;</p>
<p>public long getDo_seq()<br />{<br />return do_seq;<br />}</p>
<p>public String getProc_name()<br />{<br />return proc_name;<br />}</p>
<p>public String&nbsp; getSql_desc()<br />{<br />return sql_desc;<br />}</p>
<p>public String getWork_status()<br />{<br />return work_status;<br />}</p>
<p><br />public static void main (String[] args)<br />{<br />System.out.println("hello");<br />}</p>
<p>}<br /><br />------------------------------建一个javabean类faq 用于访问数据库，并将访问的记录存于对象WorkRecord中，多个WorkRecord存于列表中</p>
<p>//java bean <br />//file name: faq.java </p>
<p>//package Test;</p>
<p>&nbsp;&nbsp;&nbsp; import java.util.ArrayList;&nbsp; <br />&nbsp;&nbsp;&nbsp; import java.util.List;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSON;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONObject;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONSerializer; <br />&nbsp;&nbsp;&nbsp; //import WorkRecord;</p>
<p>import java.sql.*; <br />public class faq { <br />String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; <br />String sConnStr = "jdbc:odbc:wz"; <br />Connection conn = null; <br />ResultSet rs = null; <br />JSON json;<br />public faq() { <br />try { <br />Class.forName(sDBDriver); <br />}catch(java.lang.ClassNotFoundException e) { <br />System.err.println("faq(): " + e.getMessage()); <br />} <br />} </p>
<p>public&nbsp; void executeQuery(String sql)<br />&nbsp;{ <br />rs = null; <br />try { <br />conn = DriverManager.getConnection(sConnStr,"liuyz","liuyz1"); <br />Statement stmt = conn.createStatement(); <br />rs = stmt.executeQuery(sql); <br /><span style="color: red">//List result =new ArrayList();</span></p>
<p><span style="color: red">&nbsp;List&lt;WorkRecord&gt; result = new ArrayList&lt;WorkRecord&gt;();&nbsp; </span></p>
<p>while (rs.next())<br />&nbsp;{<br />&nbsp;WorkRecord rec= new WorkRecord();<br />&nbsp;rec.setdo_seq(rs.getLong("do_seq"));<br />&nbsp;rec.setproc_name(rs.getString("proc_name"));<br />&nbsp;rec.setsql_desc(rs.getString("sql_desc"));<br />&nbsp;rec.setwork_status(rs.getString("work_status"));<br />&nbsp;result.add(rec);<br />&nbsp;}<br />&nbsp;//JSONObject json= JSONSerializer.toJSON(result);<br />&nbsp; json = JSONSerializer.toJSON(result); </p>
<p>}<br />catch(SQLException ex) <br />{ <br />System.err.println("aq.executeQuery: " + ex.getMessage()); <br />} </p>
<p>//return json.toString();<br />System.out.println(json.toString()); </p>
<p>} </p>
<p>public static void main (String[] args)<br />{<br />&nbsp;faq aaa =new faq();<br />aaa.executeQuery("select * from work_log where do_seq=399252 or do_seq=399261 ");<br />}</p>
<p>} </p>
<p><br />1、在c:\下解压json支持库生成 org net 目录<br />2、在c:\下编写前面两个文件<br />3、javac WorkRecord.java ; javac faq.java<br />4、java faq 运行后返回以下json 格式的数据<br /><br />[{"do_seq":399252,"proc_name":"LIUYZ.GET_GD\n","sql_desc":"delete from&nbsp; busi_log<br />&nbsp;a where\nbusiness_id&nbsp;&nbsp; in (500000020057,8000100108,500000020204,800015100004,80<br />0015100003,800015100002,800015100008,800015100005,800015100006,800015100000,8000<br />100100,8000100126,500000020055,500000020053,8000000015,8000000012,800015101178,5<br />00000021011,800015101251,500000021012,500000020222,500000020223,500000020038,500<br />000020093,500000020094,360,500000020064,500000020339,500000020079,500000020009,5<br />00000020006,2100000003,8000100103,500000020028,500000020007,500000020012,5000000<br />20221,500000020220,500000020073,500000020074,8000000620,500000020320,50000002020<br />3,900000030001,500000020076,500000020077,8000000021,8100000987,500000020008,5000<br />00020096,2100000004,8000000002,8000000005)","work_status":"finished"},{"do_seq":<br />399261,"proc_name":"LIUYZ.GET_GD\n","sql_desc":"delete from&nbsp; yz_gd where&nbsp; fee_de<br />tail like '%终端差价%'","work_status":"finished"}]<br /><br />注：<br /><span style="color: red">//List result =new ArrayList();</span> </p>
<p><span style="color: red">&nbsp;List&lt;WorkRecord&gt; result = new ArrayList&lt;WorkRecord&gt;();&nbsp; </span></p>
<p><span style="color: red">编译正常</span><br /><span style="color: red">如改为</span><br /><span style="color: red">List result =new ArrayList();</span> </p>
<p><span style="color: red">//&nbsp;List&lt;WorkRecord&gt; result = new ArrayList&lt;WorkRecord&gt;();&nbsp; <br /></span></p>
<p><span style="color: red">编译出现下面信息</span><br /><span style="color: red">C:\&gt;javac faq.java</span><br /><span style="color: red">注意：faq.java 使用了未经检查或不安全的操作。</span><br /><span style="color: red">注意：要了解详细信息，请使用 -Xlint:unchecked 重新编译。</span><br /><span style="color: red">但运行正常，仍能产生json格式的数据</span><br /><br /></p><img src ="http://www.blogjava.net/liuyz2006/aggbug/367954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-01-05 22:00 <a href="http://www.blogjava.net/liuyz2006/articles/367954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java对象生成json实例</title><link>http://www.blogjava.net/liuyz2006/articles/367945.html</link><dc:creator>阿者</dc:creator><author>阿者</author><pubDate>Thu, 05 Jan 2012 12:28:00 GMT</pubDate><guid>http://www.blogjava.net/liuyz2006/articles/367945.html</guid><wfw:comment>http://www.blogjava.net/liuyz2006/comments/367945.html</wfw:comment><comments>http://www.blogjava.net/liuyz2006/articles/367945.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/liuyz2006/comments/commentRss/367945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuyz2006/services/trackbacks/367945.html</trackback:ping><description><![CDATA[<div class="blog_mode_text mb20" id="previewcontent">
<p>
<p>&nbsp;</p>
<p>1、不带包的使用方式<br /><br />解压json和支持包在当前目录下生成 </p>
<p>org</p>
<p>net</p>
<p>javac User.java</p>
<p>javac Test.java</p>
<p>java Test&nbsp; 输出</p>
<p>{"age":25,"name":"phl"}</p>
<p>[{"age":25,"name":"phl"},{"age":26,"name":"luckybird"}]</p>
<p>{"age":0,"name":""}<br /></p>
<p><br /><br />------------------User.java-----------------</p>
<p>public class User<br />{<br />private String name;<br />private int age;</p>
<p>public String getName()<br />{<br />return this.name;<br />}</p>
<p>public&nbsp; int getAge(){<br />return this.age;</p>
<p>}</p>
<p>public void setName(String v_name)<br />{<br />this.name=v_name;<br />}</p>
<p>public void setAge(int v_age)<br />{<br />this.age=v_age;<br />}<br />}</p>
<p>---------------Test.java------------------</p>
<p>&nbsp;&nbsp;&nbsp; import java.util.ArrayList;&nbsp; <br />&nbsp;&nbsp;&nbsp; import java.util.List;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSON;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONObject;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONSerializer;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public class Test {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User user = new User();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setName("phl");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setAge(25);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User user2 = new User();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user2.setName("luckybird");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user2.setAge(26);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;User&gt; list = new ArrayList&lt;User&gt;();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(user);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(user2);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONObject json = JSONObject.fromObject(user);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ********************************************************&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSON json2 = JSONSerializer.toJSON(list);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json2.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; json2 = JSONSerializer.toJSON(new User());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json2.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; </p>
<p>&nbsp;</p>
<p>=====================================================================<br />2、带包的使用方式</p>
<p>------------------User.java-----------------<br /><span style="color: red">package nn;</span><br /></p>
<p>public class User<br />{<br />private String name;<br />private int age;</p>
<p>public String getName()<br />{<br />return this.name;<br />}</p>
<p>public&nbsp; int getAge(){<br />return this.age;</p>
<p>}</p>
<p>public void setName(String v_name)<br />{<br />this.name=v_name;<br />}</p>
<p>public void setAge(int v_age)<br />{<br />this.age=v_age;<br />}<br />}<br /></p>
<p><br />---------------Test.java------------------<br /><span style="color: red">&nbsp;package mm;</span><br /></p>
<p>&nbsp;&nbsp;&nbsp; import java.util.ArrayList;&nbsp; <br />&nbsp;&nbsp;&nbsp; import java.util.List;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSON;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONObject;&nbsp; <br />&nbsp;&nbsp;&nbsp; import net.sf.json.JSONSerializer;&nbsp;&nbsp;<br /><span style="color: red">&nbsp;&nbsp;&nbsp; import nn.User;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; public class Test {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User user = new User();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setName("phl");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user.setAge(25);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User user2 = new User();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user2.setName("luckybird");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user2.setAge(26);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&lt;User&gt; list = new ArrayList&lt;User&gt;();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(user);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(user2);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSONObject json = JSONObject.fromObject(user);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ********************************************************&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JSON json2 = JSONSerializer.toJSON(list);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json2.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; json2 = JSONSerializer.toJSON(new User());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(json2.toString());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; </p>
<p>==================<br />javac User.java -&gt;User.class<br />javac Test.java -&gt;Test.class<br />拷贝User.class-&gt;nn目录下 ;Test.class-&gt;mm目录下<br />调用方式java mm.Test<br /><br />{"age":25,"name":"phl"}<br />[{"age":25,"name":"phl"},{"age":26,"name":"luckybird"}]<br />{"age":0,"name":""}<br /><br /><br /><br /></p></div><img src ="http://www.blogjava.net/liuyz2006/aggbug/367945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuyz2006/" target="_blank">阿者</a> 2012-01-05 20:28 <a href="http://www.blogjava.net/liuyz2006/articles/367945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>