【Java】JDK源碼分析——Double

一.概述

Double是double的包裝類,用於表示雙精度浮點數。
Double的表示方法和int、short、long不同。Double滿足IEEE754浮點數表示法。
Double表示的數值佔8個字節,共64位。其中0到51位表示尾數部分;52到63位表示指數部分;64位爲符號位。
在這裏插入圖片描述
Double.java中的相關代碼:

public final class Double extends Number implements Comparable<Double> {}

1.Double被final修飾,不能被繼承。
2.繼承了Number,可以實現數值間的轉換。
3.實現了Comparable<Double>接口,可以進行Double類型對象之間的比較。

二.源碼分析

1.全局變量

Double.java中的相關代碼:

	// 表示正無窮
	// 它的值和Double.longBitsToDouble(0x7ff0000000000000L)計算的結果相同
	public static final double POSITIVE_INFINITY = 1.0 / 0.0;

	// 表示負無窮
	// 它的值和Double.longBitsToDouble(0xfff0000000000000L)計算的結果相同
	public static final double NEGATIVE_INFINITY = -1.0 / 0.0;

	// 表示不是一個數,即一個數不能被表示
	// 它的值和Double.longBitsToDouble(0x7ff8000000000000L)計算的結果相同
	public static final double NaN = 0.0d / 0.0;

	// 表示double所能表示的最大值:1.7976931348623157e+308
	// 它的值和Double.longBitsToDouble(0x7fefffffffffffffL)計算的結果相同
	public static final double MAX_VALUE = 0x1.fffffffffffffP+1023;

	// 表示正常情況下,double可以表示的最小正數:2.2250738585072014E-308
	// 正常情況爲小數點前爲0x1
	// 它的值和Double.longBitsToDouble(0x0010000000000000L)計算的結果相同
	public static final double MIN_NORMAL = 0x1.0p-1022;

	// 表示double實際上可以表示的最小非零正數:4.9e-324
	// 小數點前爲0x0
	// 它的值和Double.longBitsToDouble(0x1L)計算的結果相同
	public static final double MIN_VALUE = 0x0.0000000000001P-1022;

	// double可以表示的最大指數
	public static final int MAX_EXPONENT = 1023;

	// double可以表示的最小指數
	public static final int MIN_EXPONENT = -1022;

	// double佔的位數
	public static final int SIZE = 64;

	// 一個double數值佔的字節數
	public static final int BYTES = SIZE / Byte.SIZE;

	// 抑制沒有類型檢查而出現的警告
	@SuppressWarnings("unchecked")
	// Double類中對應的原始的double
	// Double.class和double.class不相等,但Double.TYPE和double.class相等
	public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");

	// 用於存儲double的數值
	private final double value;

	// 用於序列化
	private static final long serialVersionUID = -9172774392245257468L;

2.構造方法

1)參數爲double

Double.java中的相關代碼:

	public Double(double value) {
    	// 保存到全局變量
        this.value = value;
	}

2)參數爲String

Double.java中的相關代碼:

	public Double(String s) throws NumberFormatException {
    	// 調用parseDouble方法,將字符串解析成double型數值
        value = parseDouble(s);
	}

3. parseDouble方法

將字符串解析成double型數值。
Double.java中的相關代碼:

	public static double parseDouble(String s) throws NumberFormatException {
    	// 調用FloatingDecimal的parseDouble方法
        return FloatingDecimal.parseDouble(s);
	}

4. valueOf方法

1)參數爲double

將double型數值轉換爲Double對象。
Double.java中的相關代碼:

	public static Double valueOf(double d) {
    	// 創建Double對象,對double數值進行封裝,返回
        return new Double(d);
	}

2)參數爲String

將String對象轉換爲Double對象。
Double.java中的相關代碼:

	public static Double valueOf(String s) throws NumberFormatException {
    	// 調用parseDouble方法,將字符串解析成double型數值
    	// 創建Double對象,對double數值進行封裝,返回
        return new Double(parseDouble(s));
	}

5. isNaN方法

判斷當前的數是不是數值型的數。
Double.java中的相關代碼:

	public boolean isNaN() {
    	// 調用了重載方法
        return isNaN(value);
	}

調用重載的isNaN方法。
判斷double型的數是不是數值型的數。
Double.java中的相關代碼:

	public static boolean isNaN(double v) {
    	// 每個NaN的存儲地址不同
        return (v != v);
	}

6. isInfinite方法

