JDK源码阅读之Double

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>=107则使用科学计数法表示。

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.0 0x1.0p0
-1.0 -0x1.0p0
2.0 0x1.0p1
3.0 0x1.8p1
0.5 0x1.0p-1
0.25 0x1.0p-2
Double.MAX_VALUE 0x1.fffffffffffffp1023
Minimum Normal Value 0x1.0p-1022
Maximum Subnormal Value 0x0.fffffffffffffp-1022
Double.MIN_VALUE 0x0.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的数都大。

文章同步【个人站】

原创文章 234 获赞 1294 访问量 23万+

猜你喜欢

转载自blog.csdn.net/qq_25343557/article/details/100641593
今日推荐