??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美jjzz,精品乱码一区二区三区,成人国产一区二区http://www.aygfsteel.com/yuxh/category/42717.htmlwayzh-cnTue, 16 Jun 2015 15:19:25 GMTTue, 16 Jun 2015 15:19:25 GMT60Eclipse中项目maven依赖库错?/title><link>http://www.aygfsteel.com/yuxh/archive/2015/06/02/425441.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Tue, 02 Jun 2015 02:27:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2015/06/02/425441.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/425441.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2015/06/02/425441.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/425441.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/425441.html</trackback:ping><description><![CDATA[新电脑装上eclipse4.4.2Q导入maven目之后Q依赖库L有很多错误。最后搜索到可能是eclipse的bugQ据说是<code>JAVA_HOME没有正确传?/code>Q,查看到eclipse默认的是安装的jre目录Q修改到jdk目录下,依赖问题解决?br />不过目前版本仍然没有解决pom文g?#8220;Plugin execution not covered by lifecycle configuration”错误Q暂时忽略不吧?img src ="http://www.aygfsteel.com/yuxh/aggbug/425441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2015-06-02 10:27 <a href="http://www.aygfsteel.com/yuxh/archive/2015/06/02/425441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA调用重写的祖父方?/title><link>http://www.aygfsteel.com/yuxh/archive/2012/05/31/379647.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Thu, 31 May 2012 03:23:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2012/05/31/379647.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/379647.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2012/05/31/379647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/379647.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/379647.html</trackback:ping><description><![CDATA[本打承一个API中的Parentc(Parentl承自GrandParentc)Q重写其中的serviceҎQcopy了Parent的serviceҎ。不q发现Parent的service中也有super.serviceҎ。当时考虑直接调用GrandParent的serviceҎ。。。未遂(包括反射也不行)。正好看到老外写的一文章,译Q?br />在Sonc里面写一个testҎQ?br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> test() {<br /> </span><span style="color: #0000FF; ">super</span><span style="color: #000000; ">.test();<br /> </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.test();<br />}<br />反编译之后:<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> test()<br />    {<br />    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">    0    0:aload_0         <br />    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">    1    1:invokespecial   #2   <Method void Parent.test()><br />    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">    2    4:aload_0         <br />    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">    3    5:invokevirtual   #3   <Method void test()><br />    </span><span style="color: #008000; ">//</span><span style="color: #008000; ">    4    8:return          </span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    }</span></div>使用ASM可以完成对GrandParentҎ的调?br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> GrandParent {<br />    </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> test() {<br />            System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">test of GrandParent</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />    }<br />}<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> Parent </span><span style="color: #0000FF; ">extends</span><span style="color: #000000; "> GrandParent{<br />    </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> test() {<br />        System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">test of Parent</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />    }<br />}<br /><br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> Son </span><span style="color: #0000FF; ">extends</span><span style="color: #000000; "> Parent{<br />    </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> test() {<br />        System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">test of Son</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />    }<br />}</span></div>调用Son实例的testҎ只会执行Son的testҎ。而ASM可以修改classQ先写一个Examplecȝ承SonQ重写testҎ<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">import</span><span style="color: #000000; "> java.io.FileOutputStream;<br /></span><span style="color: #008080; "> 2</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; "> 3</span> <span style="color: #000000; "></span><span style="color: #0000FF; ">import</span><span style="color: #000000; "> org.objectweb.asm.ClassWriter;<br /></span><span style="color: #008080; "> 4</span> <span style="color: #000000; "></span><span style="color: #0000FF; ">import</span><span style="color: #000000; "> org.objectweb.asm.MethodVisitor;<br /></span><span style="color: #008080; "> 5</span> <span style="color: #000000; "></span><span style="color: #0000FF; ">import</span><span style="color: #000000; "> org.objectweb.asm.Opcodes;<br /></span><span style="color: #008080; "> 6</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; "> 7</span> <span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">class</span><span style="color: #000000; "> ASMByteCodeManipulation </span><span style="color: #0000FF; ">extends</span><span style="color: #000000; "> ClassLoader </span><span style="color: #0000FF; ">implements</span><span style="color: #000000; "> Opcodes {<br /></span><span style="color: #008080; "> 8</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; "> 9</span> <span style="color: #000000; "> </span><span style="color: #0000FF; ">public</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">static</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> main(String args[]) </span><span style="color: #0000FF; ">throws</span><span style="color: #000000; "> Exception {<br /></span><span style="color: #008080; ">10</span> <span style="color: #000000; ">  ClassWriter cw </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> ClassWriter(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">11</span> <span style="color: #000000; ">  cw.visit(V1_1, ACC_PUBLIC, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Example</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Son</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">12</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; ">13</span> <span style="color: #000000; ">  </span><span style="color: #008000; ">//</span><span style="color: #008000; "> creates a MethodWriter for the (implicit) constructor</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">14</span> <span style="color: #008000; "></span><span style="color: #000000; ">  MethodVisitor mw </span><span style="color: #000000; ">=</span><span style="color: #000000; "> cw.visitMethod(ACC_PUBLIC, </span><span style="color: #000000; ">"</span><span style="color: #000000; "><init></span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">,</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">15</span> <span style="color: #000000; ">  mw.visitVarInsn(ALOAD, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">16</span> <span style="color: #000000; ">  mw.visitMethodInsn(INVOKESPECIAL, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Son</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; "><init></span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">17</span> <span style="color: #000000; ">  mw.visitInsn(RETURN);<br /></span><span style="color: #008080; ">18</span> <span style="color: #000000; ">  mw.visitMaxs(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">, </span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">19</span> <span style="color: #000000; ">  mw.visitEnd();<br /></span><span style="color: #008080; ">20</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; ">21</span> <span style="color: #000000; ">  </span><span style="color: #008000; ">//</span><span style="color: #008000; "> creates a MethodWriter for the 'test' method</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">22</span> <span style="color: #008000; "></span><span style="color: #000000; ">  mw </span><span style="color: #000000; ">=</span><span style="color: #000000; "> cw.visitMethod(ACC_PUBLIC, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">test</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">23</span> <span style="color: #000000; ">  mw.visitFieldInsn(GETSTATIC, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">java/lang/System</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">out</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Ljava/io/PrintStream;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">24</span> <span style="color: #000000; ">  mw.visitLdcInsn(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">test of AI3</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">25</span> <span style="color: #000000; ">  mw.visitMethodInsn(INVOKEVIRTUAL, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">java/io/PrintStream</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">println</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,<br /></span><span style="color: #008080; ">26</span> <span style="color: #000000; ">    </span><span style="color: #000000; ">"</span><span style="color: #000000; ">(Ljava/lang/String;)V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">27</span> <span style="color: #000000; ">  </span><span style="color: #008000; ">//</span><span style="color: #008000; ">Call test() of GrandParent</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">28</span> <span style="color: #008000; "></span><span style="color: #000000; ">  mw.visitVarInsn(ALOAD, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">29</span> <span style="color: #000000; ">  mw.visitMethodInsn(INVOKESPECIAL, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">GrandParent</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">test</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">30</span> <span style="color: #000000; ">  </span><span style="color: #008000; ">//</span><span style="color: #008000; ">Call test() of GrandParent</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">31</span> <span style="color: #008000; "></span><span style="color: #000000; ">  mw.visitVarInsn(ALOAD, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">32</span> <span style="color: #000000; ">  mw.visitMethodInsn(INVOKESPECIAL, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Parent</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">test</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">33</span> <span style="color: #000000; ">  </span><span style="color: #008000; ">//</span><span style="color: #008000; ">Call test() of GrandParent</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">34</span> <span style="color: #008000; "></span><span style="color: #000000; ">  mw.visitVarInsn(ALOAD, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">35</span> <span style="color: #000000; ">  mw.visitMethodInsn(INVOKESPECIAL, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Son</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">test</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">"</span><span style="color: #000000; ">()V</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">36</span> <span style="color: #000000; ">  mw.visitInsn(RETURN);<br /></span><span style="color: #008080; ">37</span> <span style="color: #000000; ">  mw.visitMaxs(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">, </span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">38</span> <span style="color: #000000; ">  mw.visitEnd();<br /></span><span style="color: #008080; ">39</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; ">40</span> <span style="color: #000000; ">  </span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">[] code </span><span style="color: #000000; ">=</span><span style="color: #000000; "> cw.toByteArray();<br /></span><span style="color: #008080; ">41</span> <span style="color: #000000; ">  FileOutputStream fos </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> FileOutputStream(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Example.class</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">42</span> <span style="color: #000000; ">  fos.write(code);<br /></span><span style="color: #008080; ">43</span> <span style="color: #000000; ">  fos.close();<br /></span><span style="color: #008080; ">44</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; ">45</span> <span style="color: #000000; ">  ASMByteCodeManipulation loader </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">new</span><span style="color: #000000; "> ASMByteCodeManipulation();<br /></span><span style="color: #008080; ">46</span> <span style="color: #000000; ">  Class</span><span style="color: #000000; "><?></span><span style="color: #000000; "> exampleClass </span><span style="color: #000000; ">=</span><span style="color: #000000; "> loader.defineClass(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Example</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, code, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">,<br /></span><span style="color: #008080; ">47</span> <span style="color: #000000; ">    code.length);<br /></span><span style="color: #008080; ">48</span> <span style="color: #000000; ">  Object obj </span><span style="color: #000000; ">=</span><span style="color: #000000; "> exampleClass.newInstance();<br /></span><span style="color: #008080; ">49</span> <span style="color: #000000; ">  exampleClass.getMethod(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">test</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">).invoke(obj, </span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">50</span> <span style="color: #000000; "> <br /></span><span style="color: #008080; ">51</span> <span style="color: #000000; "> }<br /></span><span style="color: #008080; ">52</span> <span style="color: #000000;">}</span></div>输出Q?br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">test of AI3<br />test of GrandParent<br />test of Parent<br />test of Son</span></div>看看怎样实现的,11行定义一个新的类Examplel承Son?2行,Example重写testҎQ先打印“test of AI3”Q再分别?9?2?5行调?span style="color: #000000; ">GrandParent、Parent、Son的testҎ?/span><div></div><div> mainҎ中,45行创建Example的实例,再用反射调他的testҎ?br />使用invokespecialq种方式也有局限,只能从子c调用。否则报错:<div><strong>Exception in thread "main" java.lang.VerifyError: (class: Example, method: test1 signature: (LAI2;)V) Illegal use of nonvirtual function call</strong></div></div><img src ="http://www.aygfsteel.com/yuxh/aggbug/379647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2012-05-31 11:23 <a href="http://www.aygfsteel.com/yuxh/archive/2012/05/31/379647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java时区处理http://www.aygfsteel.com/yuxh/archive/2012/03/15/371982.htmlyuxhyuxhThu, 15 Mar 2012 15:08:00 GMThttp://www.aygfsteel.com/yuxh/archive/2012/03/15/371982.htmlhttp://www.aygfsteel.com/yuxh/comments/371982.htmlhttp://www.aygfsteel.com/yuxh/archive/2012/03/15/371982.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/371982.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/371982.html
通用协调?UTC, Universal Time Coordinated)Q格林尼d^均时(GMT, Greenwich Mean Time) ׃历史原因Q这两个旉是一L?div>北京时区是东八区Q领先UTC八个时Q在电子邮g信头的Date域记?0800?div>转换中,最重要的公式就是:
UTC Q?时区?Q?本地旉
    public static Calendar convertToGmt(Calendar cal) {
        Date date 
= cal.getTime();
        TimeZone tz 
= cal.getTimeZone();

        System.out.println(
"input calendar has date [" + date + "]");

        
// Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
        long msFromEpochGmt = date.getTime();

        
// gives you the current offset in ms from GMT at the current date
        int offsetFromUTC = tz.getOffset(msFromEpochGmt);
        System.out.println(
"offset is " + offsetFromUTC);

        
// create a new calendar in GMT timezone, set to this date and add the offset     
        Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        Calendar utcCal 
= Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        gmtCal.setTime(date);
        //Ҏ东西时区Q选择offsetFromUTC为正或负?/span>
        gmtCal.add(Calendar.MILLISECOND, offsetFromUTC);

        utcCal.setTime(date);
        utcCal.add(Calendar.MILLISECOND, offsetFromUTC);

        System.out.println(
"Created GMT cal with date [" + gmtCal.getTime()
                
+ "==" + utcCal.getTime() + "]");
        
return gmtCal;
    }


