Double

      Double是基本类型double的包装类,学习之前建议阅读【Jdk源码阅读之Float】相信能更加理解Double。

类图

Double类图

public final class Double extends Number implements Comparable<Double>

      通过类图和源码我们可以知道Double是不可被继承的,并且Double类型的实例对象是可以比较的。由于Double继承了Number(这是一个抽象类),所以Double重写了其所有形如xxxValue的方法。
Number

成员变量

public static final double POSITIVE_INFINITY = 1.0 / 0.0;         //正无穷
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;        //负无穷
public static final double NaN = 0.0d / 0.0;                     //NaN
public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308  保存 double 类型的最大正有限值的常量
public static final double MIN_NORMAL = 0x1.0p-1022;             // 2.2250738585072014E-308  保存 double 类型的最小正标准值的常量
public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324  保存 double 类型的最小正非零值的常量
public static final int MAX_EXPONENT = 1023;                    //有限 double 变量可能具有的最大指数。
public static final int MIN_EXPONENT = -1022;                    //标准化 double 变量可能具有的最小指数
public static final int SIZE = 64;                                //64位
public static final int BYTES = SIZE / Byte.SIZE;                //8字节
public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");
private final double value;

      Double对象的值保持在value中,并且value是不可变的。

构造方法

public Double(double value) {
    this.value = value;
}
public Double(String s) throws NumberFormatException {
    value = parseDouble(s);
}
public static double parseDouble(String s) throws NumberFormatException {
    return FloatingDecimal.parseDouble(s);
}

      Double有两个构造方法,可传入double,String类型的值,其中String会借助FloatingDecimal的parseDouble方法进行转换。我们可以传入"NaN","Infinity","0x"开头的十六进制串,科学计数法表示的字符串。

valueOf

public static Double valueOf(String s) throws NumberFormatException {
    return new Double(parseDouble(s));
}
public static Double valueOf(double d) {
    return new Double(d);
}

      valueOf与构造方法传递参数一样。与Byte,Integer等包装类的valueOf可从缓存中获取-128~127范围内的对象不同,Double调用valueOf都是new实例。

xxxValue

public byte byteValue() {
    return (byte)value;
}
public short shortValue() {
    return (short)value;
}
public int intValue() {
    return (int)value;
}
public long longValue() {
    return (long)value;
}
public float floatValue() {
    return (float)value;
}
public double doubleValue() {
    return value;
}

      这六个方法都是继承自Number类,将value值强转为对应的类型。

toString

public String toString() {
    return toString(value);
}
public static String toString(double d) {
    return FloatingDecimal.toJavaFormatString(d);
}

      返回d的字符串表示。如果d是NaN,返回"NaN";如果d是负数则以'-'为起始标识,正数无标识;如果d是infinity,正数返回Infinity,负数返回-Infinity;如果d是0.0,-0.0返回"-0.0",0.0返回"0.0";如果d<10^-3或d>=10^7则使用科学计数法表示。

toHexString

      方法有点长,这里不展示了,此方法返回 double 参数的十六进制字符串表示形式。

  • 如果参数为 NaN,那么结果为字符串 "NaN"。
  • 否则,结果是表示参数符号和数值的字符串。如果符号为负,那么结果的第一个字符是 '-' ('u002D');如果符号为正,那么结果中不显示符号字符。对于数值 m:

    • 如果 m 为无穷大,则用字符串 "Infinity" 表示;因此,正无穷大生成结果 "Infinity",负无穷大生成结果 "-Infinity"。
    • 如果 m 为 0,则用字符串 "0x0.0p0" 表示;因此,负 0 生成结果 "-0x0.0p0",正 0 生成结果 "0x0.0p0"。
    • 如果 m 是具有标准化表示形式的 double 值,则使用子字符串表示有效数字和指数字段。有效数字用字符 "0x1." 表示,后跟该有效数字剩余小数部分的小写十六进制表示形式。除非所有位数都为 0,否则移除十六进制表示中的尾部 0,在所有位数都为零的情况下,可以用一个 0 表示。接下来用 "p" 表示指数,后跟无偏指数的十进制字符串,该值与通过对指数值调用 Integer.toString 生成的值相同。
    • 如果 m 是非标准表示形式的 double 值,则用字符 "0x0." 表示有效数字,后跟该有效数字剩余小数部分的十六进制表示形式。移除十六进制表示中的尾部 0。然后用 "p-1022" 表示指数。注意,在非标准有效数字中,必须至少有一个非 0 数字。
