JDK源码之Integer类——stringSize()方法

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK源码之Integer类——stringSize()方法相关的知识,希望对你有一定的参考价值。

注意,我所使用的JDK版本是1.8,但我发现1.9版本的这个stringSize()方法和1.8版本的stringSize()方法的源码不一样。

1.8版本的stringSize()方法源码及中文注释如下:

    final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
            99999999, 999999999, Integer.MAX_VALUE};

    /**
     * 统计传入整数的数字位数,比如123是3位数字,4568是4位数字
     *
     * @param x 正整数,但事实在该方法内并没有判断该数是否是一个正整数
     * @return 返回x的位数
     */
    static int stringSize(int x) {
        // i是临时变量,用来统计一个数的位数
        for (int i = 0; ; i++)
            // 判断传入的参数x是否小于等于sizeTable[i],则返回x的位数
            if (x <= sizeTable[i])
                return i + 1;// 因为索引是从0开始的,所以要加1
    }

该方法的功能是统计传入整数的数字位数,比如123是3位数字,4568是4位数字

但需要注意的是,该方法没有用public修饰,所以无法调用,如果要尝试该功能的话,看如下代码:

public class Test {
    final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
            99999999, 999999999, Integer.MAX_VALUE};

    /**
     * 统计传入整数的数字位数,比如123是3位数字,4568是4位数字
     *
     * @param x 正整数,但事实在该方法内并没有判断该数是否是一个正整数
     * @return 返回x的位数
     */
    static int stringSize(int x) {
        // i是临时变量,用来统计一个数的位数
        for (int i = 0; ; i++)
            // 判断传入的参数x是否小于等于sizeTable[i],则返回x的位数
            if (x <= sizeTable[i])
                return i + 1;// 因为索引是从0开始的,所以要加1
    }

    public static void main(String[] args) {
        // 输出数字123的位数
        System.out.println(stringSize(123));// 3
        // 输出数字123456的位数
        System.out.println(stringSize(123456));// 6

        // 但注意,传入的参数如果是负数,那么无论是几位都会返回1
        System.out.println(stringSize(-123));// 1
        System.out.println(stringSize(-654321));// 1
    }
}

我们从上面代码中知道如果传入的参数是负数的话则无效,那么在源码中是如何使用的呢?

在源码中有两处用到:

第一处:如果是正数则直接传入,如果是负数则转换成正数传入。

第二处:如果是正数则直接传入,如果是负数则转换成正数传入。

所以该方法一定会生效,因为传入的参数一定是正数,不需要进行校验。

1.9版本的stringSize()方法的源码发生了变化,如下:

    // Left here for compatibility reasons, see JDK-8143900.
    static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

    /**
     * Returns the string representation size for a given int value.
     *
     * @param x int value
     * @return string size
     *
     * @implNote There are other ways to compute this: e.g. binary search,
     * but values are biased heavily towards zero, and therefore linear search
     * wins. The iteration results are also routinely inlined in the generated
     * code after loop unrolling.
     */
    static int stringSize(int x) {
        int d = 1;
        if (x >= 0) {
            d = 0;
            x = -x;
        }
        int p = -10;
        for (int i = 1; i < 10; i++) {
            if (x > p)
                return i + d;
            p = 10 * p;
        }
        return 10 + d;
    }

中文注释下:

public class Test {
    // 出于兼容性原因,请留在此处,请参阅JDK-8143900。
    // 下面这个数组其实没有被用到过,但JDK1.9却留下了,因为JDK1.8及之前的版本会用到这个数组
    static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
            99999999, 999999999, Integer.MAX_VALUE};
    
    /**
     * 返回给定int值的字符串表示大小,即一个数字的位数,如数字123的位数是3位,数字4567的位数是4位
     *
     * @param x 给定的整数
     * @return 返回字符串大小,即位数
     */
    static int stringSize(int x) {
        // 局部变量,计数器
        int d = 1;// 如果是负数则d=1,如果是正数则d=0,为什么呢?因为负数会把符号位计算在内,如-123执行的结果是4
        // 判断给定的整数x是否是一个正数
        if (x >= 0) {
            // 并且将d重置为0
            d = 0;
            // 如果x是一个正数,则转换成一个负数
            x = -x;
        }

        // 局部变量,用于循环
        int p = -10;
        for (int i = 1; i < 10; i++) {// 为什么是i<10,因为int数据类型的范围最大为2147483647,即10位数字
            if (x > p)// 用于确定数字的位数
                return i + d;
            p = 10 * p;// 循环
        }
        return 10 + d;
    }

    public static void main(String[] args) {
        // 输出数字123的位数
        System.out.println(stringSize(2147483647));// 10
        // 输出数字123456的位数
        System.out.println(stringSize(123456));// 6

        // 但注意,传入的参数如果是负数,那么也会返回负数的位数,但是会包括符号位在内,例如-123返回4
        System.out.println(stringSize(-123));// 4
        System.out.println(stringSize(-654321));// 7
    }
}

看了上面的代码,我们可以引申出一个问题:如何求一个整数的位数?

以上是关于JDK源码之Integer类——stringSize()方法的主要内容,如果未能解决你的问题,请参考以下文章

JDK:java.lang.Integer源码解析

Jdk1.8 之 Integer类源码浅析

JDK源码之Integer类——rotateRight()方法

JDK源码之Integer类——rotateLeft()方法

JDK源码之Integer类——numberOfLeadingZeros()方法

JDK源码之Integer类——numberOfTrailingZeros()方法