yuxh 2012-03-15 23:08 发表评论
]]>
区分getPath(), getAbsolutePath(), getCanonicalPath()http://www.aygfsteel.com/yuxh/archive/2011/06/24/352951.htmlyuxhyuxhFri, 24 Jun 2011 05:42:00 GMThttp://www.aygfsteel.com/yuxh/archive/2011/06/24/352951.htmlhttp://www.aygfsteel.com/yuxh/comments/352951.htmlhttp://www.aygfsteel.com/yuxh/archive/2011/06/24/352951.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/352951.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/352951.html

来自

http://stackoverflow.com/questions/1099300/whats-the-difference-between-getpath-getabsolutepath-and-getcanonicalpath

C:\temp\file.txt" - this is a path, an absolute path, a canonical path

.\file.txt This is a path, It's not an absolute path nor canonical path.

C:\temp\myapp\bin\..\\..\file.txt This is a path, and an absolute path, it's not a canonical path

Canonical path is always an absolute path.

Converting from a path to a canonical path makes it absolute (通常会处理改变当前目录,所以像. ./file.txt 变ؓc:/temp/file.txt). The canonical path of a file just "purifies" the path, 去除和解析类?#8220; ..\” and resolving symlinks(on unixes)

In short:

  • getPath() gets the path string that the File object was constructed with, and it may be relative current directory.
  • getAbsolutePath() gets the path string after resolving it against the current directory if it's relative, resulting in a fully qualified path.
  • getCanonicalPath() gets the path string after resolving any relative path against current directory, and removes any relative pathing (. and ..), and any file system links to return a path which the file system considers the canonical means to reference the file system object to which it points.

Also, each of this has a File equivalent which returns the corresponding File object.

The best way I have found to get a feel for things like this is to try them out:

import java.io.File;
public class PathTesting {
        public static void main(String [] args) {
                File f = new File("test/.././file.txt");
                System.out.println(f.getPath());
                System.out.println(f.getAbsolutePath());
                try {
                        System.out.println(f.getCanonicalPath());
                }
                catch(Exception e) {}
        }
}

Your output will be something like:

test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt

So, getPath() gives you the path based on the File object, which may or may not be relative; getAbsolutePath() gives you an absolute path to the file; and getCanonicalPath() gives you the unique absolute path to the file. Notice that there are a huge number of absolute paths that point to the same file, but only one canonical path.

When to use each? Depends on what you're trying to accomplish, but if you were trying to see if two Files are pointing at the same file on disk, you could compare their canonical paths.


yuxh 2011-06-24 13:42 发表评论
]]>
路径斜杠处理http://www.aygfsteel.com/yuxh/archive/2011/06/15/352358.htmlyuxhyuxhWed, 15 Jun 2011 06:47:00 GMThttp://www.aygfsteel.com/yuxh/archive/2011/06/15/352358.htmlhttp://www.aygfsteel.com/yuxh/comments/352358.htmlhttp://www.aygfsteel.com/yuxh/archive/2011/06/15/352358.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/352358.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/352358.html阅读全文

