美文网首页
Integer源码分析——下(jdk11)

Integer源码分析——下(jdk11)

作者: alexwu59 | 来源:发表于2019-12-30 16:51 被阅读0次

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常用的方法的实现原理就分析到这里,谢谢!

相关文章

  • Integer源码分析——下(jdk11)

    Integer与原生类型转换 Integer提供了几个与原生类型转换的方法: 由上面的源码可知,Integer类型...

  • java.lang.Integer#parseInt() 源码分

    java.lang.Integer#parseInt() 源码分析 Integer#parseInt() 是我们经...

  • 享元模式源码分析

    JDK源码分析 Integer Integer的缓存默认范围是:-128~127 Integer可设置最大值:12...

  • Integer源码分析

    title: Integer源码分析date: 2017-09-11 15:07:46tags: javacate...

  • Integer源码分析

    Integer 类的常量 MIN_VALUE : -231 , int 类型能够表示的最小值 MAX_VALUE ...

  • Integer源码分析

    toString() 1、如果Integer的value值正好是 Integer.MIN_VALUE 直接返回 “...

  • Integer源码分析

    Integer Integer是int的包装类而int是一种基本数据类型。 Integer是面向对象的,所以必须实...

  • JDK源码分析 Integer

    说明 对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我...

  • java Integer 源码分析

    Interger是int的包装类型,实现了Number接口,具有可比较和可序列化特性: Integer可以表示的范...

  • 2018-04-24常用类

    常用类_包装类_Integer_Number_JDK源码分析 把一个数zuoweiobject处理

网友评论

      本文标题:Integer源码分析——下(jdk11)

      本文链接:https://www.haomeiwen.com/subject/lsbdoctx.html