Fighting

分寸 , 克制

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

前言

今天要分析的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)
    }

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

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33048603/article/details/52335577
个人分类: J2se源码剖析
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

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

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