yuxh 2011-06-15 14:47 发表评论
]]>
Java PuzzlersQ三-?循环Q?/title><link>http://www.aygfsteel.com/yuxh/archive/2010/11/15/338121.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Mon, 15 Nov 2010 11:59:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2010/11/15/338121.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/338121.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2010/11/15/338121.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/338121.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/338121.html</trackback:ping><description><![CDATA[<p>31 <br>while (i != 0)<br>    i >>>= 1; //无符号右U,不管正负左边都是?<br>Z表达式合法,q里的i必须是整?<tt>byte</tt>, <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, or <tt>long</tt>)。谜题的关键在于<tt>>>>=</tt> 是一个复合赋值操作符Q不q的是复合赋值操作符会默默的?span class="docEmphasis">narrowing primitive conversionsQ即从一个数据类型{换ؓ一个更的数据cd?span class="docEmphStrong">Narrowing primitive conversions can lose information about the magnitude or precision of numeric values</span>。ؓ了问题更具体,假设q样定义Q?br>short i = -1; 因ؓ初始值i (<tt>(short)0xffff</tt>) 非零Q@环执行。第一步位UM把i提升为int?tt>short</tt>, <tt>byte</tt>, or <tt>char</tt>cd的操作数都会做这L操作。这?span class="docEmphasis">widening</span> primitive conversionQ没有信息丢失。这U提升有W号扩展Q因此结果是int?tt>0xffffffff</tt>。无W号右移一位生int?tt>0x7fffffff</tt>。ؓ了把int值存回short变量QJava执行了可怕的narrowing primitive conversion,即简单去掉高十六位。这样又变回?tt>(short)0xffff</tt>。如果定义类?tt>short</tt> or <tt>byte</tt>型的负数Q都会得到类似结果。你如果定义的是char话,则不会无限@环,因ؓchar值非负,位移之前的宽扩展不会做符h展?br><br>ȝQ?span style="color: red">不要?tt>short</tt>, <tt>byte</tt>, or <tt>char</tt>变量上用复合赋值操作符</span>。这U表辑ּq行混合cd计算Q非常容易؜淆。更p糕的是隐含的窄映射会丢掉信息?br><br>32 <br>while (i <= j && j <= i && i != j) {}<br><tt>i <= j</tt> and <tt>j <= i</tt>, surely <tt>i</tt> must equal <tt>j</tt>Q对于实数来说是q样的。他非常重要Q有个名UͼThe ?relation on the real numbers is said to be <span id="wmqeeuq" class="docEmphasis">antisymmetric。Java's <tt><=</tt> operator used to be antisymmetric before release 5.0, but no longer.Java 5之前数据比较W号(<tt><, <=</tt>, <tt>></tt>, and <tt>>=</tt>) 需要两边的操作数必Mؓ基础cd(<tt>byte</tt>, <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, <tt>float</tt>, or <tt>double).在Java 5变ؓ两边操作Cؓ凡是可{变ؓ基础cd的类型。java 5引入autoboxing and auto-unboxing 。The boxed numeric types are <tt>Byte</tt>, <tt>Character</tt>, <tt>Short</tt>, <tt>Integer</tt>, <tt>Long</tt>, <tt>Float</tt>, and <tt>Double。具体点Q让上面q入无限循环Q?br></tt></tt></span>Integer i = new Integer(0);<br>Integer j = new Integer(0);<br> (<tt>i <= j</tt> and <tt>j <= i</tt>) perform <span id="wmqeeuq" class="docEmphasis">unboxing conversions</span> on <tt>i</tt> and <tt>j</tt> and compare the resulting <tt>int</tt> values numerically。i和j表示0Q所以表辑ּ为true?tt>i != j</tt>比较的是对象引用Q也为true。很奇怪规范没有把{号改ؓ比较倹{原因很单:兼容性。当一U语aq泛应用的时候,不能破坏已存在的规范来改变程序的行ؓ。System.out.println(new Integer(0) == new Integer(0));L输出falseQ所以必M留。当一个是boxed numeric cdQ另一个是基本cd的时候可以值比较。因为java 5之前q是非法的,具体点:<br>System.out.println(new Integer(0) == 0); //之前的版本非法,Java 5输出True<br>ȝQ?span style="color: red">当两边的操作数是boxed numericcd的时候,数字比较W和{于W号是根本不同的Q数字比较符是值比较,{号比较的是对象引用</span>?br><br>33 <br>while (i != 0 && i == -i) {}<br>有负可Ci一定是数字QNaN不行Q因Z不等于Q何数。事实上Q没有实数可以出现这U情c但Java的数字类型ƈ没有完美表达实数。QҎ׃个符号位Q一个有效数字(数Q,一个指数构成。QҎ只有0才会和自q负数相等Q所以i肯定是整数。有W号整数用的是二q制补码计算Q取反加一。补码的一大优势是用一个唯一的数来表C?。然而有一个对应的~点Q本来可表达偶数个|现在用一个表达了0Q剩下奇C来表C正负数Q意味着正数和负数的数量不一栗比如int|他的<tt>Integer.MIN_VALUE</tt>Q?tt>-2</tt><sup>31</sup>Q。十六进制表?tt>0x8000000</tt>。通过补码计算可知他的负数仍然不变。对他取负数是溢Z的,不过Java在整数计中忽略了溢出?br>ȝQJava使用二进制补码,是不对称的。有W号整数(<tt>int</tt>, <tt>long</tt>, <tt>byte</tt>, and <tt>short</tt>) 负数值比整数值多一个?br><br>34<br>        final int START = 2000000000;<br>        int count = 0;<br>        for (float f = START; f < START + 50; f++)<br>            count++;<br>        System.out.println(count);<br>注意循环变量是float。回忆谜?8 Q明显f++没有M作用。f的初始化值接q?tt>Integer.MAX_VALUE</tt>Q因此需?1位来准确表达Q但是floatcd只提供了24位精度。增加这样大的一个floatg会改变倹{看h会死循环Q运行程序会发现Q输?。@环中f?tt>(float)(START + 50)做比较。但int和float比较的时候,自动把int先提CZؓfloat。不q的是三个会引v_ֺ丢失的宽基本cd转换的其中之一Q另外两个是long到floatQlong到doubleQ。f的初始值巨大,?0再{换ؓfloat和直接把f转换为float是一L效果Q即<tt>(float)2000000000 == 2000000050Q所?tt>f < START + 50</tt> p|。只要把float改ؓint卛_修正?br></tt></tt>     没有计算器,你怎么知道 2,000,000,050 和float表示2,000,000,000一P…?br>The moral of this puzzle is simple: <span style="color: red" class="docEmphStrong">Do not use floating-point loop indices</span>, because it can lead to unpredictable behavior. If you need a floating-point value in the body of a loop, take the <tt>int</tt> or <tt>long</tt> loop index and convert it to a <tt>float</tt> or <tt>double</tt>. <span id="wmqeeuq" class="docEmphStrong">You may lose precision when converting an <tt>int</tt> or <tt>long</tt> to a <tt>float</tt> or a <tt>long</tt> to a <tt>double</tt></span>, but at least it will not affect the loop itself. <span id="wmqeeuq" class="docEmphStrong">When you use floating-point, use <tt>double</tt> rather than <tt>float</tt></span> unless you are certain that <tt>float</tt> provides enough precision <span id="wmqeeuq" class="docEmphasis">and</span> you have a compelling performance need to use <tt>float</tt>. The times when it's appropriate to use <tt>float</tt> rather than <tt>double</tt> are few and far between?br></span></p> <p><span id="wmqeeuq" class="docEmphasis">35 <br></span><span id="wmqeeuq" class="docEmphasis">下面E序模拟一个简单的旉<br>int minutes = 0; <br>for (int ms = 0; ms < 60*60*1000; ms++) <br>  if (ms %  60*1000 == 0) <br>     minutes++; <br> </span><span id="wmqeeuq" class="docEmphasis">System.out.println(minutes); </span><span id="wmqeeuq" class="docEmphasis"><br>l果?tt>60000Q问题在于布表辑ּms % 60*1000 == 0Q最单的修改Ҏ是:if (ms % (60 * 1000) == 0) <br>更好的方法是<font color="#ff0000">用合适命名的帔R代替力数字</font>Q?/tt></span></p> <p><span id="wmqeeuq" class="docEmphasis"><tt></tt></span>private static final int MS_PER_HOUR = 60 * 60 * 1000; <br>private static final int MS_PER_MINUTE = 60 * 1000; <br>public static void main(String[] args) {<br>   int minutes = 0; <br>   for (int ms = 0; ms < MS_PER_HOUR; ms++) <br>     if (ms % MS_PER_MINUTE == 0) <br>        minutes++;<br>    System.out.println(minutes); <br>} <span id="wmqeeuq" class="docEmphasis"><br><font color="#ff0000">l不要用I格来分l;使用括号来决定优先</font></p></span><img src ="http://www.aygfsteel.com/yuxh/aggbug/338121.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2010-11-15 19:59 <a href="http://www.aygfsteel.com/yuxh/archive/2010/11/15/338121.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java PuzzlersQ三-一 循环Q?/title><link>http://www.aygfsteel.com/yuxh/archive/2010/11/15/336547.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Mon, 15 Nov 2010 08:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2010/11/15/336547.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/336547.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2010/11/15/336547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/336547.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/336547.html</trackback:ping><description><![CDATA[<span style="color: #000000">24      <br />   for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) {<br />         if (b == 0x90)<br />             System.out.print("Joy!");<br />     }<br /> <tt>Ox90</tt> 过了byte的取D?font face="Courier New">-128?27。byte和int比较是一U؜合类型比较。考虑个表辑ּ<tt>((byte)0x90 == 0x90)得到的是false。byte和int做比较的时候,Java先对byteq行了widening primitive conversion 再比较两个int倹{因为byte是有W号cdQ{变做了符h展,把负的byteD{换ؓ相应的int倹{这个例子中(byte)0x90被{变ؓ-112Q当然不{于int?<tt>0x90</tt>或者说+144。؜合比较总让惑,因ؓLpȝL升一个操作数来和另一U类型匹配。有几种方式可避免؜合比较。可以把int映射为byteQ之后比较两个byte| <br /> if (b == (byte)0x90)<br />     System.out.println("Joy!");<br /> 另外Q可用mask抑制W号扩展Q把byte转换为intQ之后比较两个int|<br /> if ((b & 0xff) == 0x90)<br />     System.out.println("Joy!");<br /> 但最好的Ҏ是把帔R值移出@环放到常量声明中?br /> <span id="wmqeeuq" class="docEmphStrong">    private static final byte TARGET = 0x90; // Broken!</span><br />     public static void main(String[] args) {<br />         for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++)<br />             if (b == TARGET)<br />                 System.out.print("Joy!");<br />     }<br /> 不幸的是Q上面编译通不q:<tt>0x90</tt>对于bytecd来说不是一个有效倹{这样修改即可:<br /> private static final byte TARGET = <span id="wmqeeuq" class="docEmphStrong">(byte)</span>0x90;<br /> <p class="docText">To summarize: <span id="wmqeeuq" class="docEmphStrong">Avoid mixed-type comparisons, because they are inherently confusing</span> (<a class="docLink" href="ch02lev1sec5.html#ch02lev1sec5">Puzzle 5</a>). To help achieve this goal, <span id="wmqeeuq" class="docEmphStrong">use declared constants in place of "magic numbers." </span>You already knew that this was a good idea; it documents the meanings of constants, centralizes their definitions, and eliminates duplicate definitions.现在你知道他q可以强制你为每一个常量定义适用的类型,避免一U؜合类型比较的来源?/p> <p class="docText">25 <br /> </span<br /> <font color="#000000">int j = 0;<br /> for (int i = 0; i < 100; i++)<br />   j = j++;<br /> System.out.println(j); //</font><font color="#000000">打印出的?<span></p> </font></tt></font> <p>问题出在 j = j++; {同于下列操作:</p> <p>int tmp = j; j = j + 1; j = tmp; <br /> q次的教训和N7一P<font color="#ff0000">在一个表辑ּ中不要给同一个变量赋Dq一ơ?/font></p> <p><font color="#000000">26</font></p> <p><font color="#000000">public static final int END = Integer.MAX_VALUE;<br /> public static final int START = END - 100;<br /> public static void main(String[] args) {<br />     int count = 0;<br />     for (int i = START; i <= END; i++)<br />        count++;<br />      System.out.println(count);<br /> }<br /> 看v来像100Q再仔细看@环是于{于Q应该是101Q结果是E序没有输出M|陷入一个死循环。问题出?tt>Integer.MAX_VALUEQ当l箋增加的时候,他悄悄变?tt>Integer.MIN_VALUE。如果你需要@环intD界,最好用long变量做烦引:<br /> for (long i = START; i <= END; i++)  //输出101<br /> <font color="#ff0000">教训是:<tt>int</tt>s are not integers。无Z时用基本cdQ注意边界倹{上溢或下溢会出C么情况?一般来说最好用大一点的cdQ基本类型是<tt>byte</tt>, <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, and <tt>long</tt>Q?/font>也可以不用longQ?/tt></tt></font></p> <p><font color="#000000">int i = START; <br /> do { <br />   count++; <br /> } while (i++ != END); <br /> 考虑到清晰和单,L用long索引Q除了一U特D情况:如果要遍历所有int|q样用int索引的话会快两倍?br /> 一个@环四十亿int|调用Ҏ的常规用法:</font><font color="#ff0000"></p> <pre><font color="#000000">// Apply the function f to all four billion int values int i = Integer.MIN_VALUE; do { f(i); } while (i++ != Integer.MAX_VALUE); </font></pre> <p><span style="color: #000000">27  位移<br /> <font color="#ff0000"><span style="color: #000000"><font style="color: #000000" color="#ff0000">Cjava是用二q制补码计算Q在M有符号基本类型中(<tt>byte</tt>, <tt>short</tt>, <tt>int</tt>, or <tt>long</tt>)都是用所有位|?来表C?1?<br /> </font><font color="#ff0000"><span style="color: #000000"><font color="#ff0000">        <span style="color: #000000"><font style="color: #000000" color="#ff0000">int i = 0;<br />         while (-1 << i != 0)       //左位U?br />             i++;<br />         System.out.println(i);<br /> </font>int型的-1?tt>0xffffffff</tt> 表示。不断左U,双?补位。移?2ơ,变ؓ?Q蟩出@环打?2Q实际上E序会死循环。问题出?1<<32不等?而是{于-1Q因Z<span style="color: #ff0000">Uȝ号只用右Ҏ作数的低五位作ؓUd距离</span>Q如果左操作数是long的话用六位。三个位UL作符Q?lt;<,>>,>>>都是q样。移动距LL0?1Q左Ҏ作数是long的话0?3。位U距ȝ32取模Q左Ҏlong则用64取模。给intgU?2位或llonggU?4位只会返回本w。所以不可能用位Ud全移除一个数据。幸q的是,有一个简单的办法解决q个问题。保存上一ơ的位移l果Q每一ơP代多Ud一位?br />         int distance = 0;<br />         for (int val = -1; val != 0; val <<= 1)<br />             distance++;<br />         System.out.println(distance);<br /> 修改后的E序说明了一个原则:<span style="color: #ff0000">位移距离如果可能的话Q用帔R</span>?br /> 另外一个问题,许多E序员认为右UM个负的移动距,和左移一P反之亦然。事实上不是q样Q左UL左移Q右Ud是右UR负数距d留下低五位(long留六位)Q其余的|?变Z正数距离。比如,左移一个int?1的距,实际上是左移31位?br /> <br /> 28 无穷的表C?br /> for (int i = start; i <= start + 1; i++) {<br /> }<br /> 看v来@环两ơ就会结束,如果q样定义呢:<br /> int start = Integer.MAX_VALUE - 1;//d@?br /> while (i == i + 1) {<br /> }<br /> q个不可能死循环Q如果i是无I呢QJava采用IEEE 754点数算术,用double或float来表C无I所以可以用M点数计表辑ּ得出无穷来初始化i。比如:double i = 1.0 / 0.0;<br /> 更好的是可以利用标准库提供的帔R:double i = Double.POSITIVE_INFINITY;<br /> 事实上,Ҏ用不着用无I初始化i来引h循环。只要够大的QҎ够了:double i = 1.0e40;<br /> q是因ؓ点数越大,他的值和下一个数的DMp大。distribution of floating-point values is a consequence of their representation with a fixed number of <u>significant</u> bits. l够大的QҎ加一不会改变|因ؓ他不能填充这个数和下一个数之间的距RQҎ操作q回最接近准确数学l果的Q点倹{一旦两个相LQ点g间的距离大于2Q加1׃会有效果。floatcd来说Q超q?<sup>25</sup>Q或33,554,432Q再?无效;对double来说过2<sup>54</sup>Q接q?.8 x 10<sup>16</sup>Q再?无效?br />      盔R点C间的距离UCؓulpQunit in the last place的羃写)。在Java 5?<tt>Math.ulpҎ被引入来计算float或double值的ulp?/tt></span></font></span></font></span></font></span></p> <p><span style="color: #000000"><font color="#ff0000"><span style="color: #000000"><font color="#ff0000"><span style="color: #000000"><font color="#ff0000"><span style="color: #000000"><tt>ȝQ?font color="#ff0000">不可能用float或double来表C无I另外,在一个大的QҎ上加一个小的QҎQg会改变。有点不合常理,实数q不是这栗记住二q制点数计只是近g实数计算?/font></tt></span></font></span></font></span></font></span></p> <p></font><font color="#ff0000"><span style="color: #000000"><span style="color: #000000"><span style="color: #000000"><span style="color: #000000"><tt>29 NaN</tt></span></span></span></span></font></span></span></p> <p>while (i != i) { } <br /> IEEE 754 点数计保留了一个特D值来来表CZ是数字的数量。NaN是Q点计不能很好定义的敎ͼ比如<tt>0.0 / 0.0。规范定?font color="#ff0000">NaN不等于Q何数包括自己</font>。因此double i = 0.0 / 0.0; 可让开始的{式不成立。也有标准库定义的常量:</tt>double i = Double.NaN; 如果一个或多个操作CؓNaNQ那么QҎ计算׃{于NaN?/p> <p>ȝQfloat和doule存在Ҏ的值NaNQ小心处理?/p> <p>30<br /> while (i != i + 0) { } q一ơ不能用float或者double?br /> <tt>+操作W除了数字,只能处理String?操作W会被重载:对于StringcdQ他做的是连接操作。如果操作数有非StringcdQ会先做转换变ؓString之后再做q接。i一般用作数字,要是对String型变量这么命名容易引赯解?/tt></p> <p><tt>ȝQ?font color="#ff0000">操作W重载非常容易误gh。好的变量名Q方法名Q类名和好的注释对于E序的可L一样重要?/font></tt></p> <img src ="http://www.aygfsteel.com/yuxh/aggbug/336547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2010-11-15 16:39 <a href="http://www.aygfsteel.com/yuxh/archive/2010/11/15/336547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java PuzzlersQ二-?字符Q?/title><link>http://www.aygfsteel.com/yuxh/archive/2010/10/30/335872.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Sat, 30 Oct 2010 05:46:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2010/10/30/335872.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/335872.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2010/10/30/335872.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/335872.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/335872.html</trackback:ping><description><![CDATA[19  单行注释<br />     public static void main(String[] args) {<br />         System.out.println(classify('n') + classify('+') + classify('2'));<br />     }<br />     static String classify(char ch) {<br />         if ("0123456789".indexOf(ch) >= 0)<br />             return "NUMERAL ";<br />         if ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)<br />             return "LETTER ";<br />        /* (Operators not supported yet)<br />         if ("+-<span style="color: red">*/</span>&|!=".indexOf(ch) >= 0)<br />             return "OPERATOR ";<br />        */<br />         return "UNKNOWN ";<br />     }<br /> ~译出错Q块注释不能嵌套Q在注释内的文本都不会被Ҏ对待?br /> <span id="wmqeeuq" class="docEmphStrong">// Code commented out with an if statement - doesn't always work!<br /> if (false) {</span><br />     /* Add the numbers from 1 to n */<br />     int sum = 0;<br />     for (int i = 1; i <= n; i++)<br />         sum += i;<br /> <span id="wmqeeuq" class="docEmphStrong">}</span><br /> q是语言规范推荐的一U条件编译的技术,但不是非帔R合注释代码。除非包含的语句都是有效的表辑ּQ否则这U条件编译不能用作注释。最好的注释代码Ҏ是用单行注释?br /> <br /> 20   反斜?br />    <tt>Me.class.getName()</tt> q回的是Mecȝ完整名,?tt>"com.javapuzzlers.Me"</tt>?nbsp;<br />    System.out.println( Me.class.getName().replaceAll(".", "/") + ".class"); <br />    应该得到<tt>com/javapuzzlers/Me.class</tt>Q不寏V问题出?span class="docEmphStrong"><tt>String.replaceAll</tt></span>把正则表辑ּ作ؓW一个参敎ͼ而不是字W。正则表达是“.”表示配对M单独的字W,所以类名的每一个字W都被斜U替代。ؓ了只匚w句号Q必ȝ反斜U(\Q{义。因为反斜线在字W串中有Ҏ意义——它是escape sequence的开始——反斜线自n也必ȝ一个反斜线转义?br /> 正确QSystem.out.println( Me.class.getName().replaceAll(<span id="wmqeeuq" class="docEmphStrong">"\\."</span>, "/") + ".class");<br /> Z解决q类问题Qjava 5提供了一个新的静态方?tt>java.util.regex.Pattern.quote</tt>。用一个字W串作ؓ参数Q增加Q何需要的转义Q返回一个和输入字符串完全匹配的正则表达式字W串Q?br />   System.out.println(Me.class.getName().replaceAll(<span id="wmqeeuq" class="docEmphStrong">Pattern.quote(".")</span>, "/") + ".class");<br /> q个E序的另外一问题是依赖于^台。不是所有的文gpȝ都是用斜U来l织文g。ؓ了在你运行的q_取得正确的文件名Q你必须使用正确的^台分隔符来替换斜Uѝ?br /> <br /> 21 <br />     System.out.println(MeToo.class.getName().<br />     replaceAll("\\.", File.separator) + ".class");<br /> <tt>java.io.File.separator</tt> 是一个公q<tt>String</tt> 属性,指定用来包含q_依赖的文件名分隔W。在UNIX上运行打?tt>com/javapuzzlers/MeToo.class</tt>。然而,在Windows上程序抛出异常:<br />     StringIndexOutOfBoundsException: String index out of range: 1<br /> l果?tt>String.replaceAll</tt> 的第二个参数不是普通字W串而是一个在<tt>java.util.regex</tt> 规范中定义的 <span id="wmqeeuq" class="docEmphasis">replacement stringQ反斜线转义了后面的字符。当在Windows上运行的时候,替换字符是一个单独的反斜U,无效。JAVA 5提供了两个新Ҏ来解册个问题,一个是<tt>java.util.regex.Matcher.quoteReplacementQ它替换字符串ؓ相应的替换字W串Q?br />  System.out.println(MeToo.class.getName().replaceAll(<br />    "\\.",  <span id="wmqeeuq" class="docEmphStrong">Matcher.quoteReplacement(File.separator)</span>)+".class");<br /> W二个方法提供了更好的解x法?tt>String.replace(CharSequence, CharSequence)?tt>String.replaceAll</tt>做同L事情Q但他把两个参数都作为字W串处理QSystem.out.println(MeToo.class.getName().<span id="wmqeeuq" class="docEmphStrong">replace(".", File.separator)</span> + ".class");   <br /> 如果用的是java早期版本没有简单的Ҏ产生替换字符丌Ӏ完全不用正则表辑ּQ?tt>String.replace(char, char)跟容易一些:<br /> System.out.println(MeToo.class.getName().<span id="wmqeeuq" class="docEmphStrong">replace('.', File.separatorChar) + ".class");</span><br /> <span style="color: red">教训Q当用不熟悉的库Ҏ的时候,心炏V有怀疑的话,查看Javadoc</span>。当然正则表辑ּ也很手Q他~译时可能没问题q行时却更容易出错?/tt></tt></tt></span> <br /> <br /> 22  <span id="wmqeeuq" class="docEmphasis">statement label</span><br />      <span style="color: red">认真写注释,及时更新。去掉无用代?/span>。如果有东西看v来奇怪不真实Q很有可能是错误的?<br /> 23<br />    <font color="#3333cc"> private static Random rnd = new Random();<br />     public static void main(String[] args) {<br />       StringBuffer word = null;<br />       switch(rnd.nextInt(2)) {<br />           case 1:  word = new StringBuffer('P');<br />           case 2:  word = new StringBuffer('G');<br />           default: word = new StringBuffer('M');<br />       }<br />       word.append('a');<br />       word.append('i');<br />       word.append('n');<br />       System.out.println(word);<br />    }<br /> <span style="color: rgb(0,0,0)">在一ơ又一ơ的q行中,以相{的概率打印出PainQGain?MainQ答案它L在打印ain。一共有三个bugDq种情况?br /> </span>一?<tt>Random.nextInt(int)</tt> Q看规范可知q里q回的是0到intg间的前闭后开区间的随机数。因此程序中永远不会q回2?/font><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">q是一个相当常见的问题源,被熟知ؓ“栅栏柱错误(fencepost errorQ?#8221;。这个名字来源于对下面这个问题最常见的但却是错误的答案,如果你要建造一?00英尺长的栅栏Q其栅栏柱间隔ؓ10英尺Q那么你需要多根栅栏柱呢Q?1Ҏ9栚w是正答案,q取决于是否要在栅栏的两端树立栅栏柱Q但?0根却是错误的。要当心栅栏柱错误,每当你在处理长度、范围或模数的时候,都要仔细定其端Ҏ否应该被包括在内Qƈ且要保你的代码的行与其相对应?br /> W二个bug?case没有配套?/span></span><tt>break</tt>?span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">?.0版本Pjavac提供?Xlint:fallthrough标志Q当你忘记在一个case与下一个case之间dbreak语句是,它可以生成警告信息。不要从一个非I的case向下q入了另一个case。这是一U拙劣的风格Q因为它q不常用Q因此会误导读者。十ơ中有九ơ它都会包含错误。如果Java不是模仿C建模的,那么它倒是有可能不需要break。对语言设计者的教训是:应该考虑提供一个结构化的switch语句?br /> </span></span><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">最后一个,也是最微妙的一个bug是表辑ּnew StringBuffer(‘M')可能没有做哪些你希望它做的事情。S</span></span><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">tringBuffer(char)构造器Ҏ不存在?/span></span><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">StringBuffer有一个无参数的构造器Q一个接受一个String作ؓ字符串缓冲区初始内容的构造器Q以及一个接受一个int作ؓ~冲区初始容量的构造器。在本例中,~译器会选择接受int的构造器Q通过拓宽原始cd转换把字W数?M'转换Z个int数?7[JLS 5.1.2]。换句话_new StringBuffer(‘M')q回的是一个具有初始容?7的空的字W串~冲区。该E序余下的部分将字符a、i和ndCq个I字W串~冲ZQƈ打印字符串缓冲区那Lain的内?span style="color: red"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">?span style="color: rgb(255,0,0)"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span"><span style="color: red"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span"><span style="color: red"><span style="color: red"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span"><span style="color: red"> <span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; font-size: 14px" class="Apple-style-span"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; font-size: 14px" class="Apple-style-span"><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; font-size: 14px" class="Apple-style-span">Z避免q类问题Q不在什么时候,都要可能用熟悉的惯用法和API</span></span></span></span></span></span></span>。如果你必须使用不熟悉的APIQ那么请仔细阅读其文?/span></span></span></span></span></span></span></span></span><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">?/span></span></span></span></span></span></span></span><span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 19px; font-family: 宋体,Arial; color: rgb(51,51,51); font-size: 14px" class="Apple-style-span">在本例中Q程序应该用常用的接受一个String的StringBuffer构造器?/span></span> <img src ="http://www.aygfsteel.com/yuxh/aggbug/335872.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2010-10-30 13:46 <a href="http://www.aygfsteel.com/yuxh/archive/2010/10/30/335872.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Puzzlers(?一 字符)http://www.aygfsteel.com/yuxh/archive/2010/10/22/335023.htmlyuxhyuxhFri, 22 Oct 2010 00:49:00 GMThttp://www.aygfsteel.com/yuxh/archive/2010/10/22/335023.htmlhttp://www.aygfsteel.com/yuxh/comments/335023.htmlhttp://www.aygfsteel.com/yuxh/archive/2010/10/22/335023.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/335023.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/335023.html       System.out.print("H" + "a");System.out.print('H' + 'a'); //貌似输出HaHaQ?/tt>
       最后输出的?tt>Ha169
