专业编程基础技术教程

网站首页 > 基础教程 正文

Integer源码分析——下(jdk11)

ccvgpt 2024-08-06 12:36:00 基础教程 27 ℃



Integer源码分析——下(jdk11)

  • Integer与原生类型转换

Integer提供了几个与原生类型转换的方法:

public int intValue() {

        return value;

  }

    public long longValue() {

        return (long)value;

    }

    public float floatValue() {

        return (float)value;

    }

    public double doubleValue() {

        return (double)value;

    }

由上面的源码可知,Integer类型转换原生类型,只需要把value进行对应类型的强制转换即可,因为Integer中实际存储的值存储在value变量中。

  • Integer.getInteger(String nm)

getInteger是Integer的静态方法,参数nm是系统变量key,即从系统变量nm读取字符串,然后再转换为对应的Integer,此方法有3个重载方法:

public static Integer getInteger(String nm)
public static Integer getInteger(String nm, int val)
public static Integer getInteger(String nm, Integer val) 


这三个方法中,后面两个方法提供了一个默认值,当nm的系统变量为null,返回方法传入的默认值val

下面重点分析getInteger(String nm, Integer val)的实现逻辑,因为其他两个方法的实现,都是通过调用此方法来实现的:

public static Integer getInteger(String nm, Integer val) {

        String v = null;

        //获取系统变量nm的值

        try {

            v = System.getProperty(nm);

        } catch (IllegalArgumentException | NullPointerException e) {

        }

        //当v不为null的时候,调用Integer.decode(v)方法

        if (v != null) {

            try {

                return Integer.decode(v);

            } catch (NumberFormatException e) {

            }

        }

        //如果v==null,返回默认值

        return val;

}

程序中使用System.getProperty(nm);获取的系统变量,通常是程序,用户,jvm等相关信息,如果用户想要设置自定义的系统变量,通常可以在启动程序的时候,使用下面的方法:```

java -jar JarName -DpropertyName=value```

propertyName就是用户设置的系统变量的key

下面介绍一下Integer.decode(v)的实现原理

public static Integer decode(String nm) throws NumberFormatException {

        //表示进制 8, 10,16,默认是10

        int radix = 10;

        //字符串的当前位置

        int index = 0;

        boolean negative = false;

        Integer result;

        if (nm.length() == 0)

            throw new NumberFormatException("Zero length string");

        //获取nm的第一个字符,然后判断是正数还是负数

        char firstChar = nm.charAt(0);

        if (firstChar == '-') {

            negative = true;

            index++;

        } else if (firstChar == '+')

            index++;

        //然后获取除了符号位之后的数字字符串的开头几个字符,

        //来判断数字的进制形式

        if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {

            index += 2;

            radix = 16;

        }

        else if (nm.startsWith("#", index)) {

            index ++;

            radix = 16;

        }

        else if (nm.startsWith("0", index) && nm.length() > 1 + index) {

            index ++;

            radix = 8;

        }

        

        if (nm.startsWith("-", index) || nm.startsWith("+", index))

            throw new NumberFormatException("Sign character in wrong position");

        //对字符串经过上面步骤的校验,获取nm代表字符串的进制和数字字符串,

        //通过调用Integer.valueOf对nm进行真正的字符到数字的转换,

        //Integer.valueOf具体实现原理参考:[Integer源码分析——上 (jdk11)]

        try {

            result = Integer.valueOf(nm.substring(index), radix);

            result = negative ? Integer.valueOf(-result.intValue()) : result;

        } catch (NumberFormatException e) {

            String constant = negative ? ("-" + nm.substring(index))

                                       : nm.substring(index);

            result = Integer.valueOf(constant, radix);

        }

        return result;

}

Integer源码分析——上 (jdk11)


注意这里进行了两步转换:


result = Integer.valueOf(nm.substring(index), radix);

result = negative ? Integer.valueOf(-result.intValue()) : result;

由于nm.substring(index)是去掉了正负符号和进制类型,因此第一次调用valueOf得到的是正数。如果nm表示的负数,然后需要第二步进行一个正负转换。

这里注意的是当抛出NumberFormatException异常是,会执行下面两行代码:

String constant = negative ? ("-" + nm.substring(index)) : nm.substring(index);

result = Integer.valueOf(constant, radix);


这里的原理呢?

当nm="-2147483648",在执行Integer.valueOf(nm.substring(index), radix)的时候,nm.substring(index)的结果是"2147483648",由于int类型值得范围是:

-2147483648<=int<=2147483647

而因此在执行Integer.valueOf("2147483648", 10),会抛出异常NumberFormatException,因为"2147483648"在转换的时候出现了溢出,因此需要通过String constant = negative ? ("-" + "2147483648") : "2147483648"; 把"2147483648"转换为"-2147483648",然后再调用Integer.valueOf("-2147483648", radix);

这样的处理方法可以正确的解决"-2147483648"转为int的溢出问题。

Integer常用的方法的实现原理就分析到这里,下一阶段分析一下java常用集合的实现,目前已经发布了ArrayList和LinkedList,下面开始写HashMap,谢谢大家!

最近发表
标签列表