﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-落雪的梦想-随笔分类-Java</title><link>http://www2.blogjava.net/gufen/category/3587.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 14:51:35 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 14:51:35 GMT</pubDate><ttl>60</ttl><item><title>JDK5.0的11个主要新特征</title><link>http://www.blogjava.net/gufen/archive/2005/10/15/15567.html</link><dc:creator>落花飞雪</dc:creator><author>落花飞雪</author><pubDate>Sat, 15 Oct 2005 04:15:00 GMT</pubDate><guid>http://www.blogjava.net/gufen/archive/2005/10/15/15567.html</guid><wfw:comment>http://www.blogjava.net/gufen/comments/15567.html</wfw:comment><comments>http://www.blogjava.net/gufen/archive/2005/10/15/15567.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gufen/comments/commentRss/15567.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gufen/services/trackbacks/15567.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 泛型(Generic)1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明增强了java的类型安全，可以在编译期间对容器内的对象进行类型检查，在运行期不必进行类型的转换。而在j2se5之前必须在运行期...&nbsp;&nbsp;<a href='http://www.blogjava.net/gufen/archive/2005/10/15/15567.html'>阅读全文</a><img src ="http://www.blogjava.net/gufen/aggbug/15567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gufen/" target="_blank">落花飞雪</a> 2005-10-15 12:15 <a href="http://www.blogjava.net/gufen/archive/2005/10/15/15567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win32下Swt-Designer4.1.1与MyEclipse4.0的破解方法及注册机</title><link>http://www.blogjava.net/gufen/archive/2005/09/27/14184.html</link><dc:creator>落花飞雪</dc:creator><author>落花飞雪</author><pubDate>Tue, 27 Sep 2005 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/gufen/archive/2005/09/27/14184.html</guid><wfw:comment>http://www.blogjava.net/gufen/comments/14184.html</wfw:comment><comments>http://www.blogjava.net/gufen/archive/2005/09/27/14184.html#Feedback</comments><slash:comments>44</slash:comments><wfw:commentRss>http://www.blogjava.net/gufen/comments/commentRss/14184.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gufen/services/trackbacks/14184.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>Win32</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下</SPAN><SPAN lang=EN-US>Swt-Designer<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">4.1.1</st1:chsdate></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">破解</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境：</SPAN><SPAN lang=EN-US>win32</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Eclipse3.1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Designer_v<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">4.1.1</st1:chsdate></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">1．<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先去</SPAN><SPAN lang=EN-US><A href="http://www.swt-designer.com/">http://www.swt-designer.com/</A></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">左边的</SPAN><SPAN lang=EN-US>download</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">菜单点击进去后下载</SPAN><SPAN lang=EN-US>Edition for Eclipse 3.1 &amp; 3.2</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，下载后的文件名为</SPAN><SPAN lang=EN-US>Designer_v<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">4.1.1</st1:chsdate>_for_Eclipse3.1.zip<IMG height=283 alt=Snap2.gif src="http://www.blogjava.net/images/blogjava_net/gufen/001.swt.myeclipse.crack/Snap2.gif" width=606 border=0><BR></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt"><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2．<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">然后在我的网络硬盘中下载破解文件</SPAN><SPAN lang=EN-US>: <A href="http://www.thefilehut.com/userfiles/gufen/forblog/swt.designer.pro.keygen.for.eclipse.3.1.rar">http://www.thefilehut.com/userfiles/gufen/forblog/swt.designer.pro.keygen.for.eclipse.3.1.rar</A></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">3．<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解压后在</SPAN><SPAN lang=EN-US>cmd</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令中敲入</SPAN><SPAN lang=EN-US>swt.ui.bat</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，运行后出现以下界面，输入框中的内容，然后点击</SPAN><SPAN lang=EN-US>Generate</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">产生序列号和激活码。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: 21pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><IMG height=241 alt=Snap3.gif src="http://www.blogjava.net/images/blogjava_net/gufen/001.swt.myeclipse.crack/Snap3.gif" width=377 border=0><BR>如果你所使用的环境和版本不是</SPAN><SPAN lang=EN-US>win32</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Eclipse3.1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Designer_v<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">4.1.1</st1:chsdate></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，请参照</SPAN><SPAN lang=EN-US><A href="http://blog.chinaz.com/u1/530/archives/2005/1789.shtml">http://blog.chinaz.com/u1/530/archives/2005/1789.shtml</A></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来进行破解。这种情况下需要：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 45pt; TEXT-INDENT: -9pt; mso-list: l2 level2 lfo2; tab-stops: list 45.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">a)<SPAN style="FONT: 7pt 'Times New Roman'"> </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将该目录下的</SPAN><SPAN lang=EN-US>org.eclipse.swt.win32.win32.x86_<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">3.1.0</st1:chsdate>.jar</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US>swt-win32-3138.dll</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">删除</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 45pt; TEXT-INDENT: -9pt; mso-list: l2 level2 lfo2; tab-stops: list 45.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">b)</SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</SPAN><SPAN lang=EN-US>Eclipse</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录下找到</SPAN><SPAN lang=EN-US>swt.jar</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（名字视版本而定，</SPAN><SPAN lang=EN-US>eclipse3.1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下是</SPAN><SPAN lang=EN-US>org.eclipse.swt.win32.win32.x86_<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">3.1.0</st1:chsdate>.jar</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN> <SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US>swt-win32-2135.dll</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（名字视版本而定，</SPAN><SPAN lang=EN-US>eclipse3.1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下是</SPAN><SPAN lang=EN-US>swt-win32-3138.dll</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个文件，拷贝到</SPAN><SPAN lang=EN-US>swt.ui.bat</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所在的目录。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 45pt; TEXT-INDENT: -9pt; mso-list: l2 level2 lfo2; tab-stops: list 45.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">c)</SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修改</SPAN><SPAN lang=EN-US>swt.ui.bat,</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如这样：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 21pt; mso-para-margin-left: 3.43gd"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">原来是</SPAN><SPAN lang=EN-US>: start javaw -cp SWTDesigner_<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">2.0.0</st1:chsdate>_Keygen.jar;<SPAN style="COLOR: red">org.eclipse.swt.win32.win32.x86_3.1.0.jar</SPAN> swtdesigner.keygen.SWTUI</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 21pt; mso-para-margin-left: 3.43gd"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修改为</SPAN><SPAN lang=EN-US>:start javaw -cp SWTDesigner_<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">2.0.0</st1:chsdate>_Keygen.jar;<SPAN style="COLOR: red">swt.jar</SPAN> swtdesigner.keygen.SWTUI</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 36pt; TEXT-INDENT: 21pt; mso-para-margin-left: 3.43gd"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">红色为修改的地方，然后运行后将</SPAN><SPAN lang=EN-US>Version</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">填入你下载的</SPAN><SPAN lang=EN-US>swt-designer</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">版本号即可产生注册码。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 18pt"><SPAN lang=EN-US></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo3; tab-stops: list 21.0pt"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">4.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将下载的</SPAN><SPAN lang=EN-US>Designer_v<st1:chsdate Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False" w:st="on">4.1.1</st1:chsdate>_for_Eclipse3.1.zip</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">插件安装到</SPAN><SPAN lang=EN-US>eclipse,</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果你不知道如何安装插件请在</SPAN><SPAN lang=EN-US>google</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里搜索这方面的文章，应该很多的。我也是这样走过来的。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行</SPAN><SPAN lang=EN-US>eclipse,</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打开</SPAN><SPAN lang=EN-US>window-&gt;preferences…-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">选择左边树形中的</SPAN><SPAN lang=EN-US>designer(</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果没有这一项说明</SPAN><SPAN lang=EN-US>swt-designer</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">插件没有安装成功</SPAN><SPAN lang=EN-US>)</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN><SPAN lang=EN-US>-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">点击右下的“</SPAN><SPAN lang=EN-US>Registration and Activation</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”</SPAN><SPAN lang=EN-US>-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">弹出“</SPAN><SPAN lang=EN-US>Product Registration and Activation</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”框，用默认直接点击</SPAN><SPAN lang=EN-US>Next-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这一步需要注意的是</SPAN><SPAN lang=EN-US>Name</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">框中两个字符串之间要有个空格，他会认为一个是姓一个是名，否则</SPAN><SPAN lang=EN-US>Next</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮一直是灰的，其他随便填，</SPAN><SPAN lang=EN-US>email</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">框中要合乎</SPAN><SPAN lang=EN-US>email</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">格式就可以了</SPAN><SPAN lang=EN-US>-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">输入破解产生的序列号和激活码</SPAN><SPAN lang=EN-US>-&gt;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">显示“</SPAN><SPAN lang=EN-US>Activation is complete. Thank you.</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”表示破解成功</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">现在就可以免费使用</SPAN><SPAN lang=EN-US>swt-designer</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">了</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>Win32</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下</SPAN><SPAN lang=EN-US>MyEclipse4.0</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">破解</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个破解起来很简单，先去</SPAN><SPAN lang=EN-US>http://www.myeclipseide.com</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下载</SPAN><SPAN lang=EN-US>Myeclipse4.0,</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">然后去</SPAN><SPAN lang=EN-US><A href="http://www.thefilehut.com/userfiles/gufen/forblog/MyEclipse-4.0.0-GA.Keygen.zip">http://www.thefilehut.com/userfiles/gufen/forblog/MyEclipse-4.0.0-GA.Keygen.zip</A></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下载破解。安装</SPAN><SPAN lang=EN-US>Myeclipse,</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之后解压破解文件后运行</SPAN><SPAN lang=EN-US>keygen.bat</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，产生一个</SPAN><SPAN lang=EN-US>key</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，之后在</SPAN><SPAN lang=EN-US>Myeclipse</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">注册一下就可以了。<SPAN lang=EN-US>Myeclipse我忘记什么地方注册了，好像装好<SPAN lang=EN-US>Myeclipse后在preferences中的<SPAN lang=EN-US>Myeclipse里点几下就会弹出来个框，把key copy过去确认就可以了。<BR><BR>以上破解方法仅供个人学习，请支持正版。(形式？)</SPAN></SPAN></SPAN></SPAN></P><img src ="http://www.blogjava.net/gufen/aggbug/14184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gufen/" target="_blank">落花飞雪</a> 2005-09-27 13:05 <a href="http://www.blogjava.net/gufen/archive/2005/09/27/14184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Effective Java》笔记(选择自 njchenyi 的 Blog)</title><link>http://www.blogjava.net/gufen/archive/2005/09/25/13993.html</link><dc:creator>落花飞雪</dc:creator><author>落花飞雪</author><pubDate>Sun, 25 Sep 2005 07:24:00 GMT</pubDate><guid>http://www.blogjava.net/gufen/archive/2005/09/25/13993.html</guid><wfw:comment>http://www.blogjava.net/gufen/comments/13993.html</wfw:comment><comments>http://www.blogjava.net/gufen/archive/2005/09/25/13993.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gufen/comments/commentRss/13993.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gufen/services/trackbacks/13993.html</trackback:ping><description><![CDATA[<DIV>有别人写好的笔记，不用自己费神写了。对于看过Effective Java的偶而忘记某个条目，看看笔记或许能记起来。</DIV>
<DIV>&nbsp;</DIV>
<DIV>Creating and Destroying Object</DIV>
<DIV>Item 1:考虑用静态工厂方法替代构造器<BR>例如：public static Boolean valueOf(boolean b)<BR>&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (b?Boolean.TRUE:Boolean.FALSE);<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>这样的好处是方法有名字，并且它可以复用对象，不像构造器每次调用都产生新的对象。其次它还可以返回返回类型的子类。不好的地方是如果没有public or protected构造器的类将不能被继承。还有就是静态工厂方法的名字和其他的静态方法名字不容易区分。</DIV>
<DIV>Item 2:通过添加私有构造器来加强单例属性（singletom property)<BR>例如：public class Hello<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final Hello Instance = new Hell();</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Hello()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static Hello getInstance()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Instance;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>这个私有构造器只能在内部被使用，确保了单例模式！<BR>Item 3:避免创建重复的对象<BR>对不可修改的对象尽量进行复用，这样效率和性能都会提高。例如如果循环100次String s = new String("hello")将创建100个对象 循环100次String s = "hello";则只创建了一个对象。很好的进行了复用。</DIV>
<DIV>Item 4:用私有构造器来避免被实例化<BR>例如public UtilityClass<BR>{<BR>&nbsp;&nbsp; private UtilityClass()<BR>&nbsp;&nbsp; {}</DIV>
<DIV>///<BR>}<BR>通常那些工具类是这么设计的</DIV>
<DIV>Item 5:消除绝对的对象引用<BR>&nbsp;&nbsp;&nbsp;&nbsp; 虽然java中使用gc来管理内存，但是如果不注意的话也会产生“内存泄漏”。例如下面的程序<BR>public class Stack<BR>{<BR>&nbsp;private Object[] elements;<BR>&nbsp;private int size = 0;<BR>&nbsp;<BR>&nbsp;public Stack(int i)<BR>&nbsp;{<BR>&nbsp; this.elements = new Object[i]; <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void push(Object e)<BR>&nbsp;{<BR>&nbsp; ensure();<BR>&nbsp; elements[size++] = e; <BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public Object pop()<BR>&nbsp;{<BR>&nbsp; if(size == 0)<BR>&nbsp; {<BR>&nbsp;&nbsp; //// <BR>&nbsp; } <BR>&nbsp; <BR>&nbsp; return elements[size--];<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;private void ensure()<BR>&nbsp;{<BR>&nbsp; //// <BR>&nbsp;}<BR>}<BR>标记的地方存在着内存泄漏的问题，因为当他被弹出栈的时候，它也没有成为可回收的垃圾对象，Stack维护着他们的绝对的引用。将不能更改。改进的方法是如下的写法<BR>&nbsp;public Object pop()<BR>&nbsp;{<BR>&nbsp; if(size == 0)<BR>&nbsp; {<BR>&nbsp;&nbsp; //// <BR>&nbsp; } <BR>&nbsp; Object obj = elements[--size];<BR>&nbsp; elements[size] = null;<BR>&nbsp; <BR>&nbsp; return obj;<BR>&nbsp;}<BR>&nbsp;但是切忌不要滥用null。</DIV>
<DIV>Item 6:避免finalizer<BR>垃圾回收器是低线程级别运行的且不能被强迫执行。System.gc()只是建议垃圾回收器收集垃圾，它可不一定马上运行，而且垃圾回收器运行的时候会挂起其他线程导致程序停止响应。推荐使用的方法类似于<BR>InputStream is = null;</DIV>
<DIV>try<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is = /////;<BR>}<BR>finally<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();<BR>}</DIV>
<DIV>Methods Common to All Objects</DIV>
<DIV>item 7:当你覆盖equals方法的时候一定要遵守general contact<BR>&nbsp;&nbsp; 覆盖equals的时候一定要加倍的小心，其实最好的办法就是不覆盖这个方法。比如在下面的情况下就可以不覆盖</DIV>
<DIV>&nbsp;&nbsp; 1这个类的每个实例都是唯一的，例如Thread类</DIV>
<DIV>&nbsp;&nbsp; 2 如果你不关心这个类是否该提供一个测试逻辑相等的方法</DIV>
<DIV>&nbsp;&nbsp; 3超类已经覆盖了equals方法，并且它合适子类使用</DIV>
<DIV>&nbsp;&nbsp; 4如果这个类是private或者是package-private的，并且你确信他不会被调用</DIV>
<DIV>&nbsp;&nbsp; 但是当我们要为这个类提供区分逻辑相等和引用相等的方法的时候，我们就必须要覆盖这个方法了。例如String类，Date类等，覆盖的时候我们一定要遵从general contact，说白了就是一个合同。合同的主要内容是<BR>&nbsp;&nbsp; 1．x.equals(x)必须返回true<BR>&nbsp;&nbsp; 2．x.equals（y）当且仅当y.equals(x)返回true的时候返回true<BR>&nbsp;&nbsp; 3．x.equals(y)返回true，y.equals(z)返回true,那么x.equals(z)必须返回true<BR>&nbsp;&nbsp; 4.如果没有任何修改得话 那么多次调用x.equals(y)的返回值应该不变<BR>&nbsp;&nbsp; 5．任何时候非空的对象x,x.equals(null)必须返回false</DIV>
<DIV>下面是作者的建议如何正确的覆盖equals方法<BR>1．&nbsp; 用==检查是否参数就是这个对象的引用<BR>2．&nbsp; 用instanceof判断参数的类型是否正确<BR>3．&nbsp; 把参数转换成合适的类型<BR>4．&nbsp; 比较类的字段是不是匹配</DIV>
<DIV>例如：<BR>public boolean equals(Object o)</DIV>
<DIV>{</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(o== this) return true;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(o instanceof xxxx) return false;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xxx in = (xxx)o;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ……..</DIV>
<DIV>}</DIV>
<DIV>最后一点要注意的时候不要提供这样的方法public boolean equals(MyClass o)这样是重载并不是覆盖Object的equals方法</DIV>
<DIV>item 8 :当你覆盖equals的时候必须覆盖hashCode方法<BR>&nbsp;&nbsp;&nbsp; 这点必须切忌，不然在你和hash-based集合打交道的时候，错误就会出现了。关键问题在于一定要满足相等的对象必须要有相等的hashCode。如果你在PhoneNumber类中覆盖了equals方法，但是没有覆盖hashCode方法，那么当你做如下操作的时候就会出现问题了。<BR>Map m = new HashMap();<BR>m.put(new PhoneNumber(408,863,3334),”ming”)<BR>当你调用m.get(new PhoneNumber(408,863,3334))的时候你希望得到ming但是你却得到了null,为什么呢因为在整个过程中有两个PhoneNumber的实例，一个是put一个是get，但是他们两个逻辑相等的实例却得到不同的hashCode那么怎么可以取得以前存入的ming呢。</DIV>
<DIV>&nbsp;</DIV>
<DIV>Item 9:永远覆盖toString方法<BR>&nbsp;&nbsp;&nbsp; 在Object的toString方法返回的形式是Class的类型加上@加上16进制的hashcode。你最好在自己的类中提供toString方法更好的表述实例的信息，不然别人怎么看得明白呢。</DIV>
<DIV>Item 10:覆盖clone()方法的时候一定要小心<BR>&nbsp;&nbsp;&nbsp; 一个对象要想被Clone，那么要实现Clone()接口，这个接口没有定义任何的方法，但是如果你不实现这个接口的话，调用clone方法的时候会出现CloneNotSupportedException，这就是作者叫做mixin的接口类型。通常clone()方法可以这样覆盖</DIV>
<DIV>public Object clone()</DIV>
<DIV>{</DIV>
<DIV>try<BR>{</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.clone();</DIV>
<DIV>}</DIV>
<DIV>catch(CloneNotSupportedException e)<BR>{}</DIV>
<DIV>}</DIV>
<DIV>但是当你要clone的类里面含有可修改的引用字段的时候，那么你一定要把整个类的蓝图进行复制，如果对你clone得到的对象进行修改的时候还会影响到原来的实例，那么这是不可取的。所以应该这样clone()</DIV>
<DIV>public Object clone() throws CloneNotSupportedException</DIV>
<DIV>{</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stack Result&nbsp; = (Stack)super.clone();</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result.elements = (Object[])elements.clone();</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return result;</DIV>
<DIV>}</DIV>
<DIV>其中elements是stack类中可修改的引用字段，注意如果elements是final的话我们就无能为力了，因为不能给他重新赋值了.其实如果不是必须的话，根本就不用它最好。</DIV>
<DIV>&nbsp;</DIV>
<DIV>Item 11:考虑适当的时候覆盖Comparable接口<BR>&nbsp;&nbsp;&nbsp;&nbsp; Thinking in java上说的更清楚，这里不多少了。</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 越来越发现这是一本难得的好书，Java程序员不看这本书的话真是很遗憾。本章讲述的是类和接口相关的问题。这几个Item都非常重要. </DIV>
<DIV>Item 12：把类和成员的可访问范围降到最低<BR>&nbsp;&nbsp;&nbsp; 好的模块设计应该尽最大可能封装好自己的内部信息，这样可以把模块之间的耦合程度降到最低。开发得以并行，无疑这将加快开发的速度，便于系统地维护。Java中通过访问控制符来解决这个问题。</DIV>
<DIV>public表示这个类在任何范围都可用。 <BR>protected表示只有子类和包内的类可以使用 <BR>private-package(default)表示在包内可用 <BR>private表示只有类内才可以用<BR>你在设计一个类的时候应该尽量的按照4321得顺序设计。如果一个类只是被另一个类使用，那么应该考虑把它设计成这个类的内部类。通常public的类不应该有public得字段，不过我们通常会用一个类来定义所有的常量，这是允许的。不过必须保证这些字段要么是基本数据类型要么引用指向的对象是不可修改的。不然他们将可能被修改。例如下面的定义中data就是不合理的，后面两个没有问题。<BR>public class Con<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int[] data = {1,2,3};// it is bad<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final String hello = "world";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int i = 1;<BR>}</DIV>
<DIV>Item 13:不可修改的类更受青睐</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 不可修改的类意思是他们一经创建就不会改变，例如String类。他们的设计、实现都很方便，安全性高——它们是线程安全的。设计不可修改类有几点规则：</DIV>
<DIV>不要提供任何可以修改对象的方法 <BR>确保没有方法能够被覆盖，可以通过把它声明为final <BR>所有字段设计成final <BR>所有字段设计成private <BR>确保外部不能访问到类的可修改的组件<BR>不可修改类也有个缺点就是创建不同值得类的时候要创建不同的对象，String就是这样的。通常有个解决的办法就是提供一个帮助类来弥补，例如StringBuffer类。<BR>Item 14:化合(合成）比继承更值得考虑</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实现代码重用最重要的办法就是继承，但是继承破坏了封装，导致软件的键壮性不足。如果子类继承了父类，那么它从父类继承的方法就依赖父类的实现，一旦他改变了会导致不可预测的结果。作者介绍了InstrumentedHashSet作为反例进行说明，原因就是没有明白父类的方法实现。作者给出的解决办法是通过化合来代替继承，用包装类和转发方法来解决问题。把想扩展的类作为本类的一个private final得成员变量。把方法参数传递给这个成员变量并得到返回值。这样做的缺点是这样的类不适合回掉框架。继承虽然好，我们却不应该滥用，只有我们能确定它们之间是is-a得关系的时候才使用。</DIV>
<DIV>Item 15:如果要用继承那么设计以及文档都要有质量保证，否则就不要用它</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 为了避免继承带来的问题，你必须提供精确的文档来说明覆盖相关方法可能出现的问题。在构造器内千万不要调用可以被覆盖的方法，因为子类覆盖方法的时候会出现问题。<BR>import java.util.*;</DIV>
<DIV>public class SubClass extends SuperClass<BR>{<BR>&nbsp;private final Date date;<BR>&nbsp;<BR>&nbsp;public SubClass()<BR>&nbsp;{<BR>&nbsp; date = new Date(); <BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void m()<BR>&nbsp;{<BR>&nbsp; System.out.println(date); <BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public static void main(String[] args)<BR>&nbsp;{<BR>&nbsp; SubClass s = new SubClass();<BR>&nbsp; s.m(); <BR>&nbsp;}<BR>&nbsp;<BR>}</DIV>
<DIV>class SuperClass<BR>{<BR>&nbsp;public SuperClass()<BR>&nbsp;{<BR>&nbsp; m(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void m()<BR>&nbsp;{<BR>&nbsp; <BR>&nbsp;}<BR>}<BR>由于在date被初始化之前super（）已经被调用了，所以第一次输出null而不是当前的时间。<BR>由于在Clone()或者序列化的时候非常类似构造器的功能，因此readObject()和clone（）方法内最好也不要包括能被覆盖的方法。</DIV>
<DIV>Item 16:在接口和抽象类之间优先选择前者</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口和抽象类都用来实现多态，不过我们应该优先考虑用接口。知道吗？James说过如果要让他重新设计java的话他会把所有都设计成接口的。抽象类的优点是方便扩展，因为它是被继承的，并且方法可以在抽象类内实现，接口则不行。</DIV>
<DIV>Item 17：接口只应该用来定义类型</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口可以这样用的 Collection c = new xxxx();这是我们最常用的。不要把接口用来做其他的事情，比如常量的定义。你应该定义一个类，里面包含public final static 得字段。</DIV>
<DIV>Item 18: 在静态和非静态内部类之间选择前者</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果一个类被定义在其他的类内部那么它就是嵌套类，可以分为静态内部类、非静态内部类和匿名类。<BR>&nbsp;&nbsp; static member class 得目的是为enclosing class服务，如果还有其他的目的，就应该把它设计成top-level class。nonstatic member class是和enclosing class instance关联的，如果不需要访问enclosing class instance的话应该把它设计成static得，不然会浪费时间和空间。anonymous class是声明和初始化同时进行的。可以放在代码的任意位置。典型应用是Listener 和process object例如Thread。</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 由于以前学过C语言，所以对C还是蛮有感情，而JAVA和C又有很多相似之处，很多从C转过来学习JAVA的兄弟，可能一开始都不是很适应，因为很多在C里面的结构在JAVA里面都不能使用了，所以下面我们来介绍一下C语言结构的替代。</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Item 19:用类代替结构<BR>&nbsp;&nbsp;&nbsp;&nbsp; JAVA刚面世的时候，很多C程序员都认为用类来代替结构现在太复杂，代价太大了，但是实际上，如果一个JAVA的类退化到只包含一个数据域的话，这样的类与C语言的结构大致是等价的。</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 比方说下面两个程序片段：</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Point<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实际上这段代码和C语言的结构基本上没什么区别，但是这段代码恐怕是众多OO设计Fans所不齿的，因为它没有体现封装的优异性，没有体现面向对象设计的优点，当一个域被修改的时候，你不可能再采取任何辅助的措施了，那我们再来看一看采用包含私有域和共有访问方法的OO设计代码段：<BR>&nbsp;&nbsp;&nbsp;&nbsp; class Point<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Point(float x,float y)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x=x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y=y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public float getX(){retrun x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public float getY(){return y;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setX(float x){this.x=x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setY(float y){this.y=y;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单从表面上看，这段代码比上面那个多了很多行，还多了很多函数，但是仔细想一下，这样的OO设计，似乎更人性化，我们可以方面的对值域进行提取，修改等操作，而不直接和值域发生关系，这样的代码不仅让人容易读懂，而且很安全，还吸取了面向对象程序设计的灵活性，试想一下，如果一个共有类暴露它的值域，那么想要在将来的版本中进行修改是impossible的，因为共有类的客户代码已经遍布各处了。<BR>需要提醒一点的是，如果一个类是包级私有的，或者是一个私有的嵌套类，则直接暴露其值域并无不妥之处。</DIV>
<DIV>Item 20：用类层次来代替联合<BR>我们在用C语言来进行开发的时候，经常会用到联合这个概念，比如：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct{<BR>&nbsp;&nbsp;&nbsp;&nbsp; double length;<BR>&nbsp;&nbsp;&nbsp;&nbsp; double width;&nbsp;&nbsp;&nbsp;&nbsp; <BR>}rectangleDimensions_t;</DIV>
<DIV>那我们在JAVA里面没有联合这个概念，那我们用什么呢？对！用继承，这也是JAVA最吸引我的地方之一，它可以使用更好的机制来定义耽搁数据类型，在Bruce Eckel的Thinking in java里面也多次提到了一个和形状有关的例子，我们可以先笼统的定义一个抽象类，即我们通常所指的超类，每个操作定义一个抽象的方法，其行为取决于标签的值，如果还有其他的操作不依赖于标签的值，则把操作变成根类（继承的类）中的具体方法。<BR>这样做的最重要的优点是：类层次提供了类型的安全性。<BR>其次代码非常明了，这也是OO设计的优点。<BR>而且它很容易扩展，即使是面向多个方面的工作，能够同样胜任。<BR>最后它可以反映这些类型之间本质上的层次关系，从而允许更强的灵活性，以便编译时类型检查。</DIV>
<DIV>Item 21：用类来代替enum结构<BR>Java程序设计语言提出了类型安全枚举的模式来替代enum结构，它的基本思想很简单：定义一个类来代表枚举类型的单个元素，并且不提供任何公有的构造函数，相反，提供公有静态final类，使枚举类型中的每一个常量都对应一个域。<BR>类型安全枚举类型的一个缺点是，装载枚举类的和构造常量对象时，需要一定的时间和空间开销，除非是在资源很受限制的设备比如蜂窝电哈和烤面包机上，否则在实际中这个问题不会被考虑。<BR>&nbsp;总之，类型安全枚举类型明显优于int类型，除非实在一个枚举类型主要被用做一个集合元素，或者主要用在一个资源非常不受限的环境下，否则类型安全枚举类型的缺点都不成问题，依次，在要求使用一个枚举类型的环境下，我们首先应考虑类型安全枚举类型模式。</DIV>
<DIV>Item 22：用类和接口来代替函数指针<BR>众所周知，JAVA语言和C的最大区别在于，前者去掉了指针，小生第一次接触JAVA的时候觉得好不习惯，因为突然一下子没了指针，觉得好不方面啊，C语言的精髓在于其指针的运用，而JAVA却把它砍掉了，让人好生郁闷，不过随着时间的推移，我渐渐明白了用类和接口的应用也同样可以提供同样的功能，我们可以直接定义一个这样一个类，他的方法是执行其他方法上的操作，如果一个类仅仅是导出这样一个方法，那么它实际上就是一个指向该方法的指针，举个例子：<BR>class StringLengthComprator{<BR>public int compare(String s1,String s2)<BR>{<BR>return s1.length()-s2.length();<BR>}<BR>}<BR>这个类导出一个带两个字符串的方法，它是一个用于字符串比较的具体策略。它是无状态的，没有域，所以，这个类的所有实例在功能上都是等价的，可以节省不必要的对象创建开销。但是我们不好直接把这个类传递给可户使用，因为可户无法传递任何其他的比较策略。相反，我们可以定义一个接口，即我们在设计具体策略类的时候还需要定义一个策略接口：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public interface Comparator{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object o1,Object o2);<BR>}<BR>&nbsp; 我们完全可以依照自己的需要来定义它。<BR>具体的策略类往往使用匿名类声明。<BR>在JAVA中，我们为了实现指针的模式，声明一个接口来表示该策略，并且为每个具体策略声明一个实现了该接口的类，如果一个具体策略只被使用一次的话，那么通常使用匿名类来声明和实例化这个具体策略类，如果一个策略类反复使用，那么它的类通常是一个私有的的静态成员类。 <BR>下面我们来讨论一下有关方法设计的几个方面，下面说的几个要点大多数都是应用在构造函数中，当然也使用于普通方法，我们追求的依然是程序的可用性，健壮性和灵活性。</DIV>
<DIV>Item 23：检查参数的有效性</DIV>
<DIV>非公有的方法我们应该用断言的方法来检查它的参数，而不是使用通常大家所熟悉的检查语句来检测。如果我们使用的开发平台是JDK1.4或者更高级的平台，我们可以使用assert结构；否则我们应该使用一种临时的断言机制。<BR>有些参数在使用过程中是先保存起来，然后在使用的时候再进行调用，构造函数正是这种类型的一种体现，所以我们通常对构造函数参数的有效性检查是非常仔细的。</DIV>
<DIV>Item 24：需要时使用保护性拷贝<BR>众所周知，JAVA在代码安全性方面较C/C++有显著的提高，缓冲区溢出，数组越界，非法指针等等，我们的JAVA都有一个很完善的机制来进行免疫，但是这并不代表我们不必去考虑JAVA的安全性，即便在安全的语言，如果不采取措施，还是无法使自己与其他类隔开。假设类的客户会尽一切手段来破坏这个类的约束条件，在这样的前提下，你必须从保护性的方面来考虑设计程序。通过大量的程序代码研究我们得出这样的结论：对于构造性函数的每个可变参数进行保护性拷贝是必要的。需要注意的是，保护性拷贝是在检查参数的有效性之前 进行的，并且有效性检查是针对拷贝之后的对象，而不是原始的对象。对于“参数类型可以被不可信方子类化”的情况，不要用clone方法来进行参数的保护性拷贝。<BR>对于参数的保护性拷贝并不仅仅在于非可变类，当我们编写一个函数或者一个构造函数的时候，如果它要接受客户提供的对象，允许该对象进入到内部数据结构中，则有必要考虑一下，客户提供的对象是否是可变的，如果是，则要考虑其变化的范围是否在你的程序所能容纳的范围内，如果不是，则要对对象进行保护性拷贝，并且让拷贝之后的对象而不是原始对象进入到数据结构中去。当然最好的解决方法是使用非可变的对象作为你的对象内部足见，这样你就可以不必关心保护性拷贝问题了。）：</DIV>
<DIV>Item 25：谨慎使用设计方法的原型<BR>（1）谨慎的选择方法的名字：即要注意首先要是易于理解的，其次还要与该包中的其他方法的命名风格相一致，最后当然要注意取一个大众所认可的名字。<BR>（2）不要追求提供便利的方法：每一个方法都应该提供其应具备的功能点，对于接口和类来方法不要过多，否则会对学习使用维护等等方面带来许多不必要的麻烦，对于每一个类型所支持的每一个动作，都提供一个功能完全的方法，只有一个方法过于频繁的使用时，才考虑为它提供一个快捷方法。<BR>（3）避免过长的参数列表：通常在实践中，我们以三个参数作为最大值，参数越少越好，类型相同的长参数列尤其影响客户的使用，两个方法可以避免过长的参数这样的情况发生，一是把一个方法分解成多个，每一个方法只要求使用这些参数的一个子集；二是创建辅助类，用来保存参数的聚集，这些辅助类的状态通常是静态的。<BR>对于参数类型，优先使用接口而不是类。<BR>这样做的目的是避免影响效能的拷贝操作。<BR>谨慎的使用函数对象。<BR>创建函数对象最容易的方法莫过于使用匿名类，但是那样会带来语法上混乱，并且与内联的控制结构相比，这样也会导致功能上的局限性。</DIV>
<DIV>Item 26：谨慎的使用重载<BR>到底是什么造成了重载机制的混淆算法，这是个争论的话题，一个安全而保守的方法是，永远不要导出两个具有相同参数数目的重载方法。而对于构造函数来说，一个类的多个构造函数总是重载的，在某些情况下，我们可以选择静态工厂，但是对于构造函数来说这样做并不总是切合实际的。<BR>当涉及到构造函数时，遵循这条建议也许是不可能的，但我们应该极力避免下面的情形：<BR>同一组参数只需要经过类型的转换就可以传递给不同的重载方法。如果这样做也不能避免的话，我们至少要保证一点：当传递同样的参数时，所有的重载方法行为一致。如果不能做到这一点，程序员就不能有效的使用方法或者构造函数。</DIV>
<DIV>Item 27：返回零长度的数组而不是null<BR>因为这样做的原因是编写客户程序的程序员可能忘记写这种专门的代码来处理null返回值。没有理由从一个取数组值的方法中返回null，而不是返回一个零长度数组。</DIV>
<DIV>Item 28：为所有导出的API元素编写文档注释<BR>不爱写注释可能是大多数程序员新手的通病（包括偶哈~），但是如果想要一个API真正可用，就必须写一个文档来说明它，保持代码和文档的同步是一件比较烦琐的事情，JAVA语言环境提供了javadoc工具，从而使这个烦琐的过程变得容易，这个工具可以根据源代码自动产生API文档。<BR>为了正确得编写API文档，我们必须每一个被导出的类，接口，构造函数，方法和域声明之前加一个文档注释。<BR>每一个方法的文档注释应该见解的描述它和客户之间的约定。<BR>我们接下来讨论一下Java语言的细节，包括局部变量的处理，库的使用，以及两种不是语言本身提供的机制的使用等等一些大家平时可能忽略的问题。</DIV>
<DIV>Item 29:将局部变量的作用域最小化<BR>和C语言要求局部变量必须被生命在代码的开始处相比，Java程序设计语言宽松得多，它允许你在代码的任何位置声明。要想使一个局部变量的作用域最小化，最高小的技术是在第一次需要使用它的地方声明，变量的作用域是从声明它的地方开始到这个声明做在的代码块的结束位止，如果我们把变量的声明和代码的使用位置分开的过大，那么对于读这段代码的人来说，是很不幸的。<BR>我们几乎都是在一个局部变量声明的地方同时给它初始化，注意这是很重要的，甚至有时候，如果我们的初始化应该推迟到下一个代码的位置，我们同时应该把声明也往后延迟。这条规则唯一的例外是try-catch这个语句，因为如果一个变量被方法初始化，那么这个方法很有可能抛出一个异常，那我们最常用的方法就是把它置于try块的内部去进行初始化。由此我们可以得出，for循环优于while循环，我们在能使用for循环的地方尽量使用for而不使用while，因为for循环是完全独立的，所以重用循环变量名字不会有任何伤害。<BR>最后我们要记住的是尽量把我们的函数写的小而集中，这样才能真正组做到”最小化局部变量的作用域”这一要旨。</DIV>
<DIV>Item 30：了解和使用库<BR>使用标准库，我们可以充分利用编写这些库的Java专家的知识，以及在你之前其他人的使用经验，这就是所谓站在巨人的肩膀上看世界吧~<BR>在每一个Java平台的发行版本里面，都会有许多新的包的加入，和这些更新保持一直是值得的，比如说我们J2ME的开发，在MIDP 1.0的时代，我们要写个Game还要自己动手写工具类，现在MIDP2.0推出之后，大多数写游戏的人都觉得方便了很多，因为在这个版本里面加入了游戏包，为我们的开发节省了大量的人力物力。</DIV>
<DIV>Item 31：如果想要知道精确的答案，就要避免使用double和float<BR>&nbsp;&nbsp;&nbsp;&nbsp; 对于金融行业来说，对数据的严整性要求是很高的，不容半点马虎，那大家都知道再我们的Java语言里面有两个浮点数类型的变量float和double，可能大家会认为他们的精度对于金融行业这样对数字敏感的行业来说，已经够用了，但是在开发当中，我们要尽量少使用double和float，因为让他们精确的表达0.1是不可能的。那我们如何解决这个问题呢，答案是使用BigDecimal,int或者long进行货币计算。在这里对大家的忠告是：对于商务运算，我们尽量使用BigDecimal，对于性能要求较高的地方，我们有能力自己处理十进制的小数点，数值不太大的时候，我们可以使用int或者long，根据自己的需要来判定具体使用哪一个，如果范围超过了18位数，那我们必须使用BigDecimal。</DIV>
<DIV>Item 32：如果其他类型更适合，则尽量避免使用字符串<BR>&nbsp;&nbsp;&nbsp;&nbsp; 在偶看到这条建议之前，我就很喜欢用字符串，不管在什么场合下，先String了再说，但是实际上很多情况下，我们要根据实际情况来判定到底使用什么类型，而且字符串不适合替代枚举类型，类型安全枚举类型和int值都比字符串更适合用来表示枚举类型的常量。字符串也不适合替代聚集类型，有一个更好的方法就是简单的写一个类来描述这个数据集，通常是一个私有的静态成员类最好。字符串也不适合代替能力表，总而言之，如果可以适合更加适合的数据类型，或者可以编写更加适当的数据类型，那么应该避免使用字符串来表示对象。</DIV>
<DIV>Item 33：了解字符串的连接功能<BR>我们经常在使用System.out.println()的时候，往括号里写一串用“+”连接起来的字符串，这是我们最常见的，但是这个方法并不适合规模较大的情形，为连接N个字符串而重复地使用字符串连接操作符，要求N的平方级的时间，这是因为字符串是非可变的，这就导致了在字符串进行连接的时候，前后两者都要拷贝，这个时候我们就提倡使用StingBuffer替代String。</DIV>
<DIV>Item 34：通过接口引用对象<BR>通俗的说就是尽量优先使用接口而不是类来引用对象，如果有合适的接口存在那么对使用参数，返回值，变量域都应该使用接口类型养成使用接口作为对象的习惯，会使程序变得更加灵活。<BR>如果没有合适的接口，那么，用类而不是接口来引用一个对象，是完全合适的。</DIV>
<DIV>Item 35：接口优先于映像机制<BR>java.lang.relect提供了“通过程序来访问关于已装载的类的信息”，由此，我们可以通过一个给定的Class实例，获得Constructor,Method和Field实例。<BR>映像机制允许一个类使用另一个类，即使当前编译的时候后者还不存在，但是这种能力也要付出代价：<BR>我们损失了了编译时类型检查的好处，而且要求执行映像访问的代码非常笨拙和冗长，并且在性能上大大损失。<BR>通常，普通应用在运行时刻不应以映像方式访问对象。</DIV>
<DIV>Item 36：谨慎的使用本地方法<BR>JNI允许Java应用程序调用本地方法，所谓本地方法是指用本地程序设计语言（如C，C++）来编写的特殊方法，本地方法可以在本地语言执行任何计算任务，然后返回到Java程序设计语言中。但是随着JDK1.3及后续版本的推出这种通过使用本地方法来提高性能的方法已不值得提倡，因为现在的JVM越来越快了，而且使用本地方法有一些严重的缺点，比如使Java原本引以为傲的安全性荡然无存，总之在使用本地方法的时候要三思。</DIV>
<DIV>Item 37：谨慎使用优化<BR>不要因为性能而牺牲合理的代码结构，努力编写好的程序而不是快的程序，但是避免那些限制性能的设计决定，同时考虑自己设计的API决定的性能后果，为了获得更好的性能而对API进行修改这也是一个非常不好的想法，通常我们在做优化之后，都应该对优化的程度进行一些测量。</DIV>
<DIV>Item 38：遵守普遍接受的命名惯例<BR>Java有一套比较完善的命名惯例机制，大部分包含在《The Java Language Specification》，严格得讲这些惯例分成两类，字面的和语法的。<BR>字面涉及包，类，接口，方法和域，语法的命名惯例比较灵活，所以争议更大，字面惯例是非常直接和明确的，而语法惯例则相对复杂，也很松散。但是有一个公认的做法是：“如果长期养成的习惯用法与此不同的话，请不要盲目遵从 </DIV>
<DIV>Item 12：把类和成员的可访问范围降到最低<BR>&nbsp;&nbsp;&nbsp; 好的模块设计应该尽最大可能封装好自己的内部信息，这样可以把模块之间的耦合程度降到最低。开发得以并行，无疑这将加快开发的速度，便于系统地维护。Java中通过访问控制符来解决这个问题。</DIV>
<DIV>public表示这个类在任何范围都可用。 <BR>protected表示只有子类和包内的类可以使用 <BR>private-package(default)表示在包内可用 <BR>private表示只有类内才可以用<BR>你在设计一个类的时候应该尽量的按照4321得顺序设计。如果一个类只是被另一个类使用，那么应该考虑把它设计成这个类的内部类。通常public的类不应该有public得字段，不过我们通常会用一个类来定义所有的常量，这是允许的。不过必须保证这些字段要么是基本数据类型要么引用指向的对象是不可修改的。不然他们将可能被修改。例如下面的定义中data就是不合理的，后面两个没有问题。<BR>public class Con<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int[] data = {1,2,3};// it is bad<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final String hello = "world";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int i = 1;<BR>}</DIV>
<DIV>Item 13:不可修改的类更受青睐<BR>&nbsp;&nbsp;&nbsp; 不可修改的类意思是他们一经创建就不会改变，例如String类。他们的设计、实现都很方便，安全性高——它们是线程安全的。设计不可修改类有几点规则：</DIV>
<DIV>不要提供任何可以修改对象的方法 <BR>确保没有方法能够被覆盖，可以通过把它声明为final <BR>所有字段设计成final <BR>所有字段设计成private <BR>确保外部不能访问到类的可修改的组件<BR>不可修改类也有个缺点就是创建不同值得类的时候要创建不同的对象，String就是这样的。通常有个解决的办法就是提供一个帮助类来弥补，例如StringBuffer类。</DIV>
<DIV>Item 14:化合(合成）比继承更值得考虑<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实现代码重用最重要的办法就是继承，但是继承破坏了封装，导致软件的键壮性不足。如果子类继承了父类，那么它从父类继承的方法就依赖父类的实现，一旦他改变了会导致不可预测的结果。作者介绍了InstrumentedHashSet作为反例进行说明，原因就是没有明白父类的方法实现。作者给出的解决办法是通过化合来代替继承，用包装类和转发方法来解决问题。把想扩展的类作为本类的一个private final得成员变量。把方法参数传递给这个成员变量并得到返回值。这样做的缺点是这样的类不适合回掉框架。继承虽然好，我们却不应该滥用，只有我们能确定它们之间是is-a得关系的时候才使用。</DIV>
<DIV>Item 15:如果要用继承那么设计以及文档都要有质量保证，否则就不要用它</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 为了避免继承带来的问题，你必须提供精确的文档来说明覆盖相关方法可能出现的问题。在构造器内千万不要调用可以被覆盖的方法，因为子类覆盖方法的时候会出现问题。<BR>import java.util.*;</DIV>
<DIV>public class SubClass extends SuperClass<BR>{<BR>&nbsp;private final Date date;<BR>&nbsp;<BR>&nbsp;public SubClass()<BR>&nbsp;{<BR>&nbsp; date = new Date(); <BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public void m()<BR>&nbsp;{<BR>&nbsp; System.out.println(date); <BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;public static void main(String[] args)<BR>&nbsp;{<BR>&nbsp; SubClass s = new SubClass();<BR>&nbsp; s.m(); <BR>&nbsp;}<BR>&nbsp;<BR>}</DIV>
<DIV>class SuperClass<BR>{<BR>&nbsp;public SuperClass()<BR>&nbsp;{<BR>&nbsp; m(); <BR>&nbsp;} <BR>&nbsp;<BR>&nbsp;public void m()<BR>&nbsp;{<BR>&nbsp; <BR>&nbsp;}<BR>}<BR>由于在date被初始化之前super（）已经被调用了，所以第一次输出null而不是当前的时间。<BR>由于在Clone()或者序列化的时候非常类似构造器的功能，因此readObject()和clone（）方法内最好也不要包括能被覆盖的方法。</DIV>
<DIV>Item 16:在接口和抽象类之间优先选择前者<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口和抽象类都用来实现多态，不过我们应该优先考虑用接口。知道吗？James说过如果要让他重新设计java的话他会把所有都设计成接口的。抽象类的优点是方便扩展，因为它是被继承的，并且方法可以在抽象类内实现，接口则不行。</DIV>
<DIV>Item 17：接口只应该用来定义类型<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口可以这样用的 Collection c = new xxxx();这是我们最常用的。不要把接口用来做其他的事情，比如常量的定义。你应该定义一个类，里面包含public final static 得字段。</DIV>
<DIV>Item 18: 在静态和非静态内部类之间选择前者<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果一个类被定义在其他的类内部那么它就是嵌套类，可以分为静态内部类、非静态内部类和匿名类。<BR>&nbsp;&nbsp; static member class 得目的是为enclosing class服务，如果还有其他的目的，就应该把它设计成top-level class。nonstatic member class是和enclosing class instance关联的，如果不需要访问enclosing class instance的话应该把它设计成static得，不然会浪费时间和空间。anonymous class是声明和初始化同时进行的。可以放在代码的任意位置。典型应用是Listener 和process object例如Thread。</DIV>
<DIV>&nbsp;&nbsp;&nbsp; 由于以前学过C语言，所以对C还是蛮有感情，而JAVA和C又有很多相似之处，很多从C转过来学习JAVA的兄弟，可能一开始都不是很适应，因为很多在C里面的结构在JAVA里面都不能使用了，所以下面我们来介绍一下C语言结构的替代。</DIV>
<DIV>Item 19:用类代替结构<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JAVA刚面世的时候，很多C程序员都认为用类来代替结构现在太复杂，代价太大了，但是实际上，如果一个JAVA的类退化到只包含一个数据域的话，这样的类与C语言的结构大致是等价的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 比方说下面两个程序片段：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Point<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实际上这段代码和C语言的结构基本上没什么区别，但是这段代码恐怕是众多OO设计Fans所不齿的，因为它没有体现封装的优异性，没有体现面向对象设计的优点，当一个域被修改的时候，你不可能再采取任何辅助的措施了，那我们再来看一看采用包含私有域和共有访问方法的OO设计代码段：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Point<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Point(float x,float y)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x=x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y=y;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public float getX(){retrun x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public float getY(){return y;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setX(float x){this.x=x;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setY(float y){this.y=y;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单从表面上看，这段代码比上面那个多了很多行，还多了很多函数，但是仔细想一下，这样的OO设计，似乎更人性化，我们可以方面的对值域进行提取，修改等操作，而不直接和值域发生关系，这样的代码不仅让人容易读懂，而且很安全，还吸取了面向对象程序设计的灵活性，试想一下，如果一个共有类暴露它的值域，那么想要在将来的版本中进行修改是impossible的，因为共有类的客户代码已经遍布各处了。<BR>需要提醒一点的是，如果一个类是包级私有的，或者是一个私有的嵌套类，则直接暴露其值域并无不妥之处。</DIV>
<DIV>Item 20：用类层次来代替联合<BR>我们在用C语言来进行开发的时候，经常会用到联合这个概念，比如：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef struct{<BR>&nbsp;&nbsp;&nbsp;&nbsp; double length;<BR>&nbsp;&nbsp;&nbsp;&nbsp; double width;&nbsp;&nbsp;&nbsp;&nbsp; <BR>}rectangleDimensions_t;<BR>那我们在JAVA里面没有联合这个概念，那我们用什么呢？对！用继承，这也是JAVA最吸引我的地方之一，它可以使用更好的机制来定义耽搁数据类型，在Bruce Eckel的Thinking in java里面也多次提到了一个和形状有关的例子，我们可以先笼统的定义一个抽象类，即我们通常所指的超类，每个操作定义一个抽象的方法，其行为取决于标签的值，如果还有其他的操作不依赖于标签的值，则把操作变成根类（继承的类）中的具体方法。<BR>这样做的最重要的优点是：类层次提供了类型的安全性。<BR>其次代码非常明了，这也是OO设计的优点。<BR>而且它很容易扩展，即使是面向多个方面的工作，能够同样胜任。<BR>最后它可以反映这些类型之间本质上的层次关系，从而允许更强的灵活性，以便编译时类型检查。</DIV>
<DIV>Item 21：用类来代替enum结构<BR>Java程序设计语言提出了类型安全枚举的模式来替代enum结构，它的基本思想很简单：定义一个类来代表枚举类型的单个元素，并且不提供任何公有的构造函数，相反，提供公有静态final类，使枚举类型中的每一个常量都对应一个域。<BR>类型安全枚举类型的一个缺点是，装载枚举类的和构造常量对象时，需要一定的时间和空间开销，除非是在资源很受限制的设备比如蜂窝电哈和烤面包机上，否则在实际中这个问题不会被考虑。<BR>&nbsp;总之，类型安全枚举类型明显优于int类型，除非实在一个枚举类型主要被用做一个集合元素，或者主要用在一个资源非常不受限的环境下，否则类型安全枚举类型的缺点都不成问题，依次，在要求使用一个枚举类型的环境下，我们首先应考虑类型安全枚举类型模式。</DIV>
<DIV>Item 22：用类和接口来代替函数指针<BR>&nbsp;class StringLengthComprator{<BR>public int compare(String s1,String s2)<BR>{<BR>return s1.length()-s2.length();<BR>}<BR>}<BR>这个类导出一个带两个字符串的方法，它是一个用于字符串比较的具体策略。它是无状态的，没有域，所以，这个类的所有实例在功能上都是等价的，可以节省不必要的对象创建开销。但是我们不好直接把这个类传递给可户使用，因为可户无法传递任何其他的比较策略。相反，我们可以定义一个接口，即我们在设计具体策略类的时候还需要定义一个策略接口：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public interface Comparator{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object o1,Object o2);<BR>}<BR>&nbsp; 我们完全可以依照自己的需要来定义它。<BR>在JAVA中，我们为了实现指针的模式，声明一个接口来表示该策略，并且为每个具体策略声明一个实现了该接口的类，如果一个具体策略只被使用一次的话，那么通常使用匿名类来声明和实例化这个具体策略类，如果一个策略类反复使用，那么它的类通常是一个私有的的静态成员类。 <BR>下面我们来讨论一下有关方法设计的几个方面，下面说的几个要点大多数都是应用在构造函数中，当然也使用于普通方法，我们追求的依然是程序的可用性，健壮性和灵活性。</DIV>
<DIV>Item 23：检查参数的有效性<BR>非公有的方法我们应该用断言的方法来检查它的参数，而不是使用通常大家所熟悉的检查语句来检测。如果我们使用的开发平台是JDK1.4或者更高级的平台，我们可以使用assert结构；否则我们应该使用一种临时的断言机制。<BR>有些参数在使用过程中是先保存起来，然后在使用的时候再进行调用，构造函数正是这种类型的一种体现，所以我们通常对构造函数参数的有效性检查是非常仔细的。</DIV>
<DIV>Item 24：需要时使用保护性拷贝<BR>众所周知，JAVA在代码安全性方面较C/C++有显著的提高，缓冲区溢出，数组越界，非法指针等等，我们的JAVA都有一个很完善的机制来进行免疫，但是这并不代表我们不必去考虑JAVA的安全性，即便在安全的语言，如果不采取措施，还是无法使自己与其他类隔开。假设类的客户会尽一切手段来破坏这个类的约束条件，在这样的前提下，你必须从保护性的方面来考虑设计程序。通过大量的程序代码研究我们得出这样的结论：对于构造性函数的每个可变参数进行保护性拷贝是必要的。需要注意的是，保护性拷贝是在检查参数的有效性之前 进行的，并且有效性检查是针对拷贝之后的对象，而不是原始的对象。对于“参数类型可以被不可信方子类化”的情况，不要用clone方法来进行参数的保护性拷贝。<BR>对于参数的保护性拷贝并不仅仅在于非可变类，当我们编写一个函数或者一个构造函数的时候，如果它要接受客户提供的对象，允许该对象进入到内部数据结构中，则有必要考虑一下，客户提供的对象是否是可变的，如果是，则要考虑其变化的范围是否在你的程序所能容纳的范围内，如果不是，则要对对象进行保护性拷贝，并且让拷贝之后的对象而不是原始对象进入到数据结构中去。当然最好的解决方法是使用非可变的对象作为你的对象内部足见，这样你就可以不必关心保护性拷贝问题了。）：</DIV>
<DIV>Item 25：谨慎使用设计方法的原型<BR>（1）谨慎的选择方法的名字：即要注意首先要是易于理解的，其次还要与该包中的其他方法的命名风格相一致，最后当然要注意取一个大众所认可的名字。<BR>（2）不要追求提供便利的方法：每一个方法都应该提供其应具备的功能点，对于接口和类来方法不要过多，否则会对学习使用维护等等方面带来许多不必要的麻烦，对于每一个类型所支持的每一个动作，都提供一个功能完全的方法，只有一个方法过于频繁的使用时，才考虑为它提供一个快捷方法。<BR>（3）避免过长的参数列表：通常在实践中，我们以三个参数作为最大值，参数越少越好，类型相同的长参数列尤其影响客户的使用，两个方法可以避免过长的参数这样的情况发生，一是把一个方法分解成多个，每一个方法只要求使用这些参数的一个子集；二是创建辅助类，用来保存参数的聚集，这些辅助类的状态通常是静态的。<BR>对于参数类型，优先使用接口而不是类。<BR>这样做的目的是避免影响效能的拷贝操作。<BR>谨慎的使用函数对象。<BR>创建函数对象最容易的方法莫过于使用匿名类，但是那样会带来语法上混乱，并且与内联的控制结构相比，这样也会导致功能上的局限性。</DIV>
<DIV>Item 26：谨慎的使用重载<BR>到底是什么造成了重载机制的混淆算法，这是个争论的话题，一个安全而保守的方法是，永远不要导出两个具有相同参数数目的重载方法。而对于构造函数来说，一个类的多个构造函数总是重载的，在某些情况下，我们可以选择静态工厂，但是对于构造函数来说这样做并不总是切合实际的。<BR>当涉及到构造函数时，遵循这条建议也许是不可能的，但我们应该极力避免下面的情形：<BR>同一组参数只需要经过类型的转换就可以传递给不同的重载方法。如果这样做也不能避免的话，我们至少要保证一点：当传递同样的参数时，所有的重载方法行为一致。如果不能做到这一点，程序员就不能有效的使用方法或者构造函数。</DIV>
<DIV>Item 27：返回零长度的数组而不是null<BR>因为这样做的原因是编写客户程序的程序员可能忘记写这种专门的代码来处理null返回值。没有理由从一个取数组值的方法中返回null，而不是返回一个零长度数组。</DIV>
<DIV>Item 28：为所有导出的API元素编写文档注释<BR>不爱写注释可能是大多数程序员新手的通病（包括偶哈~），但是如果想要一个API真正可用，就必须写一个文档来说明它，保持代码和文档的同步是一件比较烦琐的事情，JAVA语言环境提供了javadoc工具，从而使这个烦琐的过程变得容易，这个工具可以根据源代码自动产生API文档。<BR>为了正确得编写API文档，我们必须每一个被导出的类，接口，构造函数，方法和域声明之前加一个文档注释。<BR>每一个方法的文档注释应该见解的描述它和客户之间的约定。<BR>我们接下来讨论一下Java语言的细节，包括局部变量的处理，库的使用，以及两种不是语言本身提供的机制的使用等等一些大家平时可能忽略的问题。</DIV>
<DIV>Item 29:将局部变量的作用域最小化<BR>和C语言要求局部变量必须被生命在代码的开始处相比，Java程序设计语言宽松得多，它允许你在代码的任何位置声明。要想使一个局部变量的作用域最小化，最高小的技术是在第一次需要使用它的地方声明，变量的作用域是从声明它的地方开始到这个声明做在的代码块的结束位止，如果我们把变量的声明和代码的使用位置分开的过大，那么对于读这段代码的人来说，是很不幸的。<BR>我们几乎都是在一个局部变量声明的地方同时给它初始化，注意这是很重要的，甚至有时候，如果我们的初始化应该推迟到下一个代码的位置，我们同时应该把声明也往后延迟。这条规则唯一的例外是try-catch这个语句，因为如果一个变量被方法初始化，那么这个方法很有可能抛出一个异常，那我们最常用的方法就是把它置于try块的内部去进行初始化。由此我们可以得出，for循环优于while循环，我们在能使用for循环的地方尽量使用for而不使用while，因为for循环是完全独立的，所以重用循环变量名字不会有任何伤害。<BR>最后我们要记住的是尽量把我们的函数写的小而集中，这样才能真正组做到”最小化局部变量的作用域”这一要旨。</DIV>
<DIV>Item 30：了解和使用库<BR>使用标准库，我们可以充分利用编写这些库的Java专家的知识，以及在你之前其他人的使用经验，这就是所谓站在巨人的肩膀上看世界吧~<BR>在每一个Java平台的发行版本里面，都会有许多新的包的加入，和这些更新保持一直是值得的，比如说我们J2ME的开发，在MIDP 1.0的时代，我们要写个Game还要自己动手写工具类，现在MIDP2.0推出之后，大多数写游戏的人都觉得方便了很多，因为在这个版本里面加入了游戏包，为我们的开发节省了大量的人力物力。</DIV>
<DIV>Item 31：如果想要知道精确的答案，就要避免使用double和float<BR>&nbsp;&nbsp;&nbsp;&nbsp; 对于金融行业来说，对数据的严整性要求是很高的，不容半点马虎，那大家都知道再我们的Java语言里面有两个浮点数类型的变量float和double，可能大家会认为他们的精度对于金融行业这样对数字敏感的行业来说，已经够用了，但是在开发当中，我们要尽量少使用double和float，因为让他们精确的表达0.1是不可能的。那我们如何解决这个问题呢，答案是使用BigDecimal,int或者long进行货币计算。在这里对大家的忠告是：对于商务运算，我们尽量使用BigDecimal，对于性能要求较高的地方，我们有能力自己处理十进制的小数点，数值不太大的时候，我们可以使用int或者long，根据自己的需要来判定具体使用哪一个，如果范围超过了18位数，那我们必须使用BigDecimal。</DIV>
<DIV>Item 32：如果其他类型更适合，则尽量避免使用字符串<BR>&nbsp;&nbsp;&nbsp;&nbsp; 在偶看到这条建议之前，我就很喜欢用字符串，不管在什么场合下，先String了再说，但是实际上很多情况下，我们要根据实际情况来判定到底使用什么类型，而且字符串不适合替代枚举类型，类型安全枚举类型和int值都比字符串更适合用来表示枚举类型的常量。字符串也不适合替代聚集类型，有一个更好的方法就是简单的写一个类来描述这个数据集，通常是一个私有的静态成员类最好。字符串也不适合代替能力表，总而言之，如果可以适合更加适合的数据类型，或者可以编写更加适当的数据类型，那么应该避免使用字符串来表示对象。</DIV>
<DIV>Item 33：了解字符串的连接功能<BR>我们经常在使用System.out.println()的时候，往括号里写一串用“+”连接起来的字符串，这是我们最常见的，但是这个方法并不适合规模较大的情形，为连接N个字符串而重复地使用字符串连接操作符，要求N的平方级的时间，这是因为字符串是非可变的，这就导致了在字符串进行连接的时候，前后两者都要拷贝，这个时候我们就提倡使用StingBuffer替代String。</DIV>
<DIV>Item 34：通过接口引用对象<BR>通俗的说就是尽量优先使用接口而不是类来引用对象，如果有合适的接口存在那么对使用参数，返回值，变量域都应该使用接口类型养成使用接口作为对象的习惯，会使程序变得更加灵活。<BR>如果没有合适的接口，那么，用类而不是接口来引用一个对象，是完全合适的。</DIV>
<DIV>Item 35：接口优先于映像机制<BR>java.lang.relect提供了“通过程序来访问关于已装载的类的信息”，由此，我们可以通过一个给定的Class实例，获得Constructor,Method和Field实例。<BR>映像机制允许一个类使用另一个类，即使当前编译的时候后者还不存在，但是这种能力也要付出代价：<BR>我们损失了了编译时类型检查的好处，而且要求执行映像访问的代码非常笨拙和冗长，并且在性能上大大损失。<BR>通常，普通应用在运行时刻不应以映像方式访问对象。</DIV>
<DIV>Item 36：谨慎的使用本地方法<BR>JNI允许Java应用程序调用本地方法，所谓本地方法是指用本地程序设计语言（如C，C++）来编写的特殊方法，本地方法可以在本地语言执行任何计算任务，然后返回到Java程序设计语言中。但是随着JDK1.3及后续版本的推出这种通过使用本地方法来提高性能的方法已不值得提倡，因为现在的JVM越来越快了，而且使用本地方法有一些严重的缺点，比如使Java原本引以为傲的安全性荡然无存，总之在使用本地方法的时候要三思。</DIV>
<DIV>Item 37：谨慎使用优化<BR>不要因为性能而牺牲合理的代码结构，努力编写好的程序而不是快的程序，但是避免那些限制性能的设计决定，同时考虑自己设计的API决定的性能后果，为了获得更好的性能而对API进行修改这也是一个非常不好的想法，通常我们在做优化之后，都应该对优化的程度进行一些测量。</DIV>
<DIV>Item 38：遵守普遍接受的命名惯例<BR>Java有一套比较完善的命名惯例机制，大部分包含在《The Java Language Specification》，严格得讲这些惯例分成两类，字面的和语法的。<BR>字面涉及包，类，接口，方法和域，语法的命名惯例比较灵活，所以争议更大，字面惯例是非常直接和明确的，而语法惯例则相对复杂，也很松散。但是有一个公认的做法是：“如果长期养成的习惯用法与此不同的话，请不要盲目遵从 </DIV><img src ="http://www.blogjava.net/gufen/aggbug/13993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gufen/" target="_blank">落花飞雪</a> 2005-09-25 15:24 <a href="http://www.blogjava.net/gufen/archive/2005/09/25/13993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Practical Java》笔记</title><link>http://www.blogjava.net/gufen/archive/2005/09/25/13992.html</link><dc:creator>落花飞雪</dc:creator><author>落花飞雪</author><pubDate>Sun, 25 Sep 2005 07:22:00 GMT</pubDate><guid>http://www.blogjava.net/gufen/archive/2005/09/25/13992.html</guid><wfw:comment>http://www.blogjava.net/gufen/comments/13992.html</wfw:comment><comments>http://www.blogjava.net/gufen/archive/2005/09/25/13992.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/gufen/comments/commentRss/13992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gufen/services/trackbacks/13992.html</trackback:ping><description><![CDATA[<P>1.&nbsp;声明是什么?<BR>String s = "Hello world!";</P>
<P>许多人都做过这样的事情，但是，我们到底声明了什么？回答通常是：一个String，内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答，一半的人大概会回答错误。<BR>这个语句声明的是一个指向对象的引用，名为“s”，可以指向类型为String的任何对象，目前指</P>
<P>1.&nbsp;声明是什么?<BR>String s = "Hello world!";</P>
<P>许多人都做过这样的事情，但是，我们到底声明了什么？回答通常是：一个String，内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答，一半的人大概会回答错误。<BR>这个语句声明的是一个指向对象的引用，名为“s”，可以指向类型为String的任何对象，目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象，我们只是声明了一个只能指向String对象的引用变量。所以，如果在刚才那句语句后面，如果再运行一句：</P>
<P>String string = s;</P>
<P>我们是声明了另外一个只能指向String对象的引用，名为string，并没有第二个对象产生，string还是指向原来那个对象，也就是，和s指向同一个对象。<BR>2.&nbsp;String类的特殊性<BR>1)&nbsp;String s1 = “Hello”;&nbsp; //产生一个String ”Hello”对象,并产生该对象的一个别名s1来引用该对象<BR>String s2 = “Hello”;&nbsp; //又产生一个别名s2来引用上面的”Hello”对象<BR>s1 == s2 = true;&nbsp;&nbsp; //由于是同一个对象所以“==”返回为true<BR>s1 = “World”;&nbsp; //产生一个String ”World”对象, s1的引用不再指向“Hello”而是指向对象”World”<BR>s1 == s2 = false;&nbsp;&nbsp; //由于不是同一个对象所以“==”返回为false<BR>s1 = “Hello”;&nbsp; //同上面的String s2 = “Hello”; 现在s1又指向对象”Hello”, 因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。<BR>s1 == s2 = true;&nbsp;&nbsp; //由于是同一个对象所以“==”又返回为true了<BR>s1 = s1 + “World”;&nbsp; //这时又产生一个对象”HelloWord”,s1不再指向”Hello”而是指向”HelloWord”<BR>s1 == s2 = false;&nbsp; //不是一个对象当然是false拉<BR>s1 = s1+ "a"+"b"+"c"+…;&nbsp; // String不停的创建对象,影响性能，这种易变的String用StringBuffer会得到更好的性能<BR>StringBuffer s3 = new StringBuffer(“Hello”); <BR>s3.append(“a”); //没有生成新的对象，而是将s3引用的对象内容改为”Helloa”</P>
<P>//说明: String类用来表示那些创建后就不会再改变的字符串，它是immutable的。而StringBuffer类用来表示内容可变的字符串，并提供了修改底层字符串的方法。<BR>StingBuffer是一个可变的字符串，它可以被更改。同时StringBuffer是Thread safe的， 你可以放心的使用.</P>
<P>因为String被设计成一种安全的字符串， 避免了C/C++中的尴尬。因此在内部操作的时候会频繁的进行对象的交换， 因此它的效率不如StringBuffer。 如果需要频繁的进行字符串的增删操作的话最好用StringBuffer。 比如拼SQL文， 写共函。 另： 编绎器对String的+操作进行了一定的优化。 <BR>x = "a" + 4 + "c"<BR>会被编绎成<BR>x = new StringBuffer().append("a").append(4).append("c").toString()<BR>但：<BR>x = “a”;<BR>x = x + 4;<BR>x = x + “c”;<BR>则不会被优化。 可以看出如果在一个表达式里面进行String的多次+操作会被优化， 而多个表达式的+操作不会被优化。<BR>摘自：《Java API Using, Tips And Performance Tuning》<BR><FONT color=#000000>2)&nbsp;Integer、Boolean等wrapper类以及BigInteger、BigDecimal是immutable的，所以也有与String类似的地方，不过没有IntegerBuffer之类的东西。不过Float, Double比较特殊。如<BR>T a1 = 10; //T代指Byte,Integer,Short,Long,Boolean。 注：应用了JDK5的AUTOBOXING<BR>T a2 = 10;<BR>if (a1 == a2)<BR>&nbsp;System.out.println(true);<BR>else<BR>&nbsp;System.out.println(false);<BR>这时总是true,和String有点类似</FONT></P>
<P><FONT color=#000000>//Float时<BR>Float i1 =&nbsp; (float)10.0;<BR>Float i2 =&nbsp; (float)10.0;<BR>if (i1==i2)<BR>&nbsp;&nbsp;&nbsp;System.out.println(true);<BR>else<BR>&nbsp;&nbsp;&nbsp;System.out.println(false);<BR>这时总是false<BR><BR>//Double时<BR>Double i1 =&nbsp; 10.0;<BR>Double i2 =&nbsp; 10.0;<BR>if (i1==i2)<BR>&nbsp;&nbsp;&nbsp;System.out.println(true);<BR>else<BR>&nbsp;&nbsp;&nbsp;System.out.println(false);<BR>这时总是false<BR></FONT></P>
<P><FONT color=#000000>总之如果比较两个Wrapper类的值用equals，以免不必要的麻烦<BR></FONT>3)&nbsp;再看<BR>String s1 = new String(“Hello”);<BR>String s2 = new String(“Hello”);<BR>s1 == s2 = false;<BR>//因为new的时候JVM不管heap中有没有”Hello”对象都会产生一个新的”Hello”对象<BR>String s3 = “Hello”; //重新创建对象”Hello”, 并令s3指向对象”Hello”<BR>s3 == s1 = false; //不同对象当然false<BR>String s4 = “Hello”; <BR>s3 == s4 = true;&nbsp; //故伎重演，jvm清楚的知道哪些用了new，哪些没用new<BR><BR>3.&nbsp;方法的参数传递中都是以reference传递，而primitive传递的是副本，但如果传递的是Integer、Boolean等wrapper类和String类的Object则是以immutable方式传递。示例：<BR>import java.awt.Point;<BR>class HelloWorld<BR>{<BR>&nbsp; public static void modifyPoint(Point pt, String j, int k, Integer m, Boolean b)<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; pt.setLocation(5,5);&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; j = "15";<BR>&nbsp;&nbsp;&nbsp; k = 25;<BR>&nbsp;&nbsp;&nbsp; m = 35;<BR>&nbsp;&nbsp;&nbsp; b = true;<BR>&nbsp;&nbsp;&nbsp; System.out.println("During modifyPoint " + "pt = " + pt +<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and j = " + j+ " and k = "+ k+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and m = "+ m+ " and b = "+ b);<BR>&nbsp; }</P>
<P>&nbsp; public static void main(String args[])<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; Point p = new Point(0,0);&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;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; String i = "10";<BR>&nbsp;&nbsp;&nbsp; int k = 20;<BR>&nbsp;&nbsp;&nbsp; Integer m = 30;<BR>&nbsp;&nbsp;&nbsp; Boolean b = false;<BR>&nbsp;&nbsp;&nbsp; System.out.println("Before modifyPoint " + "p = " + p +<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and i = " + i+ " and k = "+ k+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and m = "+ m+ " and b = "+ b);<BR>&nbsp;&nbsp;&nbsp; modifyPoint(p, i, k, m, b);&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; System.out.println("After modifyPoint " + "p = " + p +<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and i = " + i+ " and k = "+ k+ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " and m = "+ m+ " and b = "+ b);<BR>&nbsp; }<BR>}<BR>输出结果：<BR>Before modifyPoint p = java.awt.Point[x=0,y=0] and i = 10 and k = 20 and m = 30 and b = false<BR>During modifyPoint pt = java.awt.Point[x=5,y=5] and j = 15 and k = 25 and m = 35 and b = true<BR>After modifyPoint p = java.awt.Point[x=5,y=5] and i = 10 and k = 20 and m = 30 and b = false<BR>4.&nbsp;final作用于基本类型变量则该变量为恒常量；final作用于对象类型变量则该对象reference为恒量；final作用于方法则该方法不能被覆盖；final作用于class则该class不能被继承。<BR>final使得被修饰的变量"不变"，但是由于对象型变量的本质是“引用”，使得“不变”也有了两种含义：引用本身的不变，和引用指向的对象不变。</P>
<P>引用本身的不变：<BR>final StringBuffer a=new StringBuffer("immutable");<BR>final StringBuffer b=new StringBuffer("not immutable");<BR>a=b;//编译期错误</P>
<P>引用指向的对象不变：<BR>final StringBuffer a=new StringBuffer("immutable");<BR>a.append(" broken!"); //编译通过</P>
<P>可见，final只对引用的“值”(也即它所指向的那个对象的内存地址)有效，它迫使引用只能指向初始指向的那个对象，改变它的指向会导致编译期错误。至于它所指向的对象的变化，final是不负责的。这很类似==操作符：==操作符只负责引用的“值”相等，至于这个地址所指向的对象内容是否相等，==操作符是不管的。</P>
<P>理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象，不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改，一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final，意图使得它“永远不变”。其实那是徒劳的。<BR>5.&nbsp;怎样初始化<BR>本问题讨论变量的初始化，所以先来看一下Java中有哪些种类的变量。<BR>1). 类的属性，或者叫值域<BR>2). 方法里的局部变量<BR>3). 方法的参数</P>
<P>对于第一种变量，Java虚拟机会自动进行初始化。如果给出了初始值，则初始化为该初始值。如果没有给出，则把它初始化为该类型变量的默认初始值。</P>
<P>primitive类型默认值<BR>boolean: false<BR>char: '\u0000'&nbsp; 对于未初始化的char c, c == ‘\u0000’ = true<BR>byte: 0<BR>short: 0<BR>int: 0<BR>long: 0<BR>float: 0.0<BR>double: 0.0<BR>object reference: null<BR>array: null<BR>注意数组本身也是对象，所以没有初始化的数组引用在自动初始化后其值也是null。</P>
<P>对于两种不同的类属性，static属性与instance属性，初始化的时机是不同的。instance属性在创建实例的时候初始化，static属性在类加载，也就是第一次用到这个类的时候初始化，对于后来的实例的创建，不再次进行初始化。</P>
<P>对于第二种变量，必须明确地进行初始化。如果再没有初始化之前就试图使用它，编译器会抗议。如果初始化的语句在try块中或if块中，也必须要让它在第一次使用前一定能够得到赋值。也就是说，把初始化语句放在只有if块的条件判断语句中编译器也会抗议，因为执行的时候可能不符合if后面的判断条件，如此一来初始化语句就不会被执行了，这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句，就可以通过编译，因为无论如何，总有至少一条初始化语句会被执行，不会发生使用前未被初始化的事情。对于try-catch也是一样，如果只有在try块里才有初始化语句，编译部通过。如果在 catch或finally里也有，则可以通过编译。总之，要保证局部变量在使用之前一定被初始化了。所以，一个好的做法是在声明他们的时候就初始化他们，如果不知道要出事化成什么值好，就用上面的默认值吧！</P>
<P>其实第三种变量和第二种本质上是一样的，都是方法中的局部变量。只不过作为参数，肯定是被初始化过的，传入的值就是初始值，所以不需要初始化。<BR>6.&nbsp;尽量使用多态(polymorphism)特性而不是instanceof<BR>7.&nbsp;一旦不需要对象，尽量显式的使之为null<BR>8.&nbsp;对象之间的”=”赋值操作乃是赋值的reference, 即左边的对象也指向右边的对象，只是该reference多了一个别名而已。<BR>9.&nbsp;“==”和equals()的区别<BR>==操作符专门用来比较变量的值是否相等。比较好理解的一点是：<BR>int a=10;<BR>int b=10;<BR>则a==b将是true。<BR>但不好理解的地方是：<BR>String a=new String("foo");<BR>String b=new String("foo");<BR>则a==b将返回false。</P>
<P>根据前一帖说过，对象变量其实是一个引用，它们的值是指向对象所在的内存地址，而不是对象本身。a和b都使用了new操作符，意味着将在内存中产生两个内容为"foo"的字符串，既然是“两个”，它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值，所以使用"=="操作符，结果会是 false。诚然，a和b所指的对象，它们的内容都是"foo"，应该是“相等”，但是==操作符并不涉及到对象内容的比较。<BR>对象内容的比较，正是equals方法做的事。</P>
<P>看一下Object对象的equals方法是如何实现的：<BR>boolean equals(Object o){</P>
<P>return this==o;</P>
<P>}<BR>Object 对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法，那你的类使用equals和使用==会得到同样的结果。同样也可以看出， Object的equals方法没有达到equals方法应该达到的目标：比较两个对象内容是否相等。因为答案应该由类的创建者决定，所以Object把这个任务留给了类的创建者。</P>
<P>看一下一个极端的类：<BR>Class Monster{<BR>private String content;<BR>...<BR>boolean equals(Object another){ return true;}</P>
<P>}<BR>我覆盖了equals方法。这个实现会导致无论Monster实例内容如何，它们之间的比较永远返回true。</P>
<P>所以当你是用equals方法判断对象的内容是否相等，请不要想当然。因为可能你认为相等，而这个类的作者不这样认为，而类的equals方法的实现是由他掌握的。如果你需要使用equals方法，或者使用任何基于散列码的集合（HashSet,HashMap,HashTable），请察看一下java doc以确认这个类的equals逻辑是如何实现的。<BR>10.&nbsp;不要依赖equals()的缺省实现<BR>11.&nbsp;一个equals()的实现模版<BR>class Golfball<BR>{<BR>&nbsp; private String brand;<BR>&nbsp; private String make;<BR>&nbsp; private int compression;</P>
<P>&nbsp; public boolean equals(Object obj)<BR>&nbsp; {</P>
<P>&nbsp;&nbsp;&nbsp; if (this == obj)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</P>
<P>&nbsp;&nbsp;&nbsp; if (obj != null &amp;&amp; getClass() == obj.getClass())<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Golfball gb = (Golfball)obj;&nbsp; //Classes are equal, downcast.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (brand.equals(gb.brand()) &amp;&amp;&nbsp; //Compare attributes.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make.equals(gb.make()) &amp;&amp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compression == gb.compression())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp; }<BR>}<BR>注意getClass() == obj.getClass()的限制，如果判断必须相等则无法比较基类和子类是否相等,完全不同的类不用考虑，完全没有可比性，除了特殊需要或很糟糕的程序。<BR>12.&nbsp;实现equals()应优先考虑使用getClass()<BR>13.&nbsp;如果某个基类我们自己实现了equals()，在它的子类中要覆盖此方法，最好调用super.equals()唤起base class的相关行为,然后再实现子类域的比较。<BR>Example:<BR>&nbsp; public boolean equals(Object obj)<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; if (this == obj)&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</P>
<P>&nbsp;&nbsp;&nbsp; if (obj != null &amp;&amp; getClass() == obj.getClass() &amp;&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.equals(obj))&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //3<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyGolfball gb = (MyGolfball)obj;&nbsp; //Classes equal, downcast.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ballConstruction == gb.construction())&nbsp; //Compare attrs.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp; }<BR>14.&nbsp;如果要在base class与derived class之间应运equals(),可以考虑instanceof来代替getClass()。对此论题的详细讨论参见:Practical Java, Practice 14<BR>15.&nbsp;instanceof什么东西？<BR>instanceof是Java的一个二元操作符，和==，&gt;，&lt;是同一类东东。由于它是由字母组成的，所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例，返回boolean类型的数据。举个例子：</P>
<P>String s = "I AM an Object!";<BR>boolean isObject = s instanceof Object;</P>
<P>我们声明了一个String对象引用，指向一个String对象，然后用instancof来测试它所指向的对象是否是Object类的一个实例，显然，这是真的，所以返回true，也就是isObject的值为True。<BR>instanceof有一些用处。比如我们写了一个处理账单的系统，其中有这样三个类：</P>
<P>public class Bill {//省略细节}<BR>public class PhoneBill extends Bill {//省略细节}<BR>public class GasBill extends Bill {//省略细节}</P>
<P>在处理程序里有一个方法，接受一个Bill类型的对象，计算金额。假设两种账单计算方法不同，而传入的Bill对象可能是两种中的任何一种，所以要用instanceof来判断：</P>
<P>public double calculate(Bill bill) {<BR>if (bill instanceof PhoneBill) {<BR>//计算电话账单<BR>}<BR>if (bill instanceof GasBill) {<BR>//计算燃气账单<BR>}<BR>...<BR>}<BR>这样就可以用一个方法处理两种子类。</P>
<P>然而，这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现，这是面向对象变成应有的做法，避免回到结构化编程模式。只要提供两个名字和返回值都相同，接受参数类型不同的方法就可以了：</P>
<P>public double calculate(PhoneBill bill) {<BR>//计算电话账单<BR>}</P>
<P>public double calculate(GasBill bill) {<BR>//计算燃气账单<BR>}</P>
<P>所以，使用instanceof在绝大多数情况下并不是推荐的做法，应当好好利用多态。<BR>16.&nbsp;认真对待异常。<BR>1).在方法体用throws子句抛出异常时尽量包括所有出现的异常，而不是仅仅抛出base exception.<BR>2).在super class中定义的方法抛出某个异常，如果在deriver class中要override该方法，那么overriding method必须：<BR>a.&nbsp;不抛出任何异常<BR>b.&nbsp;抛出和super class 中同样的异常<BR>c.&nbsp;抛出和super class 中异常的deriver class<BR>如果super class中定义的方法没有抛出异常，但deriver class中的override的方法会产生异常，必须自己内部解决<BR>&nbsp;3).好好利用finally功能。一般只要有finally，它总是会被执行，除非在try中用System.exit(0)或者在try块执行期间强行拔掉电源。finally被执行有三种情况：<BR>a.&nbsp;抛出异常<BR>b.&nbsp;try正常结束<BR>c.&nbsp;在try中执行了return, break, continue而引起离开try的操作<BR>尤其注意c.如果方法中在try块return 1,而在finally块return 2,则最终永远是2，因此尽量避免在try中使用return, break, continue，要么确保在finally中不会改变返回值<BR>&nbsp;4).不要在循环体中使用try,因为在无JIT的JVM中将大大降低性能，而且这也是良好的编程习惯<BR>&nbsp;5).不要将异常用于控制流程，而是仅仅用于会发生错误的地方<BR>&nbsp;6).不要每逢出错就使用异常，尽量使用传统的方法判断变量的有效性<BR>17.&nbsp;关于不可变类(Immutable class),如String、Byte、Integer、Short、Long、Float、Double、BigInteger、BigDecimal等，它们之所以能将同一值自动地指向同一引用，实际上是它们实现了静态工厂方法。</P><img src ="http://www.blogjava.net/gufen/aggbug/13992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gufen/" target="_blank">落花飞雪</a> 2005-09-25 15:22 <a href="http://www.blogjava.net/gufen/archive/2005/09/25/13992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>