?tt>'H' ?tt>'a' 都是 charQ不?tt>StringQ?操作W做的是加法操作而不是拼接字W串。编译器提升两个char值到int|?6位零扩展?2位的int。一个是72另一个是97。从语义上说Qchar值和字符串的怼是非常迷惑的。java语言仅仅把char看做无符L16位基本整数。库不这栯为,他里面有许多Ҏ把char参数当作Unicode字符在处理。怎样q接字符Q可以用库ҎQ如Q?br />      StringBuffer sb = new StringBuffer();
     sb.append('H');sb.append('a');
     System.out.println(sb);  //可行但丑?br />     有很多方法避免这U繁琐,只要一个操作符是stringp强制+操作W做拼接操作。习惯用法是在前面加一个空字符?#8220;”Q如Q?br />      System.out.print("" + 'H' + 'a');//虽然有用Q但q是有点不雅而且ҎD一点困?nbsp;
     试试QSystem.out.println("2 + 2 = " + 2+2);  如果用的是java 5q可以用printfQSystem.out.printf("%c%c", 'H', 'a');
      ȝQ小心应对字W串拼接操作W?font face="Courier New">“+”只有臛_一个是String的时候才做字W串拼接Q否则做加法。如果没有String型,有几个选择Q加I字W串Q用String.valueOf把第一个值显C{换ؓStringQ用String bufferQjava 5的话用printf ?br /> 12  字符数组
     String letters = "ABC";
     char[] numbers = { '1', '2', '3' };
     System.out.println(letters + " easy as " + numbers);  //q回ABC easy as [C@16f0472
 char 虽是基本整数cdQ但char值常常表C字W而不是整敎ͼ很多库对他特D对待。比如,把char传给println 输出的是Unicode 字符而不是数字码。char数组获得同样对待Q?tt>char[] 的重载是println输出数组中的所有字W,char[]?tt>String.valueOf ?tt>StringBuffer.append 的重载也cM。但是字W拼接操作符不是像这些方法,他是对两边做字符串{换然后再拼接。对于对象引用包括数l,字符串{换是q样定义的:如果应用是nullQ{换ؓ字符?tt>"null"Q否则调用被引用对象?tt>toString 无参数方法;如果toString Ҏq回的是nullQ还是用“null”字符丌Ӏ非null的char数组调用toString做什么操作?数组?tt>Object l承来的toString,定义Q?#8220;q回字符串含有对象实例类名,字符'@'Q对象的用无W号十六q制表示的hash?#8221;?nbsp;Class.getName 的说明表C对 char[] 该类对象调用该方法返?nbsp;"[C"。两个方法修正,拼接之前可显C{换数lؓStringQ?br />      System.out.println(letters + " easy as " + String.valueOf(numbers));
q可以把the System.out.println 分开成两个来利用 char[] 对println的重载:
     System.out.print(letters + " easy as ");System.out.println(numbers);
 注意q些修正只是在你正确重蝲valueOf ?tt>printlnҎ才v效。换句话_他们严重依赖~译时数l引用的cd?/tt> 下面例子看v来用来第二个修正ҎQ但q是输出丑陋字符丌Ӏ因Z调用了Object对println的重载而不是char[]的重载?br /> // Broken - invokes the wrong overloading of println!
class Abc {
    public static void main(String[] args) {
        String letters = "ABC";
        Object numbers = new char[] { '1', '2', '3' };
        System.out.print(letters + " easy as ");
        System.out.println(numbers); // Invokes println(Object)
    }
}
ȝQchar数组不是字符丌Ӏ?span style="color: red">把char数组转换为字W串Q调?nbsp;String.valueOf(char[])。一些库Ҏlchar数组提供了像字符串的支持Q典型的是给Object提供一个重载再lchar[]提供一个重载;后一个才是理想的操作?/tt>

13 Interning 
      final String pig = "length: 10";
      final String dog = "length: " + pig.length();
      System.out.println("Animals are equal: "  + pig == dog);
compile-time constants of type String are interned.换句话说QQ何两个有相同字符的Stringcd的常量表辑ּ是同一个对象引用表C的。所以如果用帔R表达式初始化的话Qpig和dog会指向同一个对象,但dog没用帔R表达式。Java语言限制哪些操作可以出现在常量表辑ּ中,Ҏ调用是不允许的。因此,E序应该输出 Animals are equal: falseQ对吧?事实上不是,q行发现只输?tt>false
。操作符的优先体现出来Q事实上?br />      System.out.println(("Animals are equal: " + pig) == dog);
有一U方法能避免q种困难Q但使用字符拼接操作W的时候,Ll重要操作数加上括号QSystem.out.println("Animals are equal: " + (pig == dog));
辩证的说Q这栯是有问题。Your code should rarely, if ever, depend on the interning of string constants。Interning 只是用来减少虚拟机内存的Q不是用来当作程序员工具的。由于字W串intern p|带来的bug非常难以?span style="color: red">。对比两个对象引用的时候,应该用equalsҎ而不?=操作W除非你是想比较对象identity而不是?/span>。所以我们的例子应该q样QSystem.out.println("Animals are equal: " + pig.equals(dog));

14 转义W?/span>
    下面E序使用 Unicode escapesQ用他们的十六进制数字码表示Unicode 字符?br />     // \u0022 is the Unicode escape for double quote (")
    System.out.println("a\u0022.length() + \u0022b".length());
  Java provides no special treatment for Unicode escapes within string literals。编译器在把Unicode escapesE序解析为字W串之前Q先变ؓ了他们表C的字符。可以?span class="docEmphasis">escape sequences:即用\"表示双引?Q例System.out.println("a\".length() + \"b".length()); 
q有很多escape sequences Q?nbsp;single quote (\'), linefeed (\n), tab (\t), and backslash (\\).  escape sequences {程序先解析为符号之后才处理。ASCII是Unicode的子集。ASCII是最的字符集,只有128个字W,Unicode?nbsp;65,000的字W。Unicode escape 能被用来把Unicode 字符插入只能使用ASCII字符的程序中。一?nbsp;Unicode escape意味着和他代表的字W完全相同的东西。但E序员用源文件的字符集不能插入一些字W的时候,可以使用 Unicode escapeQ主要是把非ASCII字符变ؓ标志W,字符Ԍ注释{?br />   ȝQ在字符串和字符文字中,用escape sequences不用Unicode escapes 。不要用Unicode escapes  表示ASCII字符。在字符串和字符文字中,用escape sequencesQ在外面的话直接把ASCII 字符插入源文件?br />
15 
     Unicode escapes must be well formed, even if they appear in comments. 下面q个例子~译出错
/**
* Generated by the IBM IDL-to-Java compiler, version 1.0
* from F:\TestRoot\apps\a1\units\include\PolicyHome.idl
* Wednesday, June 17, 1998 6:44:40 o'clock AM GMT+00:00
*/
工具在把Windows 文g名放入注释之前,必须把\L?br /> MQ?tt>\u不要出现在有效Unicode escape范围之外Q即使注释也不行。特别是自动产生代码的时候?br /> 16 
    line separator 用来表示分割文本行的字符Q每个^台的line separator 不一栗Windows 上,CR character (carriage return) followed by the LF character (linefeed)。UNIX上只有LF字符Q经常被较ؓnewline characterQ。下面把q些字符传给println
   // Note: \u000A is Unicode representation of linefeed (LF)
    char c = 0x000A;
    System.out.println(c);
l果~译错误Q仍然是׃注释中Unicode escape,~译器再抛弃注释内容和空g前就把Unicode escapes 转换为字W?span style="color: red">\u000A
代表linefeed character,因此E序最后{换ؓ 
    // Note:
   is Unicode representation of linefeed (LF)
   char c = 0x000A;
   System.out.println(c);
最单的修改Ҏ是去?nbsp;Unicode escape Q但更好的方法是用escape sequence 初始化cQ而不是用十六q制整数Q排除注释的需?br />    char c = '\n';
   System.out.println(c);
q样改后E序q是有问题,有^C赖。在某些q_Q如UNIXQ他输Z行完整的分割W;另外一些^収ͼ如WindowsQ则不会。虽然肉眼看h一P但如果存在一个文件或道里供其他E序处理?是很Ҏ出问题的?如果打算输出两行I白Q应该调用println两次。Java 5Q你可以使用printf带上格式"%n%n"?/tt>代替printlnQ每一个出现的 %n是printf打印出^台相应的行分隔符?br /> 道理Q非必需量不用Unicode escapes
17 
   Unicode escapes are essential when you need to insert characters that can't be represented in any other way into your program. Avoid them in all other cases.Unicode escapes 减少E序的清晰性,增加bug的出现。对语言设计者来_应该使Unicode escapes表示ASCII字符非法?br /> 18 字符?br />   byte bytes[] = new byte[256];
  for(int i = 0; i < 256; i++)
    bytes[i] = (byte)i;
  String str = new String(bytes);
  for(int i = 0, n = str.length(); i < n; i++)
    System.out.print((int)str.charAt(i) + " ");
  在不同的机器上运行,l果完全不一栗原因是String(byte[])构造器。规范说“用^台默认的字符集给指定的byte数组解码创徏一个新字符丌Ӏ新字符串的长度是字W集的功能,因此可能和byte数组的长度不一栗当l定的字节在默认字符集中无效Ӟ该构造器行ؓ不确?#8221;。什么是字符集?技术上_他是“the combination of a coded character set and a character-encoding scheme”。换句话_是一堆字W,表达字符的数字编码,以及一序列字符~码和字节互相{换的Ҏ。{换方案在不同的字W集中差异巨大。一些字W和字节一一对应Q大多数不这栗只有默认字W集?nbsp;ISO-8859-1Q更多被UCؓLatin-1 Q的时候上面的E序才会输出0?55的整数。J2SEq行环境的默认编码是由底层操作系l和区域军_的。在早期的JAVA版本dpȝ属?nbsp;"file.encoding"来得到JRE默认~码QJAVA 5后以后的版本Q可使用 java.nio.charset.Charset.defaultCharset()Ҏ。幸q的是,你不是非得要面对默认字符集的变化多端。char序列和byte序列互相转换的时候,你可以ƈ且大多数时候应当显式的指定字符?/span>。一个以字符集名字和byte数组为参数的String构造器可完成此d。用下面ҎQ上面程序就不会受默认字W集的媄响了QString str = new String(bytes, "ISO-8859-1"); 该构造器抛出UnsupportedEncodingExceptionQ你必须捕获Q当更好的方法是声明一个mainҎ来抛Z否则不能~译通过。事实上Q上面的E序不会抛出异常。因?tt>Charset 的规范指明Q何JAVAq_的实现必L持某些字W集QISO-8859-1是其中之一?br />
  教训Q?span style="color: red">每次从byte序列转换为StringQ不显C或隐式都在使用一U字W集。如果想E序不出意外Q每ơ用时昄指定一U字W集?br />


yuxh 2010-10-22 08:49 发表评论
]]>
Java PuzzlersQ一 表达式计)http://www.aygfsteel.com/yuxh/archive/2010/10/13/334085.htmlyuxhyuxhWed, 13 Oct 2010 05:27:00 GMThttp://www.aygfsteel.com/yuxh/archive/2010/10/13/334085.htmlhttp://www.aygfsteel.com/yuxh/comments/334085.htmlhttp://www.aygfsteel.com/yuxh/archive/2010/10/13/334085.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/334085.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/334085.html   误:public static boolean isOdd(int i) { return i % 2 == 1; }   //没有考虑到负奇数的情?br />   正:return i % 2 != 0; 更好的性能Qreturn (i & 1) != 0;
 ȝQ求余操作需要考虑W号Q?br /> 2 点数计?br />    public static void main(String args[]) { System.out.println(2.00 - 1.10); } //天真以ؓ得到0.90
    如果熟悉Double.toString 的文档,估计会觉?double 会{为stringQ程序会打印够区?tt>double值的数部分Q小数点前或后面臛_一位。这栯来应该是0.9Q可惜运行程序发现是 0.8999999999999999。问题是数字1.1不能被double准确表示Q只能用最接近的doubleDC。遗憄是结果不是最接近0.9的double?/tt>。更普遍的看q问题是Q?strong>不是所有的十进制数都能用二q制点数准的表示 。如果用jdk5或以后版本,你可能会使用printf来准设|:
// Poor solution - still uses binary floating-point!
System.out.printf("%.2f%n", 2.00 - 1.10);
  现在打印出来是正的了,但治标不LQ它仍然使用的是doubleq算Q二q制点Q,点计算在大范围内提供近D,但不L产生准确的结果。二q制点数特别不适合金融计算Q因Z不可能表C?.1——或Q?0的负q?#8212;—exactly as a finite-length binary fraction?br /> 一U解军_法是使用基本cdQ比如int longQ然后扩大操作数倍数做计。如果用q种程Q确保基本类型够大来表CZ所有你用到的数据,q个例子中,int_了System.out.println((200 - 110) + " cents");
   另一U办法?tt>BigDecimalQ他q行准确的十q制计算Q他q能通过JDBC和SQL?/tt>DECIMALcd合作?strong>有一个箴aQL使用BigDecimal(String)构造器Q绝不?/strong>BigDecimal(double).后面q个构造函数用参数的准值创Z个实例:new BigDecimal(.1)q回一?/tt>BigDecimal表示0.1000000000000000055511151231257827021181583404541015625。正用会得到预期l果0.90Q?                                                    System.out.println(new BigDecimal("2.00"). subtract(new BigDecimal("1.10"))); q个例子不是特别漂亮Qjava没有l?/span>BigDecimal提供语言学上的支持,BigDecimal也可能比使用基本cdQ对大量使用十进制计的E序比较有用Q更慢,大多数情冉|有这个需要?/tt> 
  ȝQ但需要准答案的时候,避免使用float and doubleQ金融计,使用int, long, or BigDecimal。对语言设计者来_提供十进制计的语言支持。一个方法是l操作符重蝲提供有限的支持,q样计算操作W就能和数字引用cd比如BigDecimal一起工作?。另一U方法就是像COBOL and PL/I一P提供基本十进制类型?/tt> 
 3 长整型除?br />   被除数表CZ天的微秒敎ͼ除数表示一天的毫秒敎ͼ
 public static void main(String[] args) {
        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
    }
你在想程序应该输?tt>1000
Q很不幸输出的是5Q问题出在计?tt>MICROS_PER_DAY
 时溢ZQ虽然结果是满long的,但不满int。这个计过E全部是按int 计算的,计算完之后才转ؓlong。因此很明显计算q程中溢出。ؓ什么会用int计算Q因为因子都是int型的QJava没有 target typingҎ(是Ҏl果的类型来定计算q程所用类型)。解册个问题很单,把第一个因子设|ؓlongQ这样会强制所有以后的计算都用longq行。虽然很多地斚w不需要这么做Q但q是一个好习惯?br />     final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
    final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
我们得到一个教训:和大数据打交道的时候,心溢出Q一个变量能装得下结果,q不代表计算q程中会保得到正确cd?br /> 4 学生都知道的事?br />     System.out.println(12345 + 5432l); // 毫无疑问?tt>66666
Q?看仔l了Q输?tt>17777
    教训Q?span style="color: #ff0000">使用long的时候用大写的LQ绝不用写的lQ类似的避免用l作ؓ变量名。很隄出的?q是l
// Bad code - uses el (l) as a variable name
   List<String> l = new ArrayList<String>();
   l.add("Foo");
   System.out.println(1);
5  十六q制的快?br />     System.out.println(Long.toHexString(0x100000000L + 0xcafebabe)); //输出cafebabeQ最左边?丢了Q?br />    十进制有一个十六或八进刉没有的优点:数字都是正的Q想表达负数需要一个负受这L话写十进制的int或longQ不正负都很方ѝ十六或八进制就不这样了Q必ȝ高位来决定正负。这个例子中Q?tt>0xcafebabe 是一个int帔RQ最高位?Q因此是负数=十进?nbsp;-889275714。这里还有一个؜合类型计的额外操作Q左Ҏ作数是longQ右ҎintQ计时Java通过widening primitive conversion 把int变ؓlongQ再加这两个long。因为int是有W号整型Q{变执行了一个符h展:把负的int值提升ؓ数值相{的long倹{右边的0xcafebabe被提升ؓlong?nbsp;0xffffffffcafebabeLQ再加到左边0x100000000L?/tt>。当被看作int型的时候,0xcafebabe扩展出来的高32位是-1Q而左Ҏ作数?2位是1Q相加之后ؓ0Q这解释了ؓ什么最高位?丢失。解x法是把右边的操作C写上longQ这样就避免了符h展的破坏?br /> System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));
教训Q考虑十六或八q制自n带正负,混合cd计算让hqh。ؓ避免出错Q?span style="color: red">最好不要用؜合类型计?/span>。对语言设计者来_考虑支持无符h数类型来LW号扩展的可能。有Z论十六或八进制负数应该被止Q但对于E序员来说非怸好,他们l常使用十六q制来表C符h有意义的数倹{?br />
6 多重映射
   System.out.println((int) (char) (byte) -1);
    ?tt>int
cd?1开始,映射到byteQ到charQ最后返回int。第一?2位变?位,?6位,最后回?2位。最后发现值ƈ没有回到原始Q输?tt>65535
问题来自映射时的W号扩展问题。int?1的所?2位都?Q{?位byte很直观,只留下低八位pQ仍然是-1.转char的时候,p心了,byte是有W号的,char无符受通常有可能保留数值的同时把一个整型{到更“?#8221;的类型,但不可能用char来表CZ个负的byte倹{Therefore, the conversion from byte to char is not considered a widening primitive conversion [JLS 5.1.2], but a widening and narrowing primitive conversion [JLS 5.1.4]: The byte is converted to an int and the int to a char。看h较复杂,但有一个简单规则描q窄变宽转换时的W号扩展Q?span style="color: red">原始值有W号做W号扩展Q不{换成什么类型,char只做零扩展?span style="color: #000000">因ؓbyte是有W号的,byte -1转成char会有W号扩展。结果是??6位,也就?nbsp;216 – 1?5,535。char到int宽扩展,规则告诉我们做零扩展。intcd的结果是65535。虽然规则简单,但最好不要写依赖q规则的E序。如果你是宽转换到charQ或从char转换QcharL无符h敎ͼQ最好显式说明?br />    如果从charcd的c宽{换,q且不想W号扩展Q虽然不需要,但ؓ了清晰可以这P
   int i = c & 0xffff;    
q可以写注释Q?br /> int i = c; // Sign extension is not performed
 如果从charcd的c宽{换,q且想符h展,强制char到shortQ宽度一样但有符P
int i = (short) c; // Cast causes sign extension
byte到charQ不要符?/span>Q必ȝ位屏蔽抑制他Q这是惯例不用注?0xffq种0x开头的默认是intcd的?)
char c = (char) (b & 0xff);
byte to a char Q要W号Q写注释
char c = (char) b; // Sign extension is performed
q一译־单:如果你不能清晰看出程序在q什么,他可能就没有按你希望的在q行。拼命寻求清晎ͼ虽然整数转换的符h展规则简单,但大多程序员不知道。如果你的程序依赖于他,让你的意图明显?
7 交换味
   在一个简单表辑ּ中,不要对一个变量赋Dq一ơ。更普遍的说Q不要用“聪明”的程序技巧?br /> 8  Dos Equis
        char x = 'X';
        int i = 0;
        System.out.print(true  ? x : 0);
        System.out.print(false ? i : x);
输出XXQ可惜输出的?tt>X88。注意第二三个操作数cd不一PW?点说q,混合cd计算让hqhQ条件表辑ּ中是最明显的地斏V虽然觉得两个表辑ּl果应该相同Q毕竟他们类型相|只是位置相反而已,但结果ƈ不是q样?br />        军_条g表达式结果类型的规则很多Q但有三个关键点Q?br />        1 如果W二三个操作数类型一P表达式也是这个类型,q样避免了混合cd计算?br />        2  3 复杂略过 MW一个表辑ּ是调用了PrintStream.print(char)Q第二个?tt>PrintStream.print(int) 造成l果不同
    ȝQ?span style="color: red">最好在条g表达式中W二三个操作数用同一U类?/span>

    x += i;  // {同于x = x + i;Q?br />    compound assignment expressions automatically cast the result of the computation they perform to the type of the variable on their left-hand side// 暗含映射
    例如 short x = 0;int i = 123456;
     x += i; // –7,616Qint?23456太大Qshort装不下,高位两个字节被去?br />      x = x + i; // ~译错误- "possible loss of precision"
    为避免危险,不要?tt>byte, short, or char上面用复合赋值符。当在int上用Ӟ保双不是long, float, or doublecd。在float上用Q确保右边不是double?br /> 10  复合赋值符需要两Ҏ作数都ؓ基本cd或boxed primitivesQ如int Q?tt>Integer。有一例外Q?tt>+= 左边为String的话Q允许右边ؓLcd。这时做的是字符串拼接操作?br />     Object x = "Buy ";
    String i = "Effective Java!";
    x = x + i; //x+i 为StringQ和Object兼容Q因此表辑ּ正确
    x += i; //非法左边不是String
注意q回cdQ?/span>
The arithmetic, increment and decrement, bitwise, and shift operators return a double if at least one of the operands is a double. Otherwise, they return a float if at least one of the operands is a float. Otherwise, they return a long if at least one of the operands is a long. Otherwise, they return an int, even if both operands are byte, short, or char types that are narrower than int.



yuxh 2010-10-13 13:27 发表评论
]]>
Beginning JO(interface/static/final)http://www.aygfsteel.com/yuxh/archive/2009/12/16/305947.htmlyuxhyuxhWed, 16 Dec 2009 03:16:00 GMThttp://www.aygfsteel.com/yuxh/archive/2009/12/16/305947.htmlhttp://www.aygfsteel.com/yuxh/comments/305947.htmlhttp://www.aygfsteel.com/yuxh/archive/2009/12/16/305947.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/305947.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/305947.html If a class implements two or more interfaces that call for methods with identical signatures,we need only implement one such method in the implementing class—that method will do “double duty” in satisfying both interfaces’ implementation requirements as far as the compiler is concerned.
定义 属性,Ҏ参数Q返回类型的时候尽可能使用接口Q客L代码调用q样的类会更加灵zR?br /> List和Set都是Collection接口的子c,使用Collection可以更通用?br />     如果一定要自己创徏集合c而且不通过扩展存在的ArrayList{的话,臛_实现Collection接口Q这h能在使用Collection的环境用?br />     静态方法不能ؓabstractQ不能调用非静态的属性或Ҏ。我们经常利用静态方法,属性实C?#8220;工具c?#8221;Q比如java.lang中的Math.
    接口不允许定义变量,除了定义public static final 变量来作为全局帔R。但是finalcd的变量必LC初始化Q且初始化的Ҏ必须是在x时或者在构造方法中直接赋|而不能通过调用函数赋倹{?br />     j2se 5引入 Qimport static Administrator.*; q样在代码中可以直接使用Administratorcȝ静态变量?br /> 查询了下关于是否用final限定Ҏ参数以及局部变量的问题Q有争议Q?a >http://stackoverflow.com/questions/316352?sort=votes#sort-topQ,cM习惯问题Q不q对传入的参数重新赋g是好习惯Q否则在Ҏ中用该参数的时候你会考虑前面的代码是否对参数处理q,q有可能p的进行了赋倹{們֐于方法参C用finalQ局部变量不使用。折中的办法是设|eclipse的重赋D告?

yuxh 2009-12-16 11:16 发表评论
]]>
Beginning JO(2 Collection)http://www.aygfsteel.com/yuxh/archive/2009/12/10/305397.htmlyuxhyuxhThu, 10 Dec 2009 03:38:00 GMThttp://www.aygfsteel.com/yuxh/archive/2009/12/10/305397.htmlhttp://www.aygfsteel.com/yuxh/comments/305397.htmlhttp://www.aygfsteel.com/yuxh/archive/2009/12/10/305397.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/305397.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/305397.html     通常有两U方法可以扩展collection 来满一些需要:l承某种集合cd和封装某U集合类型。第一U的优点是初始化的时候在内存中只产生一个对象,q是l承Ҏ决定的。后者的优点是我们可以方便控制被装集合的各U属性?br /> Whenever possible, it’s desirable to bury implementation details inside of a class rather than exposing client code to such details。例Q?br /> ?Q?br /> public class Student {
    private String name;
    private String studentId;  
    private ArrayList<TranscriptEntry> transcript; //成W报告?br />     public void addTranscriptEntry(TranscriptEntry te) {   // 操作transcript辑ֈ记录成W
        // Store the TranscriptEntry in our ArrayList.
        transcript.add(te);
    }
}
客户端调用代码:
Student s = new Student("1234567", "James Huddleston");
Course c = new Course("LANG 800", "Advanced Language Studies");
TranscriptEntry te = new TranscriptEntry(c, "Fall 2006", "B+");
s.addTranscriptEntry(te);
?Q?br /> 建立新对象,装一个ArrayListQ?br /> public class Transcript {
    private ArrayList<TranscriptEntry> transcriptEntries;
    public void courseCompleted(Course c, String semester, String grade) {
        // Instantiate and insert a brand-new TranscriptEntry object into the
        // ArrayList - details hidden away!
        transcriptEntries.add(new TranscriptEntry(c, semester, grade);
    }
}
public class Student {
    private String name;
    private String studentId;
    // This used to be declared as an ArrayList.
    private Transcript transcript;
    // etc.
}
客户端代码:
s.courseCompleted(c, "Spring 2006", "A+");
W二U方法Student处理更少的细节,不用transcripts怎么表达Q看不到TranscriptEntry的存在。客L代码更简单?

yuxh 2009-12-10 11:38 发表评论
]]>
Beginning Java Objectshttp://www.aygfsteel.com/yuxh/archive/2009/12/08/305181.htmlyuxhyuxhTue, 08 Dec 2009 08:57:00 GMThttp://www.aygfsteel.com/yuxh/archive/2009/12/08/305181.htmlhttp://www.aygfsteel.com/yuxh/comments/305181.htmlhttp://www.aygfsteel.com/yuxh/archive/2009/12/08/305181.html#Feedback0http://www.aygfsteel.com/yuxh/comments/commentRss/305181.htmlhttp://www.aygfsteel.com/yuxh/services/trackbacks/305181.htmlAggregation
is a special form of association, alternatively referred to as the “consists of”, “is composed of”, or “has a” relationship.Like an association, an aggregation is used to represent a relationship between two classes, A and B. But, with an aggregation, we’re representing more than mere relationship: we’re stating that an object belonging to class A, known as an aggregate,is composed of, or contains, component objects belonging to class B.
  Note that these aggregation statements appear very similar to associations, where the name of the association just so happens to be is composed of or contains. That’s because an aggregation is an association in the broad sense of the termQaggregation 是association的一U特D表现Ş式)!aggregation 和associations UML表现不同但最l代码表现Ş式一?br />   Composition is a strong form of aggregation, in which the “parts” cannot exist without the “whole.” As an example, given the relationship “a Book is composed of many Chapters”, we could argue that a chapter cannot exist if the book to which it belongs ceases to exist; whereas given the relationship “a Car is composed of many Wheels”, we know that a wheel can be removed from a car and still serve a useful purpose. Thus, we’d categorize the Book–Chapter relationship as composition and the Car–Wheel relationship as aggregation.