判斷當前的數是不是無窮大。
Double.java中的相關代碼:

	public boolean isInfinite() {
    	// 調用了重載方法
        return isInfinite(value);
	}

調用了重載的isInfinite方法。
判斷double型的數是不是無窮大。
Double.java中的相關代碼:

	public static boolean isInfinite(double v) {
    	// 判斷是否爲正無窮或負無窮
        return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
	}

7. isFinite方法

判斷一個double型的數是否有限。
Double.java中的相關代碼:

	public static boolean isFinite(double d) {
    	// 對double數取絕對值,判斷是否小於等於double能表示的最大值
        return Math.abs(d) <= DoubleConsts.MAX_VALUE;
	}

8. doubleToLongBits方法

將double型的數轉換成滿足IEEE 754浮點型表示法的long型的數。

符號位MASK:0x8000000000000000L
指數位MASK:0x7ff0000000000000L
有效位MASK:0x000fffffffffffffL
正無窮:0x7ff0000000000000L
負無窮:0xfff0000000000000L
NaN:0x7ff8000000000000L

Double.java中的相關代碼:

	public static long doubleToLongBits(double value) {
    	// 調用doubleToRawLongBits轉換成long型的數
		// 詳解在1)處
        long result = doubleToRawLongBits(value);
        // 根據指數位和非零有效位判斷是不是NaN
        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
              DoubleConsts.EXP_BIT_MASK) &&
             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
            // 若是,則設置爲NaN
            result = 0x7ff8000000000000L;
        // 返回
        return result;
	}

1)doubleToRawLongBits方法

Double.java中的相關代碼:

	public static native long doubleToRawLongBits(double value);

該方法是一個native方法,該方法會將一個double型的數轉換成滿足IEEE 754浮點型表示法的long型的數,即使該數爲NaN,也會進行轉換。

9. longBitsToDouble方法

將long型的數按照IEEE 754浮點數標準轉換爲double型的數。
Double.java中的相關代碼:

	public static native double longBitsToDouble(long bits);

該方法是一個native方法。

10. toString方法

將Double對象轉換爲String對象。
Double.java中的相關代碼:

	public String toString() {
    	// 調用了重載方法
        return toString(value);
	}

調用了重載的toString方法。
Double.java中的相關代碼:

	public static String toString(double d) {
    	// 調用FloatingDecimal的toJavaFormatString方法
        return FloatingDecimal.toJavaFormatString(d);
	}

11. toHexString方法

將double型的數轉換爲十六進制的String對象。
Double.java中的相關代碼:

    public static String toHexString(double d) {
        // 若該數不是有限的,即超過了double型的最大值或者爲NaN
        if (!isFinite(d) )
            // 調用toString方法進行轉換
            return Double.toString(d);
        else { // 若該數有限
            // 用來保存轉換的十六進制的字符串
            StringBuilder answer = new StringBuilder(24);

            // 若爲負數
            if (Math.copySign(1.0, d) == -1.0)
                // 拼接一個負號
                answer.append("-");
            // 拼接16進制的標識符
            answer.append("0x");
            // 求絕對值
            d = Math.abs(d);
            
            // 若數值爲0
            if(d == 0.0) {
                // 則拼接“0.0p0”,即0乘以2的0次方,爲0
                answer.append("0.0p0");
            } else { // 若不爲零
                // 判斷數值是否超過了正常的最小正數
                boolean subnormal = (d < DoubleConsts.MIN_NORMAL);

                // 調用doubleToLongBits方法
				// 將其轉換成滿足IEEE 754浮點型標準的long型數
				// 進行與運算,64到52位變爲0
				// 提取51到0位,即有效位(尾數部分)
				// 最後進行或運算,最高位,即64位,置爲1
                long signifBits = (Double.doubleToLongBits(d)
                                   & DoubleConsts.SIGNIF_BIT_MASK) |
                    0x1000000000000000L;

                // 若數值小於正常的最小正數
                // 則拼接”0.”,即0x0.
                // 否則,拼接”1.”,即0x1.
                answer.append(subnormal ? "0." : "1.");

                // 調用Long的toHexString方法
				// 將有效位轉換爲16進製表示的字符串,截取從第三位到第十六位
                // 64位二進制轉換位十六進制爲16位(0到15)
                // 十六位中,前三位(0,1,2)表示符號位和指數部分
				// 有效位從第四位(3)開始
                String signif = Long.toHexString(signifBits).substring(3,16);
                // 若有效位都是0,則直接拼接一個”0”
                // 若不全爲0,則進行正則表達式匹配
                // 從後向前,去掉最少一個最多12個的”0”
                answer.append(signif.equals("0000000000000") ?
                              "0":
                              signif.replaceFirst("0{1,12}$", ""));

                // 拼接p,表示指數中以2爲底數
                answer.append('p');
                // 若數值小於正常的最小正數
				// 則指數部分拼接最小指數
				// 否則,調用Math的getExponent方法獲取指數,再拼接
                answer.append(subnormal ?
                              DoubleConsts.MIN_EXPONENT:
                              Math.getExponent(d));
            }
            // 獲取字符串,返回
            return answer.toString();
        }
	}

