Java源码分析(二)Double

本篇是源码分析的第二篇,上篇我们一起分析了Integer类的源码,本篇一起学习下Double类的源码,看下其实现。

一、Double类图

首先,相比Integer,Double类的源码只有1000+行代码。如下是Integer及其关联类/接口的类图:

通过Integer类的类图,我们总结下它的特点:

  • Double类继承自抽象类Number
  • Double类实现了Comparable接口
  • Double类使用final修饰,因此不可以有子类(不能被继承)

二、String转Double

同Integer类似,在实际工作中,我们用的比较多的,仍然是String转Double。Java也是给我们提供了两个方法:

1、Double.parseDouble

java 复制代码
    public static double parseDouble(String s) throws NumberFormatException {
        return FloatingDecimal.parseDouble(s);
    }

可以看到,parseDouble并非在Double类中实现的,而是借助FloatingDecimal类去实现:

java 复制代码
    public static double parseDouble(String s) throws NumberFormatException {
        return readJavaFormatString(s).doubleValue();
    }

readJavaFormatString方法返回ASCIIToBinaryConverter:

java 复制代码
static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {...}

而ASCIIToBinaryConverter接口有两个方法,分别是doubleValue()和floatValue(),显而易见,分别是转double和转float的方法:

java 复制代码
   interface ASCIIToBinaryConverter {

        double doubleValue();

        float floatValue();

    }

2、Double.valueOf

另一种方法是Double.valueOf,需要注意的是,valueOf每次都是new一个Double,也就是一个新的对象。

java 复制代码
    public static Double valueOf(String s) throws NumberFormatException {
        return new Double(parseDouble(s));
    }

为什么Double不像Integer搞个缓存呢?浮点数不像整型,比如1和2之间就有无数个浮点数,那么又如何去实现类似IntegerCache的缓存呢?显然是不现实的!

三、isNaN

需要注意的一点,Double内部定义了一个非法的double值,即NaN:

java 复制代码
    /**
     * A constant holding a Not-a-Number (NaN) value of type
     * {@code double}. It is equivalent to the value returned by
     * {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
     */
    public static final double NaN = 0.0d / 0.0;

相应的,在很多情况下,确实会产生NaN的double值,因此在使用一个double值做一些运算时,记得使用Double.isNaN去判断下该非法值并做相应的异常处理:

java 复制代码
    /**
     * Returns {@code true} if the specified number is a
     * Not-a-Number (NaN) value, {@code false} otherwise.
     *
     * @param   v   the value to be tested.
     * @return  {@code true} if the value of the argument is NaN;
     *          {@code false} otherwise.
     */
    public static boolean isNaN(double v) {
        return (v != v);
    }

如下代码示例:

java 复制代码
    public static void main(String[] args) {
        String s = "NaN";
        double d = 0d;
        try {
            d = Double.parseDouble(s);
        } catch (NumberFormatException e) {
            System.out.println(e.getMessage());
            return;
        }
        if (Double.isNaN(d)) {
            System.out.println(d);
            return;
        }
        d = d * 2.0d;
        System.out.println(d);
    }

四、一道题目

那么,看下这道题目输出是什么呢?

java 复制代码
public class DoubleTest {
    public static void main(String[] args) {
        Double d1 = 100d;
        Double d2 = 100d;
        System.out.println(d1 == d2);
    }
}

答案是false。原因则是上面提到的,valueOf每次都是new一个Double对象。

相比Integer的源码,Double源码相对简单一些。但是需要特别注意使用double时isNaN的判断,否则程序可能产生意想不到的错误。

相关推荐
长河12 分钟前
Java开发者LLM实战——LangChain4j最新版教学知识库实战
java·开发语言
Cyan_RA922 分钟前
SpringMVC @RequestMapping的使用演示和细节 详解
java·开发语言·后端·spring·mvc·ssm·springmvc
喵手2 小时前
玩转Java网络编程:基于Socket的服务器和客户端开发!
java·服务器·网络
再见晴天*_*3 小时前
SpringBoot 中单独一个类中运行main方法报错:找不到或无法加载主类
java·开发语言·intellij idea
hdsoft_huge7 小时前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
雨白7 小时前
Java 多线程指南:从基础用法到线程安全
android·java
Hungry_Shark7 小时前
IDEA版本控制管理之使用Gitee
java·gitee·intellij-idea
赛姐在努力.7 小时前
《IDEA 突然“三无”?三秒找回消失的绿色启动键、主菜单和项目树!》
java·intellij-idea
猎板PCB黄浩8 小时前
从废料到碳减排:猎板 PCB 埋容埋阻的绿色制造革命,如何实现环保与性能双赢
java·服务器·制造
ZzzK,8 小时前
JAVA虚拟机(JVM)
java·linux·jvm