l承没留意的好处Q?br /> • Best of all, we can derive a new class from an existing class even if we don’t own the source code for the latter! As long as we have the compiled bytecode version of a class, the inheritance mechanism works just fine; we don’t need the original source code of a class in order to extend it. This is one of the most dramatic ways to achieve productivity with an objectoriented language: find a class (either one written by someone else or one that is built into the language) that does much of what you need, and create a subclass of that class,adding just those features that you need for your own purposes.
classification is the natural way that humans organize information; so, it only makes sense that we’d organize software along the same lines, making it much more intuitive and hence easier to develop, maintain,extend, and communicate with users about.
l承与Association, aggregation异同QP186Q:
Association, aggregation, and inheritance are all said to be relationships between classes. Where inheritance differs from association and aggregation is at the object level.inheritance is indeed a relationship between classes, but not between distinct objects.
注意Q避免连锁反应,Whenever possible, avoid adding features to non-leaf classes once they have been established in code form in an application, to avoid ripple effects throughout an inheritance hierarchy. 说比做容易,q就要求在编码之前尽可多的花旉在需求分析和对象建模阶段Q虽然不能避免新需求出玎ͼ但至避免忽视遗漏了当前的需求?
     Overriding:子类l承父类Q重写唯一能改变的是方法的讉K控制Q而且只能比父cL宽松Q如父类用的是privateQ子cd以用public。参考了下thinking in java 4th P202 发现q种说法不对Q而且是一?span style="color: red">陷阱Q父cȝ该方法根本对子类不可见!子类的该Ҏ实际上是一个全新的ҎQ连重蝲都算不上。所以只能重写non-privateҎ。遇到privateҎ你得心Q没有编译错误,但不会像你想象的工作Q最好给Ҏ重新取名Q避免陷阱?br />