12. byteValue方法

獲取當前數值對應的byte型數。
Double.java中的相關代碼:

	public byte byteValue() {
	    // 進行類型轉換,返回
        return (byte)value;
	}

13. shortValue方法

獲取當前數值對應的short型數。
Double.java中的相關代碼:

	public short shortValue() {
	    // 進行類型轉換,返回
        return (short)value;
	}

14. intValue方法

獲取當前數值對應的int型數。
Double.java中的相關代碼:

    public int intValue() {
   	 	// 進行類型轉換,返回
        return (int)value;
	}

15. longValue方法

獲取當前數值對應的long型數。
Double.java中的相關代碼:

	public long longValue() {
    	// 進行類型轉換,返回
        return (long)value;
	}

16. floatValue方法

獲取當前數值對應的float型數。
Double.java中的相關代碼:

	public float floatValue() {
    	// 進行類型轉換,返回
        return (float)value;
	}

17. doubleValue方法

獲取當前數值對應的double型數。
Double.java中的相關代碼:

	public double doubleValue() {
    	// 直接返回
        return value;
	}

18. hashCode方法

獲取Double對象的哈希值。
Double.java中的相關代碼:

    @Override
	public int hashCode() {
	    // 調用Double的靜態方法
        return Double.hashCode(value);
	}

1)hashCode方法

Double.java中的相關代碼:

	public static int hashCode(double value) {
 	   // 將value轉換成滿足IEEE 754浮點型標準的long型數
        long bits = doubleToLongBits(value);
        // 將其不帶符號右移32位,再和原數進行異或運算
        // 最後進行類型轉換,返回
        return (int)(bits ^ (bits >>> 32));
	}

19. equals方法

比較兩個Double對象是否相等。
Double.java中的相關代碼:

	public boolean equals(Object obj) {
    	// 若類型爲Double
    	// 同時轉換爲long型後比較相等,則返回true
        return (obj instanceof Double)
               && (doubleToLongBits(((Double)obj).value) ==
                      doubleToLongBits(value));
	}

20. compareTo方法

對兩個Double對象進行比較。
若相等,則返回0。若大於anotherDouble則返回1,小於則返回-1。
Double.java中的相關代碼:

	public int compareTo(Double anotherDouble) {
	    // 調用Double的靜態方法compare
        return Double.compare(value, anotherDouble.value);
	}

1)compare方法

Double.java中的相關代碼:

	public static int compare(double d1, double d2) {
    	// 若小於,則返回-1
        if (d1 < d2)
            return -1;
        // 若大於,則返回1
        if (d1 > d2)
            return 1; 

        // 此時兩個數可能相等,或至少其中一個爲NaN
        // 調用doubleToLongBits方法進行轉換
        long thisBits    = Double.doubleToLongBits(d1);
        long anotherBits = Double.doubleToLongBits(d2);

        // 若相等,則返回0
        // 若小於,說明thisBits =-0.0, anotherBits = 0.0)
        // 或thisBits != NaN, anotherBits = NaN
        // 若大於,說明thisBits =0.0, anotherBits = -0.0)
        // 或thisBits = NaN, anotherBits != NaN
        return (thisBits == anotherBits ?  0 :
                (thisBits < anotherBits ? -1 :
                 1)); 
	}

21. sum方法

求兩個double數的和
Double.java中的相關代碼:

	public static double sum(double a, double b) {
		// 相加,返回
        return a + b;
	}

22. max方法

求兩個double數的最大值。
Double.java中的相關代碼:

	public static double max(double a, double b) {
    	// 調用Math的max方法
        return Math.max(a, b);
	}

23. min方法

求兩個double數的最小值。
Double.java中的相關代碼:

	public static double min(double a, double b) {
		// 調用Math的min方法
        return Math.min(a, b);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章