关闭

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

标签: java源码数据classj2se
1003人阅读 评论(0) 收藏 举报
分类:

前言

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

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

0
0
查看评论

java源码分析(10)- Double(1)

Double 在研究double前,必须先介绍下IEEE 754算数标准,Double和Float都遵循此标准。 Double遵循此标准中的64位浮点数表示方式。从左到右具体为: 1.第一位为符号部,0表示正,1表示负 2.2~12位为指数部,用以存放具体数值的指数 3.13~64位为...
  • qq_29346449
  • qq_29346449
  • 2016-06-14 17:19
  • 769

Float&Double源码

Float基本属性 Double基本属性
  • caimengyuan
  • caimengyuan
  • 2017-03-10 20:34
  • 140

再探java基础——throw与throws

再探java基础——throw与throws 以前虽然知道一些异常的处理,也用过一些,但是对throw和throws区别还是有不太清楚。今天用实例测试一下。 异常处理机制 异常处理是对可能出现的异常进行处理,以防止程序遇到异常时被卡死,处于一直等待,或死循环。 异常有两个过程,一个是抛出异常...
  • luoweifu
  • luoweifu
  • 2013-08-31 14:30
  • 72653

深入Java基础(一)——基本数据类型及其包装类

这一系列打算慢慢地去接触源码,并且列出相关的题目,对于完全的初学者的话,我到时候会搜一套我认为比较好的培训机构的视频以及给些社区资料和相关博客咯。让我们一起开始思考,深入学习Java吧。这篇文章就数据类型咯-文章结构:1. 基本数据类型的系统描述;2.数据类型的包装类理解(含源码解析);3.数据类型...
  • Jack__Frost
  • Jack__Frost
  • 2016-12-21 22:18
  • 6665

java核心基础--jdk源码分析学习--基本数据类型

java基本数据类型。四类八种—重点是【记住占几位】 逻辑类型 boolean (占几位不一定) 文本类型 char(16-bit)(unicode) 整数类型 byte(8-bit)、short(16-bit)、int(32-bit)、long(64-bit) 浮点类型 float(32-bi...
  • c5113620
  • c5113620
  • 2017-12-05 17:02
  • 10372

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

大家都知道int 是基本数据类型而Integer则是int的包装类,为什么要为基本数据类型提供包装类呢?这里我只说一个最基本的原因 “为了在各种类型间转化,通过各种方法的调用。否则 你无法直接通过变量转化”,这只是其一,其余的我就不一一赘述了,下面让我们来一下Integer的源码 publi...
  • qq_33048603
  • qq_33048603
  • 2016-08-19 20:31
  • 1685

JAVA中基本数据类型和封装类的区别Integer和Double为例

int 为基本类型,Integer是int对应的封装类,或称包装类,是对象。                int               &#...
  • fresh_coder2014
  • fresh_coder2014
  • 2016-03-14 10:57
  • 3486

JAVA基本数据类型范围和float、double精度问题

1.八中数据类型的分类如下:  第一类:整型 byte short int long 第二类:浮点型 float double 第三类:逻辑型 boolean(它只有两个值可取true false) 第四类:字符型 char 2.各种基本数据类型所占的字节: boolean 布尔型...
  • zc_ad
  • zc_ad
  • 2016-11-30 09:56
  • 2080

J2SE(三)Java基本数据类型

java的数据类型有两种: (1)内置数据类型 (2)引用数据类型
  • u012170724
  • u012170724
  • 2016-04-08 17:34
  • 166

OC基础:OC 基本数据类型与对象之间的转换方法

1.Foundation框架中提供了很多的集合类如:NSArray,NSMutableArray,NSSet,NSMutableSet,NSDictionary,NSMutableDictionary但是这些类只能存放OC对象类型的数据 2.如果要存放基本数据类型,必须先将基本暑假类型包装成对象...
  • shaoting19910730
  • shaoting19910730
  • 2015-06-18 20:01
  • 680
    个人资料
    • 访问:112186次
    • 积分:1387
    • 等级:
    • 排名:千里之外
    • 原创:41篇
    • 转载:3篇
    • 译文:0篇
    • 评论:32条
    博客专栏
    最新评论