﻿<?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-kangdy-随笔分类-java相关</title><link>http://www.blogjava.net/kangdy/category/47814.html</link><description>我就像AK47里打出去的子弹。目标TMD永远在前方。我只能TMD拼命向前。</description><language>zh-cn</language><lastBuildDate>Fri, 25 Nov 2011 09:21:12 GMT</lastBuildDate><pubDate>Fri, 25 Nov 2011 09:21:12 GMT</pubDate><ttl>60</ttl><item><title>JAXB向Xml非根节点添加一个或多个属性</title><link>http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Wed, 23 Nov 2011 06:33:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/364635.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/364635.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/364635.html</trackback:ping><description><![CDATA[JAXB 向Xml非根节点添加一个或多个属性，直接上代码，关于JAXB的相关注解可查阅JAVA API。<br /><br /><span style="color: red;">原创文章，转载请注明出处。</span><a href="http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html">http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html</a><br /><br />code1: colors类&nbsp; 根节点<br /><fieldset><legend>code1</legend><div>package com.kangdy.test;<br /><br />import javax.xml.bind.annotation.XmlAccessType;<br />import javax.xml.bind.annotation.XmlAccessorType;<br />import javax.xml.bind.annotation.XmlElement;<br />import javax.xml.bind.annotation.XmlRootElement;<br /><br />@XmlRootElement(name = "Colors")<br />@XmlAccessorType(XmlAccessType.FIELD)<br />public class Colors {<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;@XmlElement(name = "red",nillable=true)<br />&nbsp;&nbsp; &nbsp;private Red red;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;@XmlElement(name = "blue",nillable=true)<br />&nbsp;&nbsp; &nbsp;private Blue blue;<br /><br />&nbsp;&nbsp; &nbsp;public Red getRed() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return red;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public Blue getBlue() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return blue;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setRed(Red red) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.red = red;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setBlue(Blue blue) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.blue = blue;<br />&nbsp;&nbsp; &nbsp;}<br />}</div></fieldset><br />code2:&nbsp; Red类&nbsp; 子节点<br /><fieldset><legend>code2</legend>package com.kangdy.test;<br /><br />import javax.xml.bind.annotation.XmlAccessType;<br />import javax.xml.bind.annotation.XmlAccessorType;<br />import javax.xml.bind.annotation.XmlAttribute;<br />import javax.xml.bind.annotation.XmlRootElement;<br /><br />@XmlRootElement(name = "red")<br />@XmlAccessorType(XmlAccessType.FIELD)<br />public class Red {<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;private String value;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;@XmlAttribute(name = "att1")<br />&nbsp;&nbsp; &nbsp;private String att;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;public String getValue() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return value;<br />&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;public void setValue(String value) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.value = value;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public String getAtt() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return att;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setAtt(String att) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.att = att;<br />&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;<br />}<br /><br /></fieldset><br />code3:&nbsp; 类 Blue 子节点<br /><fieldset><legend>code3</legend><div>package com.kangdy.test;<br /><br />import javax.xml.bind.annotation.XmlAccessType;<br />import javax.xml.bind.annotation.XmlAccessorType;<br />import javax.xml.bind.annotation.XmlAttribute;<br />import javax.xml.bind.annotation.XmlRootElement;<br /><br />@XmlRootElement(name = "blue")<br />@XmlAccessorType(XmlAccessType.FIELD)<br />public class Blue {<br />&nbsp;&nbsp; &nbsp;private String value;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;@XmlAttribute(name = "att2")<br />&nbsp;&nbsp; &nbsp;private String att2;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;@XmlAttribute(name = "att1")<br />&nbsp;&nbsp; &nbsp;private String att;<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;public String getAtt() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return att;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setAtt(String att) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.att = att;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public String getValue() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return value;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setValue(String value) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.value = value;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public String getAtt2() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return att2;<br />&nbsp;&nbsp; &nbsp;}<br /><br />&nbsp;&nbsp; &nbsp;public void setAtt2(String att2) {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;this.att2 = att2;<br />&nbsp;&nbsp; &nbsp;}<br />}</div></fieldset><br />code4: main类<br /><fieldset><legend>code4</legend><div>package com.kangdy.test;<br /><br />import java.io.StringWriter;<br /><br />import javax.xml.bind.JAXBContext;<br />import javax.xml.bind.Marshaller;<br /><br />public class Jaxbtest {<br />&nbsp;&nbsp; &nbsp;public static void main(String[] args) throws Exception {<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;StringWriter writer = new StringWriter();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;JAXBContext jc = JAXBContext.newInstance(Colors.class);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Marshaller ma = jc.createMarshaller();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Colors colors = new Colors();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Red red = new Red();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;red.setAtt("att-red");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;red.setValue("red");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Blue blue = new Blue();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;blue.setValue("blue");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;blue.setAtt("att-blue");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;blue.setAtt2("blue-att2");<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;colors.setRed(red);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;colors.setBlue(blue);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;ma.marshal(colors, writer);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println(writer.toString());<br /><br />&nbsp;&nbsp; &nbsp;}<br />}</div></fieldset><br />运行结果：<br /><fieldset><legend>结果</legend><div>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;<br />&lt;Colors&gt;<br />&nbsp;&nbsp;&nbsp; &lt;red att1="att-red"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;red&lt;/value&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/red&gt;<br />&nbsp;&nbsp;&nbsp; &lt;blue att1="att-blue" att2="blue-att2"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;blue&lt;/value&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/blue&gt;<br />&lt;/Colors&gt;</div></fieldset><img src ="http://www.blogjava.net/kangdy/aggbug/364635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2011-11-23 14:33 <a href="http://www.blogjava.net/kangdy/archive/2011/11/23/364635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重新认识Java finally</title><link>http://www.blogjava.net/kangdy/archive/2011/11/01/362456.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Tue, 01 Nov 2011 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2011/11/01/362456.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/362456.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2011/11/01/362456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/362456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/362456.html</trackback:ping><description><![CDATA[关于java finally 网上有2篇文章个人认为相当不错<br />以下是转贴内容：<br /><br /><strong>1 . JAVA finally字句的异常丢失和返回值覆盖解析</strong><br />原帖地址 ：<br /><a href="http://blog.csdn.net/sureyonder/article/details/5560538">http://blog.csdn.net/sureyonder/article/details/5560538</a><br /><fieldset><legend>转贴</legend><div>Java虚拟机在每个try语句块和与其相关的catch子句的结尾 处都会&#8220;调用&#8221;finally子句的子例程。实际上，finally子句在方法内部的表现很象&#8220;微型子例程&#8221;。finally子句正常结束后－指的是finally子句中最后一条语句正常执行完毕，不包括抛出异常，或执行return、continue、break等情况，隶属于这个finally子句的微型子例程执行&#8220;返回&#8221;操作。程序在第一次调用微型子例程的地方继续执行后面的语句。<br /><br />finally&#8220;微型子例程&#8221;不等同于方法函数的调用，finally子句都是在同一个栈内执行的，微型子例程的&#8220;返回&#8221;操作也不会涉及到方法退栈，仅仅是使程序计数器pc跳转到同一个方法的一个不同的位置继续执行。<br />一　异常丢失<br />&nbsp;&nbsp;&nbsp; public static void exceptionLost() &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception( "exception in try" ); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception( "exception in finally" ); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch( Exception e ) &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( e ); &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br /><br />exceptionLost()的输出结果是&#8220;exception in finally&#8221;，而不是try块中抛出的异常，这是JAVA异常机制的一个瑕疵－异常丢失。<br /><br />在字节码中，throw语句不是原子性操作。在较老的JDK中，exceptionLost()中try块的throw语句分解为几步操作：<br />1) 把Exception("exception in try")对象引用存储到一个局部变量中<br />　　astore_2 　// pop the reference to the thrown exception, store into local variable 2<br />2) 调用finally微型子程序<br />3) 把局部变量中的Exception("exception in try")对象引用push到操作数栈顶，然后抛出异常<br />　　aload_2 　// push the reference to the thrown exception from local variable 2<br /><br />　　athrow 　　// throw the exception<br /><br />如果finally通过break、return、continue，或者抛出异常而退出，那么上面的第３步就不会执行。<br /><br />在JDK1.6中，通过字节码我们可以看到，finally子句作为一种特殊的catch来实现的，下面是exceptionLost()方法的异常表：<br /><br />Exception table：<br />&nbsp; from&nbsp;&nbsp; to&nbsp; 　target 　type<br />&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp; 　10&nbsp;&nbsp;&nbsp; 10&nbsp;&nbsp; 　　any<br />　0&nbsp;&nbsp;&nbsp; 　21&nbsp;&nbsp;&nbsp; 21&nbsp;&nbsp; 　　Class java/lang/Exception<br /><br />finally可以捕获从0行到9行之间抛出的任何类型(any)的异常，并重新抛出捕获的异常，或者抛出一个自己构造的新异常，这个新异常就会覆盖try语句块中的异常。<br />二　返回值覆盖<br /><br />&nbsp;&nbsp;&nbsp; public static int getValue() &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int value = 0; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = 100; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return value; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = 200; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;<br /><br />这个方法的返回值是100还是200?结果是100。<br />在字节码中，return语句不是原子性操作，它会把getValue()中的return语句分解为几步操作：<br />1) 把value值存储到一个局部变量(这里命名为temp)中：<br />　　 iload_0　　 // push local variable 0 - the 100<br />　　 istore_2　&nbsp; //&nbsp; pop an int (the 100), store into local varaible 2<br />2) 调用finally微型子程序<br />3) 把局部变量(指temp)的值push到操作数栈顶，然后返回到调用方法<br />&nbsp;　&nbsp;&nbsp; iload_2　　// push local varaible 2 - the 100<br />&nbsp;　　ireturn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // return int on top of the stack - the 100: return 100<br /><br />由于return语句在返回之前会把返回值保存到一个临时的局部变量中，所以在finally子句内对value重新赋值不会影响返回值。<br /><br />了解finally子句内在的一些知识，我们能够了解finally能够做什么和不能够做什么，这样会帮助我们正确使用finally子句。</div></fieldset><br /><strong>2 . 关于 Java 中 finally 语句块的深度辨析</strong><br />原帖地址 ：<a href=" http://www.ibm.com/developerworks/cn/java/j-lo-finally/index.html?ca=drs-"><br /><div>http://www.ibm.com/developerworks/cn/java/j-lo-finally/index.html?ca=drs-</div></a><div></div><fieldset><legend>转贴</legend><div>关于 Java 虚拟机是如何编译 finally 语句块的问题，有兴趣的读者可以参考<span style="color: #008000;">《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally。那里详细介绍了 Java 虚拟机是如何编译 finally 语句块。实际上，Java 虚拟机会把 finally 语句块作为 subroutine</span><span style="color: #008000;">（对于这个 subroutine 不知该如何翻译为好，干脆就不翻译了，免得产生歧义和误解。）</span><span style="color: #008000;">直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是，还有另外一个不可忽视的因素，那就是在执行 subroutine</span><span style="color: #008000;">（也就是 finally 语句块）</span><span style="color: #008000;">之前，try 或者 catch 语句块会保留其返回值到本地变量表（Local Variable Table）中。待 subroutine 执行完毕之后，再恢复保留的返回值到操作数栈中，然后通过 return 或者 throw 语句将其返回给该方法的调用者（invoker）。</span><span style="color: #008000;">请注意，前文中我们曾经提到过 return、throw 和 break、continue 的区别，</span><span style="color: #008000;">对于这条规则（保留返回值），只适用于 return 和 throw 语句</span><span style="color: #008000;">，不适用于 break 和 continue 语句，因为它们根本就没有返回值。</span></div></fieldset><img src ="http://www.blogjava.net/kangdy/aggbug/362456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2011-11-01 16:56 <a href="http://www.blogjava.net/kangdy/archive/2011/11/01/362456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转贴)BigInteger 和 BigDecimal </title><link>http://www.blogjava.net/kangdy/archive/2010/12/10/340257.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Fri, 10 Dec 2010 06:16:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2010/12/10/340257.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/340257.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2010/12/10/340257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/340257.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/340257.html</trackback:ping><description><![CDATA[<p><font style="line-height: 1.3em;" color="#ff0000"><strong><wbr>高精度数字</strong><wbr></font><wbr><br />
Java 提供了两个类专门用于进行高精度运算BigInteger 和 BigDecimal ，尽管它们可大致划分到与封装器相同的类别里，但两者都没有对应的主类型；这两个类都有自己的一系列方法，类似于我们针对主类型执行的操作，也就是说能用 int 或float 做的事情，用BigInteger和BigDecimal 一样可以做，只是必须换用方法调用，而不是使用运算符。此外由于牵涉更多，所以运算速度会慢一点总之我们牺牲了速度，但换来了精度。</p>
<p style="color: red;"><strong>高精度浮点数BigDecimal</strong> </p>
<p>一些非整数值（如几美元和几美分这样的小数）需要很精确。浮点数不是精确值，所以使用它们会导致舍入误差。因此，使用浮点数来试图表示象货币量这样的精确数量不是一个好的想法。使用浮点数来进行美元和美分计算会得到灾难性的后果。浮点数最好用来表示象测量值这类数值，这类值从一开始就不怎么精确。<br />
&nbsp;&nbsp;&nbsp;&nbsp;从 JDK 1.3 起，Java 开发人员就有了另一种数值表示法来表示非整数：BigDecimal。BigDecimal 是标准的类，在编译器中不需要特殊支持，它可以表示任意精度的小数，并对它们进行计算。在内部，可以用任意精度任何范围的值和一个换算因子来表示 BigDecimal，换算因子表示左移小数点多少位，从而得到所期望范围内的值。因此，用 BigDecimal 表示的数的形式为 unscaledValue*10-scale。<br />
用于加、减、乘和除的方法给&nbsp;&nbsp;BigDecimal 值提供了算术运算。由于 BigDecimal 对象是不可变的，这些方法中的每一个都会产生新的 BigDecimal 对象。因此，因为创建对象的开销，BigDecimal 不适合于大量的数学计算，但设计它的目的是用来精确地表示小数。如果您正在寻找一种能精确表示如货币量这样的数值，则 BigDecimal 可以很好地胜任该任务。<br />
如浮点类型一样，BigDecimal 也有一些令人奇怪的行为。尤其在使用 equals() 方法来检测数值之间是否相等时要小心。equals() 方法认为，两个表示同一个数但换算值不同（例如，100.00 和&nbsp;&nbsp;100.000）的 BigDecimal 值是不相等的。然而，compareTo() 方法会认为这两个数是相等的，所以在从数值上比较两个&nbsp;&nbsp;BigDecimal 值时，应该使用 compareTo() 而不是 equals()。<br />
另外还有一些情形，任意精度的小数运算仍不能表示精确结果。例如，1 除以 9 会产生无限循环的小数 .111111...。出于这个原因，在进行除法运算时，BigDecimal 可以让您显式地控制舍入。movePointLeft() 方法支持 10 的幂次方的精确除法。<br />
对于 BigDecimal，有几个可用的构造函数。其中一个构造函数以双精度浮点数作为输入，另一个以整数和换算因子作为输入，还有一个以小数的 String 表示作为输入。要小心使用&nbsp;&nbsp;BigDecimal(double) 构造函数， 因为如果不了解它，会在计算过程中产生舍入误差。请使用基于整数或 String 的构造函数。<br />
如果使用 BigDecimal(double) 构造函数不恰当，在传递给 JDBC setBigDecimal() 方法时，会造成似乎很奇怪的 JDBC 驱动程序中的异常。例如，考虑以下 JDBC 代码，该代码希望将数字 0.01 存储到小数字段：<br />
&nbsp;&nbsp;PreparedStatement ps =connection.prepareStatement("INSERT INTO Foo SET name=?, value=?");<br />
&nbsp;&nbsp;ps.setString(1, "penny");<br />
&nbsp;&nbsp;ps.setBigDecimal(2, new BigDecimal(0.01));<br />
&nbsp;&nbsp;ps.executeUpdate();<br />
&nbsp;&nbsp;&nbsp;&nbsp; 在执行这段似乎无害的代码时会抛出一些令人迷惑不解的异常（这取决于具体的 JDBC 驱动程序），因为 0.01 的双精度近似值会导致大的换算值，这可能会使 JDBC 驱动程序或数据库感到迷惑。JDBC 驱动程序会产生异常，但可能不会说明代码实际上错在哪里，除非意识到二进制浮点数的局限性。相反，使用 BigDecimal("0.01") 或 BigDecimal(1, 2) 构造 BigDecimal 来避免这类问题， 因为这两种方法都可以精确地表示小数。<br />
&nbsp;<br />
</p>
<fieldset><legend>code :</legend>
<p>import java.math.BigDecimal;<br />
/** * *<br />
* &lt;p&gt;Title: 开源,开放&lt;/p&gt;<br />
* * &lt;p&gt;Description: opeansource&lt;/p&gt;<br />
* * &lt;p&gt;Copyright: Copyright (c) 2004&lt;/p&gt;<br />
* * &lt;p&gt;Company: ?海棠&lt;/p&gt;<br />
* * @author HaiTang Ming<br />
* * @version 1.0 */<br />
public class BigDecimalUtil {&nbsp; <br />
//默认除法运算精度,及即保留小数点多少位&nbsp; <br />
private static final int DEF_DIV_SCALE = 2;&nbsp; <br />
//这个类不能实例化&nbsp; <br />
private BigDecimalUtil (){&nbsp;&nbsp; }&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 提供精确的加法运算。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v1 被加数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v2 加数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @return 两个参数的和&nbsp;&nbsp;&nbsp; <br />
&nbsp; * */&nbsp; <br />
public static double add(double v1,double v2){&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b1 = new BigDecimal(Double.toString(v1));&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b2 = new BigDecimal(Double.toString(v2));&nbsp;&nbsp;&nbsp; <br />
&nbsp; return (b1.add(b2)).doubleValue();&nbsp; <br />
}&nbsp; </p>
<p>/**</p>
<p>&nbsp; *提供精确的减法运算。&nbsp; <br />
&nbsp; * * @param v1 被减数&nbsp; <br />
&nbsp; * * @param v2 减数&nbsp; <br />
&nbsp; * * @return 两个参数的差<br />
&nbsp; **/&nbsp; <br />
public static double sub(double v1,double v2){&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b1 = new BigDecimal(Double.toString(v1));&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b2 = new BigDecimal(Double.toString(v2));&nbsp;&nbsp;&nbsp; <br />
&nbsp; return (b1.subtract(b2)).doubleValue();&nbsp; <br />
}&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 提供精确的乘法运算。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v1 被乘数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v2 乘数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @return 两个参数的积&nbsp;&nbsp;&nbsp; <br />
&nbsp; * */<br />
public static double mul(double v1,double v2){&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b1 = new BigDecimal(Double.toString(v1));&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b2 = new BigDecimal(Double.toString(v2));&nbsp;&nbsp;&nbsp; <br />
&nbsp; return (b1.multiply(b2)).doubleValue();&nbsp; <br />
}&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 小数点以后多少位，以后的数字四舍五入。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v1 被除数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v2 除数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @return 两个参数的商&nbsp;&nbsp;&nbsp; <br />
&nbsp; * */&nbsp; <br />
public static double div(double v1,double v2){&nbsp;&nbsp;&nbsp; <br />
&nbsp; return div(v1,v2,DEF_DIV_SCALE);&nbsp; <br />
}&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 定精度，以后的数字四舍五入。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v1 被除数&nbsp; <br />
&nbsp; * @param v2 除数&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param scale 表示表示需要精确到小数点以后几位。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @return 两个参数的商&nbsp;&nbsp;&nbsp; <br />
&nbsp; * */&nbsp; <br />
public static double div(double v1,double v2,int scale){&nbsp;&nbsp;&nbsp; <br />
&nbsp; if(scale&lt;0){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; throw new IllegalArgumentException("The scale must be a positive integer or zero");&nbsp;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b1 = new BigDecimal(Double.toString(v1));&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b2 = new BigDecimal(Double.toString(v2));&nbsp;&nbsp;&nbsp; <br />
&nbsp; return (b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP)).doubleValue();&nbsp; <br />
}&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 提供精确的小数位四舍五入处理。&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param v 需要四舍五入的数字&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @param scale 小数点后保留几位&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * @return 四舍五入后的结果&nbsp;&nbsp;&nbsp; <br />
&nbsp; * */&nbsp; <br />
public static double round(double v,int scale){&nbsp; <br />
&nbsp; if(scale&lt;0){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; throw new IllegalArgumentException("The scale must be a positive integer or zero");<br />
&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal b = new BigDecimal(Double.toString(v));&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigDecimal one = new BigDecimal("1");&nbsp;&nbsp;&nbsp; <br />
&nbsp; return (b.divide(one,scale,BigDecimal.ROUND_HALF_UP)).doubleValue();&nbsp; <br />
}&nbsp;&nbsp;&nbsp; <br />
public static void main(String[] args){&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(add(234.44,534.90));<br />
&nbsp; <br />
&nbsp; double a = 123.345678;&nbsp;&nbsp;&nbsp; <br />
&nbsp; double d = round(a,2);&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println("round("+a+",2)---&gt;"+d);&nbsp; <br />
}<br />
}</p>
</fieldset>
<p style="color: red;"><strong>高精度整数BigInteger</strong> </p>
<p>BigInteger支持任意精度的整数，也就是说我们可精确表示任意大小的整数值；同时在运算过程中不会丢失任何信息;<br />
在BigInteger类中有所有的基本算术运算方法，如加、减、乘、除，以及可能会用到的位运算如或、异或、非、左移、右移等。下面是一些方法的例子：当然，如果要有更多的使用方法，可以查阅java api 。</p>
<fieldset><legend>code :</legend>public class BigIntegerTest {&nbsp; <br />
public BigIntegerTest() {&nbsp;&nbsp; }&nbsp; <br />
/**&nbsp;&nbsp;&nbsp; <br />
&nbsp; * * 测试BigInteger<br />
&nbsp; * */&nbsp; <br />
public static void testBigInteger() {&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigInteger bi = new BigInteger("888");&nbsp;&nbsp;&nbsp; <br />
&nbsp; //multiply :乘法&nbsp;&nbsp;&nbsp; <br />
&nbsp; BigInteger result = bi.multiply(new BigInteger("2"));&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(result);&nbsp;&nbsp;&nbsp; <br />
&nbsp; //divide : 除法&nbsp;&nbsp;&nbsp; <br />
&nbsp; result = bi.divide(new BigInteger("2"));&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(result);&nbsp;&nbsp;&nbsp; <br />
&nbsp; //add : 加法&nbsp;&nbsp;&nbsp; <br />
&nbsp; result = bi.add(new BigInteger("232"));&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(result);&nbsp;&nbsp;&nbsp; <br />
&nbsp; //subtract :减法&nbsp;&nbsp;&nbsp; <br />
&nbsp; result = bi.subtract(new BigInteger("23122"));&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(result);&nbsp;&nbsp;&nbsp; <br />
&nbsp; result = bi.shiftRight(2);&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(result);&nbsp; <br />
}&nbsp;&nbsp;&nbsp; <br />
public static void main(String[] args) {&nbsp;&nbsp;&nbsp; <br />
&nbsp; testBigInteger();&nbsp; <br />
}<br />
}</fieldset>原贴地址<a href="http://dev.firnow.com/course/3_program/java/javaxl/2008914"><font color="#000000">：</font>http://dev.firnow.com/course/3_program/java/javaxl/2008914</a> /142796_2.html
<img src ="http://www.blogjava.net/kangdy/aggbug/340257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2010-12-10 14:16 <a href="http://www.blogjava.net/kangdy/archive/2010/12/10/340257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转贴) 超大整数相加，超过了long的范围，你要怎么做！</title><link>http://www.blogjava.net/kangdy/archive/2010/12/10/340256.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Fri, 10 Dec 2010 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2010/12/10/340256.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/340256.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2010/12/10/340256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/340256.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/340256.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<fieldset><legend>引用：</legend>
<p>&nbsp;这个只能够用字符串的形式来处理了，因为计算机能够处理的最大是long型，本文以字符串的形式来进行超大数据的相加，理论上只要你的内存允许，相加多大的数都可以。</p>
<p>/**</p>
<p>&nbsp;* 超大整数相加：</p>
<p>&nbsp;* 题目要求：如果系统要使用超大整数（超过long的范围），请你设计一个数据结构来存储这种</p>
<p>&nbsp;* 超大型数字以及设计一种算法来实现超大整数的加法运算</p>
<p>&nbsp;* @author Administrator</p>
<p>&nbsp;*</p>
<p>&nbsp;*/</p>
<p>public class VeryBigNumAdd {</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; /**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @param args</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp; public static void main(String[] args) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO Auto-generated method stub</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String a="1223232";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=a.length()-1;i&gt;=0;i--)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print(a.charAt(i));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VeryBigNumAdd vbn=new VeryBigNumAdd();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String a="123453243455535634535252345234677576252241234123523453664563634";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String b="123453243455535634535252345234677576252241234123523453664563634";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String result=vbn.doAdd(a,b);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("result:"+result);</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; /**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; *</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @param a 加数字符串1</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @param b 加数字符串2</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @return 结果字符串</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">* 分析：</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; * 1、取得两个字符串的长度</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; * 2、把两个的长度做比较，并得出较长的长度，及较短的长度</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; * 3、把长度较短的加数字符串，在左面补0，使之与较长的字符串一样长</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; * 4、从最高位，一个个数的取出来相加，当然首先得转换为整型</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; * 5、设置进位，如果两个数相加及加上进位大于等于10，并且这不是最左边一个字符相加，相加结果等于</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp; （取出1＋取出2＋进位）－10，并把进位设为1；如果没有大于10，就把进位设为0，如些循环，把</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp; 相加的结果以字符串的形式结合起来，就得到最后的结果</span></p>
<p><span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp; */</span></p>
<p>&nbsp;&nbsp;&nbsp; String doAdd(String a,String b)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String str="";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int lenA=a.length();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int lenB=b.length();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int maxLen=(lenA&gt;lenB) ? lenA : lenB;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int minLen=(lenA&lt;lenB) ? lenA : lenB;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String strTmp="";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=maxLen-minLen;i&gt;0;i--)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strTmp+="0";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //把长度调整到相同</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(maxLen==lenA)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b=strTmp+b;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a=strTmp+a;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int JW=0;//进位</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=maxLen-1;i&gt;=0;i--)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int tempA=Integer.parseInt(String.valueOf(a.charAt(i)));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int tempB=Integer.parseInt(String.valueOf(b.charAt(i)));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int temp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(tempA+tempB+JW&gt;=10 &amp;&amp; i!=0)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp=tempA+tempB+JW-10;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JW=1;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp=tempA+tempB+JW;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JW=0;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str=String.valueOf(temp)+str;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return str;</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>}</p>
<p>&nbsp;</p>
</fieldset>
<p>原帖地址： http://blog.csdn.net/fenglibing/archive/2007/08/23/1756773.aspx<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;其实java 本身也提供了api ,java.math.BigInteger;import java.math.BigDecimal; 也可以实现。</p>
<fieldset><legend>code :</legend>
<p>package com.kangdy.test;</p>
<p>import java.math.BigInteger;<br />
import java.math.BigDecimal;</p>
<p>public class NumberTest {<br />
&nbsp;public static void main(String args[]){<br />
&nbsp;&nbsp;BigInteger b1= new BigInteger("2222222222222222222222222");<br />
&nbsp;&nbsp;BigInteger b2= new BigInteger("8888888888888888888888888");<br />
&nbsp;&nbsp;BigDecimal b3 = new BigDecimal("66666666666666666666666666");<br />
&nbsp;&nbsp;BigDecimal b4 = new BigDecimal("9999999999999999999999999999");<br />
&nbsp;&nbsp;System.out.println(b1.add(b2).toString());<br />
&nbsp;&nbsp;System.out.println(b3.add(b4).toString());<br />
&nbsp;}<br />
}</p>
</fieldset>
<p>这里只是给出简单的例子。<br />
<br />
<br />
<br />
</p>
<img src ="http://www.blogjava.net/kangdy/aggbug/340256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2010-12-10 14:06 <a href="http://www.blogjava.net/kangdy/archive/2010/12/10/340256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数字金额的中文大小写转化</title><link>http://www.blogjava.net/kangdy/archive/2010/11/02/336802.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Tue, 02 Nov 2010 06:59:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2010/11/02/336802.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/336802.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2010/11/02/336802.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/336802.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/336802.html</trackback:ping><description><![CDATA[曾经去过一家公司面试。笔试题的最后一题是一个数字金额大小写转化的问题。<br />
当时没想那么多，仅仅想到应该把数拆开然后添加单位的一个大致的设计思路。<br />
而那个面试官一个劲儿的问我用啥算法。那个题最后也没答上，回来后比较郁闷，<br />
在网上搜了一下。这个答案还真不少。不过觉得有一种设计还比较靠谱。<br />
大概是这样： <br />
<span style="color: red;">&nbsp;* 先将整数与小数部分分开，计算小数部分，角分并保存<br />
&nbsp;* 整数部分长度不足12位，前面加0补足。<br />
&nbsp;* 将整数部分分割3部分。高4位代表亿，中间的是万，其余分别代表千，百，十，个<br />
&nbsp;* 定一个方法拼出每一部分串。<br />
&nbsp;* 最后整数与小数部分合成。</span><br />
自己实现了一下，以下是代码。<br />
<fieldset><legend>code :</legend>
<p>package com.kangdy.test;<br />
/**<br />
&nbsp;* 数字金额转化成大写<br />
&nbsp;* 先将整数与小数部分分开，计算小数部分，角分并保存<br />
&nbsp;* 整数部分长度不足12位，前面加0补足。<br />
&nbsp;* 将整数部分分割3部分。高4位代表亿，中间的是万，其余分别代表千，百，十，个<br />
&nbsp;* 定一个方法拼出每一部分串。<br />
&nbsp;* 最后整数与小数部分合成。<br />
&nbsp;* @author dkang<br />
&nbsp;* <br />
&nbsp;*/<br />
public class NumberToString {</p>
<p>&nbsp;String numberStr;</p>
<p>&nbsp;public static final String unit[] = { "", "十", "百", "千", "万", "亿" };</p>
<p>&nbsp;public static final String unit2[] = { "元", "角", "分" };</p>
<p>&nbsp;public static final String numStr[] = { "零", "壹", "贰", "叁", "肆", "伍", "陆",<br />
&nbsp;&nbsp;&nbsp;"柒", "捌", "玖" };</p>
<p>&nbsp;/**<br />
&nbsp; * 字符串长度不足12位用0补足<br />
&nbsp; * <br />
&nbsp; * @param str<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String additionalZero(String str) {<br />
&nbsp;&nbsp;StringBuffer strb = new StringBuffer();<br />
&nbsp;&nbsp;if (str.length() &lt; 12) {<br />
&nbsp;&nbsp;&nbsp;int size = 12 - str.length();<br />
&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; size; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;strb.append("0");<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return strb.append(str).toString();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 递归拆分数字成字符串<br />
&nbsp; * <br />
&nbsp; * @param value<br />
&nbsp; * @param strBuffer<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String decomposeNumberToString(int value, StringBuffer strBuffer) {<br />
&nbsp;&nbsp;int quotient = 0;<br />
&nbsp;&nbsp;quotient = value / 10;<br />
&nbsp;&nbsp;if (quotient != 0) {<br />
&nbsp;&nbsp;&nbsp;decomposeNumberToString(quotient, strBuffer);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;int remaider = value % 10;<br />
&nbsp;&nbsp;strBuffer.append(remaider + ",");<br />
&nbsp;&nbsp;return strBuffer.toString().substring(0,<br />
&nbsp;&nbsp;&nbsp;&nbsp;strBuffer.toString().length() - 1);<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 使用循环拆分数字成字符串<br />
&nbsp; * <br />
&nbsp; * @param value<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String decomposeNumberToString2(int value) {<br />
&nbsp;&nbsp;StringBuilder strBuilder = new StringBuilder();<br />
&nbsp;&nbsp;int quotient = value;<br />
&nbsp;&nbsp;int remaider = 0;<br />
&nbsp;&nbsp;while (quotient != 0) {<br />
&nbsp;&nbsp;&nbsp;remaider = quotient % 10;<br />
&nbsp;&nbsp;&nbsp;strBuilder.append(remaider + ",");<br />
&nbsp;&nbsp;&nbsp;quotient = quotient / 10;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;strBuilder.deleteCharAt(strBuilder.lastIndexOf(","));<br />
&nbsp;&nbsp;return strBuilder.reverse().toString();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 添加单位<br />
&nbsp; * <br />
&nbsp; * @param temp<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String addUnits(String temp) {<br />
&nbsp;&nbsp;StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;String str[] = temp.split(",");<br />
&nbsp;&nbsp;String tempStr = temp.replace(",", "");<br />
&nbsp;&nbsp;if (tempStr.contains("000")) {<br />
&nbsp;&nbsp;&nbsp;return sb.append(resplaceNumToStr(str[0]) + unit[3]).toString();<br />
&nbsp;&nbsp;} else if (tempStr.contains("00")) {<br />
&nbsp;&nbsp;&nbsp;if (tempStr.charAt(3) == '0') {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return sb.append(resplaceNumToStr(str[0]) + unit[3]).append(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resplaceNumToStr(str[1]) + unit[2]).toString();<br />
&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return sb.append(resplaceNumToStr(str[0]) + unit[3]).append(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numStr[0]).append(resplaceNumToStr(str[3])).toString();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; str.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;sb.append(resplaceNumToStr(str[i]));<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (!str[i].equals("0")) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(unit[str.length - (i + 1)]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return sb.toString();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 数字替换<br />
&nbsp; * <br />
&nbsp; * @param str<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String resplaceNumToStr(String str) {<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;int num = Integer.parseInt(str);<br />
&nbsp;&nbsp;&nbsp;return numStr[num];<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return "";<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 把4位长度的数字转化成字符串<br />
&nbsp; * <br />
&nbsp; * @param number<br />
&nbsp; * @param i<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private String transformNumberToString(String number, int i) {<br />
&nbsp;&nbsp;StringBuffer strBuffer = new StringBuffer();<br />
&nbsp;&nbsp;StringBuilder strBuilder = new StringBuilder();<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;int num = Integer.parseInt(number);<br />
&nbsp;&nbsp;&nbsp;if (num != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;String s1 = decomposeNumberToString(num, strBuffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;strBuilder.append(addUnits(s1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (i == 1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strBuilder.append(unit[5]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;} else if (i == 2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strBuilder.append(unit[4]);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return strBuilder.toString();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 得到最终结果<br />
&nbsp; * <br />
&nbsp; * @param str<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public String IntegrationResultString(String str) {<br />
&nbsp;&nbsp;StringBuffer strBuffer = new StringBuffer();<br />
&nbsp;&nbsp;String numStr[] = null;<br />
&nbsp;&nbsp;if (str.indexOf(".") != -1) {<br />
&nbsp;&nbsp;&nbsp;numStr = str.split("\\.");<br />
&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;return strBuffer.append(createIntegerPartsResult(str)).toString();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;String fractionalStr = createFractionalPartsResult(numStr[1]);<br />
&nbsp;&nbsp;String integerStr = createIntegerPartsResult(numStr[0]);<br />
&nbsp;&nbsp;return strBuffer.append(integerStr).append(fractionalStr).toString();<br />
&nbsp;}</p>
<p>&nbsp;private String createIntegerPartsResult(String integer) {<br />
&nbsp;&nbsp;StringBuffer strBuffer = new StringBuffer();<br />
&nbsp;&nbsp;String temp = additionalZero(integer);<br />
&nbsp;&nbsp;String str1 = temp.substring(0, 4);<br />
&nbsp;&nbsp;strBuffer.append(transformNumberToString(str1, 1));<br />
&nbsp;&nbsp;String str2 = temp.substring(4, 8);<br />
&nbsp;&nbsp;strBuffer.append(transformNumberToString(str2, 2));<br />
&nbsp;&nbsp;String str3 = temp.substring(8, temp.length());<br />
&nbsp;&nbsp;strBuffer.append(transformNumberToString(str3, 3) + unit2[0]);<br />
&nbsp;&nbsp;return strBuffer.toString();<br />
&nbsp;}</p>
<p>&nbsp;private String createFractionalPartsResult(String fractionalStr) {<br />
&nbsp;&nbsp;StringBuilder strB = new StringBuilder();<br />
&nbsp;&nbsp;String s1 = fractionalStr.substring(0, 1);<br />
&nbsp;&nbsp;String s2 = fractionalStr.substring(1, fractionalStr.length());<br />
&nbsp;&nbsp;if (!s1.equals("0")) {<br />
&nbsp;&nbsp;&nbsp;strB.append(resplaceNumToStr(s1) + unit2[1]);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if (!s2.equals("0")) {<br />
&nbsp;&nbsp;&nbsp;strB.append(resplaceNumToStr(s2) + unit2[2]);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return strB.toString();<br />
&nbsp;}</p>
<p>&nbsp;public static void main(String args[]) {<br />
&nbsp;&nbsp;NumberToString test = new NumberToString();<br />
&nbsp;&nbsp;String str = "200123004054.11";<br />
&nbsp;&nbsp;System.out.println(test.IntegrationResultString(str));<br />
&nbsp;}<br />
}<br />
</p>
</fieldset><br />
<br />
<img src ="http://www.blogjava.net/kangdy/aggbug/336802.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2010-11-02 14:59 <a href="http://www.blogjava.net/kangdy/archive/2010/11/02/336802.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类和对象的初始化</title><link>http://www.blogjava.net/kangdy/archive/2010/07/14/326094.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Wed, 14 Jul 2010 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2010/07/14/326094.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/326094.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2010/07/14/326094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/326094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/326094.html</trackback:ping><description><![CDATA[<strong>类的生命周期</strong>：分为装载，链接，初始化 <br />
如图：<br />
<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/kangdy/147341.jpg" /><br />
<p><br />
1）装载：查找并装载类型的二进制数据<br />
2）连接：执行验证，准备，和解析（可选）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a)&nbsp;验证：确保导入类型正确<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b)&nbsp;准备：为类变量分配内存，并将其初始化为默认值<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c)&nbsp;解析：把类型中的符号引用转换成直接引用<br />
3）初始化：把类变量初始化为默认初值<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 随着Java虚拟机装载了一个类，并执行了一些它选择进行的验证之后，类就可以进入准备阶<br />
段了。在准备阶段，Java虚拟机为类变量分配内存，设置默认初始值：但在到达初始化阶段之前，<br />
类变量都没有被初始化为真正的初始值。(在准备阶段是不会执行Java代码的。)在准备阶段，虚<br />
拟机把给类变量新分配的内存根据类型设置为默认值。</p>
<p>&nbsp;为了准备让一个类或者接口被"首次主动"使用，最后一个步骤就是初始化，也就是为类变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
赋予正确的初始值。这里的&#8221;正确&#8221;初始值指的是程序员希望这个类变量所具备的起始值。正<br />
确的初始值是和在准备阶段赋予的默认初始值对比而言的。前面说过，根据类型的不同，类变<br />
量已经被赋予了默认初始值。而正确的初始值是根据程序员制定的主观计划面生成的。</p>
<p><br />
<span style="color: red">在Java代码中，一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。<br />
&nbsp;1）一个类变量初始化语句是变量声明后面的等号和表达式：<br />
&nbsp;2）静态初始化语句是一个以static开头的程序块<br />
</span>&nbsp;example :&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public class Example1 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 类变量初始化语句<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static int value = (int) (Math.random()*6.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 静态初始化语句<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("this is example");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
所有的类变量初始化语句和类型的静态初始化器都被Java编译器收集在—起，放到——个特殊<br />
的方法中。对于类来说，这个方法被称作类初始化方法；对于接口来说，它被称为接口初始化<br />
方法。在类和接口的Javaclass文件中，这个方法被称为&#8221;&lt;clinit&gt;&#8221;。通常的Java程序方法是无法<br />
调用这个&lt;clinit&gt;方法的。这种方法只能被Java虚拟机调用</p>
<p>clinit&gt;()方法<br />
&nbsp;&nbsp;&nbsp; 前面说过，Java编译器把类变量初始化语句和静态初始化浯句的代码都放到class文件的<br />
&lt;clinit&gt;()方法中，顺序就按照它们在类或者接门声明中出现的顺序。<br />
&nbsp;example: <br />
&nbsp;&nbsp;public class Example1 {<br />
&nbsp;&nbsp;&nbsp;&nbsp;static int width;<br />
&nbsp;&nbsp;&nbsp;&nbsp;static int height = (int) (Math.random()*6.0);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;static{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width = (int) (Math.random()*3.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;}<br />
java 编译器生成下面&lt;clinit&gt;方法：<br />
0 invokestatic java.lang.Math.random <br />
3 ldc2_w 6.0 (double) <br />
6 dmul <br />
7 d2i <br />
8 putstatic Example1.height <br />
11 invokestatic java.lang.Math.random <br />
14 ldc2_w 3.0 (double) 17 dmul <br />
18 d2i <br />
19 putstatic Example1.width <br />
22 return</p>
<p>clinit 方法首先执行唯一的类变量初始化语句初始化heght,然后在静态初始化语句中<br />
初始化width(<span style="color: red">虽然它声明在height之前，但那仅仅是声明了类变量而不是类变量初始化语句).</span></p>
<p>&nbsp;</p>
<p>除接口以外，<span style="color: red">初始化一个类之前必须保证其直接超类已被初始化</span>，并且该初始化过程是由 Jvm 保证线程安全的。<br />
另外，并非所有的类都会拥有一个 &lt;clinit&gt;() 方法。<br />
1）如果类没有声明任何类变量，也没有静态初始化语句，那么它不会有&lt;clinit&gt;()方法。<br />
2）如果声明了类变量但是没有使用类变量初始化语句或者静态初始化语句初始它们，那么类不会有&lt;clinit&gt;()方法。&nbsp;<br />
&nbsp;&nbsp; example: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class example{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;static int val;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
3）如果类仅包含静态 final 变量的类变量初始化语句，并且类变量初始化语句是编译时常量表达式，类不会有&lt;clinit&gt;()方法。<br />
&nbsp;&nbsp;&nbsp; example：<br />
&nbsp;&nbsp;&nbsp;&nbsp;public class Example {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static final String str ="abc";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static final int value = 100;<br />
&nbsp;&nbsp;&nbsp; }<br />
这种情况java编译器把 str 和 value 被看做是常量，jvm会直接使用该类的常量池或者在字节码中直接存放常量值。该类不会被加载。<br />
&nbsp; <br />
如果接口不包含在编译时解析成常量的字段初始化语句，接口中就包含一个&lt;clinit&gt;()方法。<br />
example:<br />
&nbsp;interface Example{<br />
&nbsp;&nbsp;int i =5;<br />
&nbsp;&nbsp;int hoursOfSleep = (int) (Math.random()*3.0);<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
字段hoursOfSleep会被放在&lt;clinit&gt;()方法中（<span style="color: red">比较诡异？？？它被看作类变量了</span>），而字段i被看作是编译时常量特殊处理(<span style="color: red"><span>JAVA语法规定，接口中的变量默认自动隐含是</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span></span>)。<br />
&nbsp;java 编译器生成下面&lt;clinit&gt;方法：<br />
0 invokestatic java.lang.Math.random<br />
3 ldc2_w 3.0 (double)<br />
6 dmul<br />
7 d2i<br />
8 putstatic Example.hoursOfSleep<br />
11 return<br />
<br />
主动使用和被动使用<br />
&nbsp;&nbsp;&nbsp; 在前面讲过，Java虚拟机在首次主动使用类型时初始化它们。只有6种活动被认为是主动使<br />
用：<br />
&nbsp;1)创建类的新实例，<br />
&nbsp;2)调用类中声明的静态方法，<br />
&nbsp;3)操作类或者接口中声明的非常量静态字段，<br />
&nbsp;4)调用JavaAPI中特定的反射方法<br />
&nbsp;5)初始化一个类的子类;<br />
&nbsp;6)以及指定一个类作为Java虚拟机启动时的初始化类。<br />
&nbsp;<br />
&nbsp;&nbsp; 使用一个非常量的静态字段只有当类或者接口的确声明了这个字段时才是主动使用、比如，<br />
类中声明的字段可能会被子类引用；接口中声明的字段可能会被子接口或者实现了这个接口的<br />
类引用。对于子类、子接口和实现接口的类来说．这就是被动使用(使用它们并不会触发<br />
它们的初始化)。下面的例子说明了这个原理：</p>
<p>class NewParement{<br />
&nbsp;static int hoursOfSleep = (int) (Math.random()*3.0);<br />
&nbsp;<br />
&nbsp;static{<br />
&nbsp;&nbsp;System.out.println("new parement is initialized.");<br />
&nbsp;}<br />
}</p>
<p>class NewbornBaby extends NewParement{<br />
&nbsp;static int hoursOfCry = (int) (Math.random()*2.0);<br />
&nbsp;<br />
&nbsp;static{<br />
&nbsp;&nbsp;System.out.println("new bornBaby is initialized.");<br />
&nbsp;}<br />
}</p>
<p><br />
public class Example1 {<br />
&nbsp;<br />
&nbsp;public static void main(String[] args){<br />
&nbsp;&nbsp;int hours = NewbornBaby.hoursOfSleep;<br />
&nbsp;&nbsp;System.out.println(hours);<br />
&nbsp;}<br />
&nbsp;static{<br />
&nbsp;&nbsp;System.out.println("example1 is initialized.");<br />
&nbsp;}<br />
&nbsp;<br />
}<br />
运行结果： <br />
example1 is initialized.<br />
new parement is initialized.<br />
0<br />
NewbornBaby 没有被初始化，也没有被加载。<br />
<br />
<br />
</p>
<p><strong>对象的生命周期<br />
</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当java虚拟机创建一个新的类实例时不管明确的还是隐含的，首先要在堆中为保存对象的实例变量分配内存，包含所有在对象类中和它超类中<br />
声明的变量（包括隐藏的实例变量）都要分配内存。其次赋默认初值，最后赋予正确的初始值。</p>
<p>java编译器为每个类都至少生成一个实例初始化方法 "&lt;init&gt;()"与构造方法相对应。</p>
<p>如果构造方法调用同一个类中的另一个构造方法(构造方法重载)，它对应的init&lt;&gt;():<br />
1)一个同类init&lt;&gt;()调用。<br />
2)对应构造方法体代码的调用。<br />
如果构造方法不是通过this()调用开始，且对象不是Object 它对应的init&lt;&gt;():<br />
1)一个超类init&lt;&gt;()调用。<br />
2)任意实例变量初始化代码调用。<br />
3)对应构造方法体代码的调用。<br />
如果上述对象是Object，则去掉第一条。如果构造方法明确使用super()首先调用对应超类init&lt;&gt;()其余不变。<br />
下面的例子详细说明了实例变量初始化(摘自Java Language Specification)<br />
class Point{<br />
&nbsp;int x,y;<br />
&nbsp;Point(){x=1;y=1;}<br />
}<br />
class ColoredPoint extends Point{<br />
&nbsp;int color = OxFF00FF;<br />
}<br />
class Test{<br />
&nbsp;public static void main(String[] args){<br />
&nbsp;&nbsp;ColoredPoint cp = new ColoredPoint();<br />
&nbsp;&nbsp;System.out.println(cp.color);<br />
&nbsp;}<br />
}<br />
首先，为新的ColoredPoint实例分配内存空间，以存储实例变量x,y和color；然后将这些变量初始化成默认值<br />
在这个例子中都是0。<br />
接下来调用无参数的ColoredPoint(),由于ColorPoint没有声明构造方法，java编译器会自动提供如下的构造方<br />
法：ColoredPoint(){super();}。<br />
该构造方法然后调用无参数的Point(),而Point()没有显示的超类，编译器会提供一个对其无参数的构造方法的<br />
隐式调用：Point(){super();x=1;y=1}。<br />
因此将会调用到Object();Object类没有超类，至此递归调用会终止。接下来会调用Object任何实例初始化语句<br />
及任何实例变量初始化语句。<br />
接着执行Object()由于Object类中未声明这样的构造方法。因此编译器会提供默认的构造方法object(){}。<br />
但是执行该构造方法不会产生任何影响，然后返回。<br />
接下来执行Point类实例变量初始化语句。当这个过程发生时，x,y的声明没有提供任何初始化表达式，因此这个<br />
步骤未采取任何动作(x,y 仍为0)；<br />
接下来执行Point构造方法体，将x,y赋值为1。<br />
接下来会执行类ColoredPoint的实例变量初始化语句。把color赋值0xFF00FF，最后执行ColoredPoint构造方法体<br />
余下的部分(super()调用之后的部分)，碰巧没有任何语句，因此不需要进一步的动作，初始化完成。</p>
<p>与C++不同的是，在创建新的类实例期间，java编程语言不会为方法分派来指定变更的规则。如果调用的方法在被<br />
初始化对象的子类中重写，那么就是用重写的方法。甚至新对象被完全初始化前也是如此。编译和运行下面的例子<br />
class Super{<br />
&nbsp;Super(){printThree();}<br />
&nbsp;void printThree{System.out.println("Three");}<br />
}<br />
class Test extends Super{<br />
&nbsp;int three = (int)Math.PI; // That is 3<br />
&nbsp;public static void main(String args[]){<br />
&nbsp;&nbsp;Test t = new Test();<br />
&nbsp;&nbsp;t.printThree();<br />
&nbsp;}<br />
&nbsp;void printThree(){System.out.println(three);}<br />
}<br />
输出：<br />
0<br />
3<br />
这表明Super类中的printThree()没有被执行。而是调用的Test中的printThree()。<br />
</p>
<p>&nbsp;</p>
<p>&nbsp;<br />
&nbsp;<br />
<br />
</p>
<img src ="http://www.blogjava.net/kangdy/aggbug/326094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2010-07-14 16:18 <a href="http://www.blogjava.net/kangdy/archive/2010/07/14/326094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java虚拟机体系结构</title><link>http://www.blogjava.net/kangdy/archive/2010/07/06/325357.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Tue, 06 Jul 2010 05:47:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2010/07/06/325357.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/325357.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2010/07/06/325357.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/325357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/325357.html</trackback:ping><description><![CDATA[<p>Java虚拟机体系结构<br />
<br />
<br />
<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/kangdy/27014_1263615671XiXS.jpg" /></p>
<p><strong>方法区</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在Java虚拟机中，被装载类型的信息存储在一个逻辑上被称为方法区的内存中。<br />
&nbsp;当虚拟机装载某个类型时，它使用类装载器定位相应的class文件，--&gt;读入这个class文件（一个线性的二进制流）-&gt;将它传入虚拟机--&gt;<br />
&nbsp;虚拟机提取类型信息，并将信息存入方法区，<span style="color: red">类型中的类（静态）变量也存储在方法区</span>.<br />
&nbsp;方法区特点：<br />
&nbsp;1)所有线程共享方法区。它是线程安全的。<br />
&nbsp;2)方法区大小不是固定的。虚拟机根据需要自行调整。<br />
&nbsp;3)方法区可以被垃圾回收。<br />
&nbsp;对于每个被装载的类型，虚拟机会在方法区中存储以下信息。<br />
&nbsp;<br />
&nbsp;1)类型的基本信息;<br />
&nbsp;&nbsp;&nbsp; &nbsp;a)类型的全限定名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b)类型的直接超类全限定名(除非这个类型是java.lang.Objet,它没超类)。<br />
&nbsp;&nbsp;&nbsp; &nbsp;c)类型是类类型还是接口类型(就是说是一个类还是一个接口)。<br />
&nbsp;&nbsp;&nbsp; &nbsp;d)类型的访问修饰符(public ,abstract或final的某个子类)<br />
&nbsp;&nbsp;&nbsp; &nbsp;e)任何直接超接口的全限定名的有序列表。<br />
&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;2)该类型的常量池<br />
&nbsp;&nbsp;&nbsp;虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合，<br />
&nbsp;&nbsp;&nbsp;包括直接常量(string，integer,floating point常量)和对其他类型、字段和方法的符号引用。<br />
&nbsp;&nbsp;&nbsp;池中的数据项就像数组一样是通过索引访问的。因为常量池存储了相应类型所用到的所有类型、<br />
&nbsp;&nbsp;&nbsp;字段和方法的符号引用，所以它在Java程序的动态连接中起着核心的作用。<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;3)字段信息<br />
&nbsp;&nbsp;&nbsp;类型中声明的每一个字段，方法区中必须保存下面的信息，字段在类或接口中声明的顺序也必须保存。<br />
&nbsp;&nbsp;&nbsp;字段名，字段类型，字段修饰符(public private protected static final 等)<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;4)方法信息<br />
&nbsp;&nbsp;&nbsp;类型中声明的每一个方法，方法区中必须保存下面的信息，方法在类或接口中声明的顺序也必须保存。<br />
&nbsp;&nbsp;&nbsp;方法名，返回值类型，参数数量和类型(按声明顺序)，方法修饰符(public private protected static final 等)<br />
&nbsp;&nbsp;&nbsp;如果方法不是抽象的或本地的还必须保存：方法字节码，操作数栈和该方法在栈针中局部变量的大小，异常表。<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;5)除了常量以外的所有类(静态)变量<br />
&nbsp;&nbsp;&nbsp;这里主要说下编译时常量：<span style="color: red">就是那些用final声明以及编译时已知的值初始化的类变量(例如：static final int val =5)<br />
&nbsp;&nbsp;&nbsp;每个编译时常量的类型都会复制它所有常量到它自己的常量池中或者它的字节码流中(通常情况下编译时直接替换字节码)。</span><br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;6)一个到类classLoader的引用<br />
&nbsp;&nbsp;&nbsp;指向ClassLoader类的引用&nbsp; 每个类型被装载的时候，虚拟机必须跟踪它是由启动类装载器<br />
&nbsp;&nbsp;&nbsp;还是由用户自定义类装载器装载的。如果是用户自定义类装载器装载的，那么虚拟机必须在类<br />
&nbsp;&nbsp;&nbsp;型信息中存储对该装载器的引用：这是作为方法表中的类型数据的一部分保存的。<br />
&nbsp;&nbsp;&nbsp;虚拟机会在动态连按期间使用这个信息。当某个类型引用另一个类型的时候，虚拟机会请求装载<br />
&nbsp;&nbsp; 发起引用类型的类装载器来装载被引用的类型。这个动态连接的过程，对于虚拟机分离命名空间<br />
&nbsp;&nbsp; 的方式也是至关重要的。为了能够正确地执行动态连接以及维护多个命名空间，虚拟机需要在方<br />
&nbsp;&nbsp; 法表中得知每个类都是由哪个类装载器装载的。<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;7)一个到Class类的引用<br />
&nbsp;&nbsp;&nbsp; 指向Class类的引用&nbsp; <span style="color: red">对于每一个被装载的类型(不管是类还是接口)，虚拟机都会相应地为<br />
&nbsp;&nbsp; &nbsp;它创建一个java.lang．Class类的实例（Class实例放在内存中的堆区），</span>而且虚拟机还必须以某种方式把这个实例的引用存储在方法区<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了尽可能提高访问效率，设计者必须仔细设计存储在方法区中的类型信息的数据结构，因此，<br />
除了以上时论的原始类型信息，实现中还可能包括其他数据结构以加快访问原始数据的速度，比如方法表。<br />
虚拟机对每个装载的非抽象类，都生成一个方法表，把它作为类信息的一部分保存在方法区。方法表是一个数组，<br />
它的元素是所有它的实例可能被调用的实例方法的直接引用，包括那些从超类继承过来的实例方法：(对于抽象类和接口，方法表没有什么帮<br />
助，因为程序决不会生成它们的实例。)运行时可以通过方法表快速搜寻在对象中调用的实例方法。<br />
&nbsp;<br />
方法区使用的例子</p>
<p>&nbsp;class Lava{<br />
&nbsp;&nbsp;private int speed = 5;<br />
&nbsp;<br />
&nbsp;&nbsp;void flow(){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;}</p>
<p>&nbsp;public class Volcano {<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;public static void main(String args[]){<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;Lava lava = new Lava();<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;lava.flow();<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>&nbsp; 1)虚拟机在方法区查找Volcano这个名字，未果，载入volcano.class文件，并提取相应信息<br />
&nbsp; &nbsp;存入方法区。<br />
&nbsp; 2)虚拟机开始执行Volcano类中main()方法的字节码的时候，尽管Lava类还没被装载，<br />
&nbsp;&nbsp;但是和大多数(也许所有)虚拟机实现一样，它不会等到把程序中用到的所有类都装载后才开<br />
&nbsp;&nbsp;始运行程序。恰好相反，它只在需要时才装载相应的类。<br />
&nbsp; 3)main()的第一条指令告知虚拟机为列在常量池第一项的类分配足够的内存。所以虚拟机<br />
&nbsp;&nbsp;使用指向Volcano常量池的指针找到第一项，发现它是一个对Lava类的符号引用，然后它就检查<br />
&nbsp;&nbsp;方法区，看Lava类是否已经被装载了。<br />
&nbsp; 4)当虚拟机发现还没有装载过名为"Lava"的类时，它就开始查找并装载文件&#8220;Lava.class&#8221;，<br />
&nbsp;&nbsp;并把从读入的二进制数据中提取的类型信息放在方法区中。<br />
&nbsp; 5)虚拟机以一个直接指向方法区Lava类数据的指针来替换常量池第—项(就是那个<br />
&nbsp;&nbsp;字符串&#8220;Lava&#8221;)——以后就可以用这个指针来快速地访问Lava类了。这个替换过程称为常量池<br />
&nbsp;&nbsp;解析，即把常量池中的符号引用替换为直接引用：这是通过在方法区中搜索被引用的元素实现<br />
&nbsp;&nbsp;的，在这期间可能又需要装载其他类。在这里，我们替换掉符号引用的&#8220;直接引用&#8221;是一个本<br />
&nbsp;&nbsp;地指针。<br />
&nbsp; 6)虚拟机准备为一个新的Lava对象分配内存。此时，它又需要方法区中的信息。还记<br />
&nbsp;&nbsp;得刚刚放到Volcano类常量池第——项的指针吗?现在虚拟机用它来访问Lava类型信息(此前刚放<br />
&nbsp;&nbsp;到方法区中的)，找出其中记录的这样一个信息：一个Lava对象需要分配多少堆空间。 <br />
&nbsp; 7)虚拟机确定一个Lava对象大小后，就在堆上分配空间，并把这个对象实例变量speed初始化为默认初始值0<br />
&nbsp;&nbsp;8)当把新生成的Lava对象的引用压到栈中，main()方法的第一条指令也完成了,指令通过这个引用<br />
&nbsp;&nbsp;调用Java代码(该代码把speed变量初始化为正确初始值5).另外用这个引用调用Lava对象引用的flow()方法。</p>
<p><strong>堆</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;每个java虚拟机实例都有一个方法区以及一个堆，一个java程序独占一个java虚拟机实例，而每个java程序都有自己的堆空间，它们不会彼此干扰,但同一个java程序的多个线程共享一个堆空间。这种情况下要考虑多线程访问同步问题。<br />
&nbsp;<br />
<strong>Java栈<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个新线程被创建时，都会得到自己的PC寄存器和一个java栈，虚拟机为每个线程开辟内存区。这些内存区是私有的，任何线程不能访问其他线程的PC寄存器和java栈。java栈总是存储该线程中java方法的调用状态。包括它的局部变量，被调用时传进来的参数，它的返回值，以及运算的中间结果等。java栈是由许多栈帧或者说帧组成，一个栈帧包含一个java方法的调用状态，当线程调用java方法时，虚拟机压入一个新的栈帧到该线程的java栈中。当方法返回时，这个栈帧被从java栈中弹出并抛弃。<br />
<strong>.本地方法栈<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;任何本地方法接口都会使用某种本地方法饯。当线程调用Java方法时，虚拟机会创建一个新的栈帧井压人Java栈。<br />
然而当它调用的是本地方法时，虚拟机会保持Java栈不变，不再在线程的Java栈中压人新的帧，虚拟机只是简单地动态连接<br />
并直接调用指定的本地方法。可以把这看做是虚拟机利用本地方法来动态扩展自己。</p>
<img src ="http://www.blogjava.net/kangdy/aggbug/325357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2010-07-06 13:47 <a href="http://www.blogjava.net/kangdy/archive/2010/07/06/325357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>