前言
今天要分析的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)
}
好了源码就讲到这里了,还剩下一些不是很重要的运算函数我就不写出来了