不要做的事情Q?br /> We shouldn’t change the semantics—that is, the intention, or meaning—of a feature.For example:
• If the print method of a superclass such as Student is intended to display the values of all of an object’s attributes in the command window, then the print method of a subclass such as GraduateStudent shouldn’t, for example, be overridden so that it directs all of its output to a file instead.
• If the name attribute of a superclass such as Person is intended to store a person’s name in “last name, first name” order, then the name attribute of a subclass such as Student should be used in the same fashion.
  We can’t physically eliminate features, nor should we effectively eliminate them by ignoring them. To attempt to do so would break the spirit of the “is a” hierarchy. By definition, inheritance requires that all features of all ancestors of a class A must also apply to class A itself in order for A to truly be a proper subclass. If a GraduateStudent could eliminate the degreeSought attribute that it inherits from Student, for example, is a GraduateStudent really a Student after all? Strictly speaking, the answer is no.
  q一步从实用角度_如果我们重写一个方法但不在q方法里做Q何事情,其他l承我们cȝ人就会出问题Q他们觉得我们的Ҏ是有意义的(特别是他们不能看到我们源代码的时候)。而我们则打破?#8220;is a” 原则Q所以绝不要q样做!
      protected关键字的q用Q用于控制承的讉K控制?br />      q用super(arguments) 减少子类构造函数重复父cL造函C码,和thiscM必须在构造函数最开始调用?br /> Student s = new Student("Fred", "123-45-6789"); 执行q段代码QObject的构造函C自动执行Q接着Student 的父cPerson构造函Cl,然后是我们调用的Student构造函敎ͼ如果调用的Student构造函数没有显C用父cL造函敎ͼ则相当于默认调用super() ?br /> java没有cȝ多承,多承很复杂的一点,如果两个父类都有相同的方法,子类怎么处理Q?

