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;
}
注意这里进行了两步转换:
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常用的方法的实现原理就分析到这里,谢谢!