J2se源码剖析 基本数据类型double

时间:2021-07-28 17:24:57

前言

今天要分析的Double源码与我上一篇博客的 java源码剖析 Inteager都是属于 java.lang中的,并且都是继承于Number,都实现了Comparable,在上一篇博客中我没有详细说明实现这个Comparable的接口到底有什么用,在这篇博客我会为大家说明这个Comparable的接口到底在Double类中实现了什么东西,接下来我们看Double中的这一段代码,

/*实现Comparable接口使Doubel对象变成可比较的对象 */
public final class Double extends Number implements Comparable<Double> {

/*在java中将 1.0 /2.0 设置为正无穷大即 Infinity*/
public static final double POSITIVE_INFINITY = 1.0 / 0.0;
/* 与上面相反 负无穷大 即 -Infinity */
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;

/* 将 0.0 /0.0 设置为一个非数字的字符串*/
public static final double NaN = 0.0d / 0.0;
/* 设置最大值为1.7976931348623157e+308*/
public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308
Double.longBitsToDouble(0x0010000000000000L)}.

/* 保存 double 类型的最小正标准值的常量,最小正标准值为 2-1022。它等于十六进制的浮点字面值 0x1.0p-1022,也等于Double.longBitsToDouble(0x0010000000000000L)。 */

public static final double MIN_NORMAL = 0x1.0p-1022;
/*指数部最大值为2^1023 */
public static final int MAX_EXPONENT = 1023;
/*指数部最小值为2^-1022 */
static final int MIN_EXPONENT = -1022;

/*设置 长度为64位*/
public static final int SIZE = 64;
/* 设置为 8个字节*/
public static final int BYTES = SIZE / Byte.SIZE;
/*表示基本类型 double 的 Class 实例。 */
@SuppressWarnings("unchecked")
public static final Class<Double> TYPE = (Class<Double>) Class.getPrimitiveClass("double");

看完上面的代码,我们先来讲解下实现这个Comparable 到底有什么用

  • 首先它是一个接口 用于对自定义的class比较大小的,
  • 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,
    但是需要修改源代码
  • 实现这个接口必须重写他的方法compareTo 用于来比较当前对象

往下看我们能看到这些变量都生命了Double的基本特征 最大值 最小值 包括一些特殊的处理 别 0.0 /0.0 将它设置为一个非double的字符串,1.0/0.0 -1.0/0.0 分别将他们设置为正无穷与负无穷

无独有偶 每个基本数据类型都有它的toString方法 double也不例外,接下来我们讲解他的toString方法

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

正如你所看到的这两个方法,让我们来了解这个两个方法到底做了什么,首先调用toString方法返回的时候调用 一个带参的toString方法 ,这是我传入value,value这个值就是对象构造方法传进去的值,请看这行代码,你就知道value是什么了

public Double(double value) {
this.value = value;
}

我们现在已经知道value的值是什么,现在让我们来了解这个带参的toString到底做了什么
再传如value之后我们直接调用了FloatingDecimal.toJavaFormatString(d);直接返回了这个方法的返回值,FloatingDecimal.toJavaFormatString(d)这个方法将穿进去的Double值转换成字符串再返回 关于这个类的源码在这里 有兴趣的朋友可以去阅读以下 http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html 在这里我就不讲解了(主要是博主实力没到这种境界)