yuxh 2009-12-08 16:57 发表评论
]]>构造函数的一些用?/title><link>http://www.aygfsteel.com/yuxh/archive/2009/12/06/304944.html</link><dc:creator>yuxh</dc:creator><author>yuxh</author><pubDate>Sun, 06 Dec 2009 14:19:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuxh/archive/2009/12/06/304944.html</guid><wfw:comment>http://www.aygfsteel.com/yuxh/comments/304944.html</wfw:comment><comments>http://www.aygfsteel.com/yuxh/archive/2009/12/06/304944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yuxh/comments/commentRss/304944.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yuxh/services/trackbacks/304944.html</trackback:ping><description><![CDATA[<p>We may wish to instantiate additional objects related to the Student object:<br /> 初始化与对象相关的一些额外对象:<br /> public class Student() {<br />     // Every Student maintains a handle on his/her own individual Transcript object.<br />     private Transcript transcript;<br />     public Student() {<br />         // Create a new Transcript object for this new Student.<br />         transcript = new Transcript();<br />         // etc.<br />     }<br /> }<br /> d数据库来初始化对象属性:<br /> public class Student {<br />     // Attributes.<br />     String studentId;<br />     String name;<br />     double gpa;<br />     // etc.<br />     // Constructor.<br />     public Student(String id) {<br />         studentId = id;<br />         // Pseudocode.<br />         use studentId as a primary key to retrieve data from the Student table of a<br />         relational database;<br />         if (studentId found in Student table) {<br />            retrieve all data in the Student record;<br />             name = name retrieved from database;<br />             gpa = value retrieved from database;<br />         // etc.<br />         }<br />     }<br /> // etc.<br /> }</p> <p>和其他已存在的对象交:<br /> public class Student {<br />     // Details omitted.<br />     // Constructor.<br />     public Student(String major) {<br />         // Alert the student's designated major department that a new student has<br />         // joined the university.<br />         // Pseudocode.<br />         majorDept.notify(about this student ...);<br />     // etc.<br />     }<br />     // etc.<br /> }<br /> <br /> 好习惯:如果需要有参数的构造函敎ͼ最好同时显C声明一个无参构造函数?br /> <span style="color: red">Ҏ出现的bug</span>Q如果给构造函数加上void~译会通过Q不q会被当作方法而不是构造函敎ͼ<br /> 当有多个构造函敎ͼ而且都有共同的初始化内容Ӟ׃出现很多重复的代码,比如构造一个新学生Q我们会做:<br /> 1 通知登记办公室学生的存在<br /> 2 l学生创建学生成l报告单<br /> 重复引v以后修改必须修改多处Q如果用this 会得到改?/p> <p>public class Student {<br />  // Attribute details omitted.<br />  // Constructor #1.<br />  public Student() {<br /> // Assign default values to selected attributes ... details omitted.<br /> // Do the things common to all three constructors in this first<br /> // constructor ...<br /> // Pseudocode.<br /> alert the registrar's office of this student's existence<br /> // Create a transcript for this student.<br /> transcript = new Transcript();<br /> }</p> <p> // Constructor #2.<br />  public Student(String s) {<br />   // ... then, REUSE the code of the first constructor within the second!<br />   this();<br />   // Then, do whatever else extra is necessary for constructor #2.<br />   this.setSsn(s);<br />  }</p> <p> // Constructor #3.<br />  public Student(String s, String n, int i) {<br />   // ... and REUSE the code of the first constructor within the third!<br />   this();<br />   // Then, do whatever else extra is necessary for constructor #3.<br />   this.setSsn(s);<br />   this.setName(n);<br />   this.setAge(i);<br />  }<br />  // etc.<br /> }</p> <span style="color: red">注意Qthis必须在方法最前面调用</span> <img src ="http://www.aygfsteel.com/yuxh/aggbug/304944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuxh/" target="_blank">yuxh</a> 2009-12-06 22:19 <a href="http://www.aygfsteel.com/yuxh/archive/2009/12/06/304944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank">ԭ</a>| <a href="http://" target="_blank">Ǽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ϴ</a>| <a href="http://" target="_blank">ԫ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ڳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨμ</a>| <a href="http://" target="_blank">̫</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">˫</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ϰ</a>| <a href="http://" target="_blank">פ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̳</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͼ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̫ԭ</a>| <a href="http://" target="_blank">Ҷ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>