浮点值十六进制字符串
1.00x1.0p0
-1.0-0x1.0p0
2.00x1.0p1
3.00x1.8p1
0.5 0x1.0p-1
0.25 0x1.0p-2
Double.MAX_VALUE0x1.fffffffffffffp1023
Minimum Normal Value 0x1.0p-1022
Maximum Subnormal Value 0x0.fffffffffffffp-1022
Double.MIN_VALUE0x0.0000000000001p-1022

isXXX

public boolean isNaN() {
    return isNaN(value);
}
public static boolean isNaN(double v) {
    return (v != v);
}

public boolean isInfinite() {
    return isInfinite(value);
}
public static boolean isInfinite(double v) {
    return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
public static boolean isFinite(double d) {
    return Math.abs(d) <= DoubleConsts.MAX_VALUE;
}
public static boolean isFinite(double d) {
    return Math.abs(d) <= DoubleConsts.MAX_VALUE;
}

       通过isNaN方法我们可以了解到Double.NaN != Double.NaN。Java 提供的任何 IEEE 754 浮点操作都不能区分具有不同位模式的两个同类型 NaN 值。不同的 NaN 值只能使用 Double.doubleToRawLongBits 方法区分。

max/min

public static double max(double a, double b) {
    return Math.max(a, b);
}
public static double min(double a, double b) {
    return Math.min(a, b);
}

hashCode

public int hashCode() {
    return Double.hashCode(value);
}
public static int hashCode(double value) {
    long bits = doubleToLongBits(value);
    return (int)(bits ^ (bits >>> 32));
}

/**
 * 根据 IEEE 754 浮点双精度格式 ("double format") 位布局,返回指定浮点值的表示形式。
 * 先通过调用doubleToLongBits获取到IEEE 754标准对应的整型数,然后再分别用 
 * DoubleConsts.EXP_BIT_MASK和DoubleConsts.SIGNIF_BIT_MASK两个掩码去判断是否为NaN,0x7ff8000000000000L对 
 * 应的即为NaN。
 */
public static long doubleToLongBits(double value) {
    long result = doubleToRawLongBits(value);
    // Check for NaN based on values of bit fields, maximum
    // exponent and nonzero significand.
    if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
          DoubleConsts.EXP_BIT_MASK) &&
         (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
        result = 0x7ff8000000000000L;
    return result;
}

      与doubleToLongBits先对的方法是longBitsToDouble,它返回对应于给定位表示形式的 double 值。如果参数是 0x7ff0000000000000L,则结果为正无穷大。如果参数是 0xfff0000000000000L,则结果为负无穷大。如果参数值在 0x7ff0000000000001L 到 0x7fffffffffffffffL 之间或者在 0xfff0000000000001L 到 0xffffffffffffffffL 之间,则结果为 NaN。

equals

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

      首先判断是否为Double对象,如果是则比较doubleToLongBits方法的返回值是否相等。

compareTo

public int compareTo(Double anotherDouble) {
    return Double.compare(value, anotherDouble.value);
}
public static int compare(double d1, double d2) {
    if (d1 < d2)
        return -1;           // Neither val is NaN, thisVal is smaller
    if (d1 > d2)
        return 1;            // Neither val is NaN, thisVal is larger

    // doubleToRawLongBits,因为可能为NaN.
    long thisBits    = Double.doubleToLongBits(d1);
    long anotherBits = Double.doubleToLongBits(d2);

    return (thisBits == anotherBits ?  0 : // Values are equal
            (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
             1));                          // (0.0, -0.0) or (NaN, !NaN)
}

      d1小于d2则返回-1,反之则返回1。无法通过上述直接比较时则使用doubleToLongBits方法分别将d1和d2转成IEEE 754标准对应的整型数,然后再比较。相等则返回0,否则返回-1或1。注意:正0比负0大;NaN比任何非NaN的数都大。

Last modification:September 8th, 2019 at 10:48 pm
如果觉得我的文章对你有用,请随意赞赏