现在让我们来Double的下一个方法toHexString() 正如他的方法名字,将Double的值转换成十六进制,并返回成字符串,现在让我们来看一下他的源代码

    public static String toHexString(double d) {

if (!isFinite(d) ) //判断是否超过double的最大值与最小值

return Double.toString(d);//如果超出了范围就返回他的字符串
else {

StringBuilder answer = new StringBuilder(24);//声明了一个StringBuilder

if (Math.copySign(1.0, d) == -1.0) //通过Math.copySign 返回的值来判断传入的double值是否为负数,如果是负数就是在上面的StringBuilder中添加一个负号
answer.append("-");

answer.append("0x");//十六进制以0x开头

d = Math.abs(d);//将传入的值进行绝对值转换要是负数的话就变成整数,整数不变

if(d == 0.0) {
answer.append("0.0p0");//如果传入的值为0.0直接返回0x0.0p0
} else { //传进来的值不为0.0
boolean subnormal = (d < DoubleConsts.MIN_NORMAL);//设置一个布尔变量 判断是否小于DoubleConsts最小值

long signifBits = (Double.doubleToLongBits(d)
& DoubleConsts.SIGNIF_BIT_MASK) |
0x1000000000000000L;
answer.append(subnormal ? "0." : "1.");
/*隔离低位十六进制的13位数字*/
String signif = Long.toHexString(signifBits).substring(3,16);
answer.append(signif.equals("0000000000000") ? // 13 zeros
"0":
signif.replaceFirst("0{1,12}$", ""));

answer.append('p');

answer.append(subnormal ?
DoubleConsts.MIN_EXPONENT:
Math.getExponent(d));
}
return answer.toString();
}
}

在这toHexString的函数中我们根据传进来的double值进行判断,通过StringBuilder来存取每次的转换的十六进制,由于博主实力有限,进制转换那段查了很多资料也弄的不是很懂,以后懂了,回来及时补坑

接下来我们就开始讲解一下ValueOf() 这个方法
同样Double的ValueOf也进行了传入不同类型的参数的函数重载
根据函数名字我们也能知道他的功能了,就是进行将传进去的值转换成一个Double实例,下面我们来看代码

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

很显然这个两个重载的函数,传入一个字符串类型的数字就会将这个字符串转换成Double并且返回一个新的实例,而传入一个double值,就是直接返回一个实例
下面讲解四个判断double的方法

    public static boolean isNaN(double v) {
return (v != v); //如果此值是一个非数字 (NaN) 值,则返回 true,否则返回 false。
}
public static boolean isInfinite(double v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);//如果此对象表示的值是正无穷大或负无穷大,则返回 true;否则返回 false。
}

public static boolean isFinite(double d) {
return Math.abs(d) <= DoubleConsts.MAX_VALUE; //判断是否超出范围
}

public static boolean isInfinite(double v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);//传入的这个double的值是无限大的幅度,则返回true,否则返回false
}

由于这四个方法逻辑都很简单我就不废话了

下面则是进行强制转换的方法了

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

这几个方法的逻辑也很简单就不一一说了下面请看Double的hashCode方法

  public int hashCode() {
return Double.hashCode(value);//传入double值
}
public static int hashCode(double value) {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));//对返回的16进制进行超级右移32位
}
/*doubleToLongBits方法根据 IEEE 754 浮点双精度格式 ("double format") 位布局,返回指定浮点值的表示形式。*/
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这个方法
doubleToLongBits根据传进来的double类型的值如果参数是正无穷大,则结果为0x7ff0000000000000L;如果参数是负无穷大,则结果为0xfff0000000000000L;如果参数是 NaN,则结果为0x7ff8000000000000L。所以不管怎么样返回的都是一个long 类型的值
我们通过if判断 result经过调用后返回的是返回指定浮点值对-9223372036854775808L也就是DoubleContsts.EXP_BIT_MASK进行与运算并且判断传进来的值是否为0 满足条件则将rsult赋值为0x7ff8000000000000L也就是 1<<62到1<<63之间然后将它返回

接下来就可以讲解compare方法

    public static int compare(double d1, double d2) {
if (d1 < d2) //d1小于d2 返回-1
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2) //d1大于d2 返回 1
return 1; // Neither val is NaN, thisVal is larger

// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1); //通过doubleToLongBits方法获取到d1与d2转换为IEEE 754 浮点双精度格式("double format") 位布局的形式。

long anotherBits = Double.doubleToLongBits(d2);

/*如果连个值相等的话就判断他们的bits,返回结果跟上面一样*/
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)
}

好了源码就讲到这里了,还剩下一些不是很重要的运算函数我就不写出来了