首页 > 编程语言 >【JAVA】探讨 Java 中 valueOf 和 parseInt 的区别

【JAVA】探讨 Java 中 valueOf 和 parseInt 的区别

时间:2022-09-28 16:39:42浏览次数:49  
标签:radix Java int valueOf NumberFormatException result parseInt Integer

前言 在编程中,遇到类型转换,好像会经常用到 parseInt 和 valueOf,当然这里只拿 Integer 类型进行陈述,其他类型也是雷同的; 想必有读者也跟我一样,经常交叉使用这两个方法,但却不知道这两者到底有什么区别,接下来就来探究一番;   区别

Integer.parseInt(s) 的作用就是把字符串 s 解析成有符号基本类型的 int; Integer.valueOf(s) 把字符串 s 解析成 Integer 对象类型,返回的对象可以调用 Integer 中的方法;

接下来,通过源码进行逐一解析;  ``` parseInt 我们首先点进 parseInt() 方法中, public static int parseInt(String s) throws NumberFormatException { return parseInt(s, 10); }

可以看到,这个被我们调用的 parseInt() 方法返回了一个重载方法:

public static int parseInt(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } else if (radix < 2) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } else if (radix > 36) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } else { boolean negative = false; int i = 0; int len = s.length(); int limit = -2147483647; if (len <= 0) { throw NumberFormatException.forInputString(s); } else { char firstChar = s.charAt(0); if (firstChar < '0') { if (firstChar == '-') { negative = true; limit = -2147483648; } else if (firstChar != '+') { throw NumberFormatException.forInputString(s); }

            if (len == 1) {
throw NumberFormatException.forInputString(s);
}

++i;
}

int multmin = limit / radix;

int result;
int digit;
for(result = 0; i < len; result -= digit) {
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0 || result < multmin) {
throw NumberFormatException.forInputString(s);
}

result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
}

return negative ? result : -result;
}
}

}

1、首先看到的是,该方法传入了两个参数,parseInt(String s, int radix),这个可以根据被调用时传入的参数,return parseInt(s, 10);,盲猜一下,s 就是表示要转换成数字型的字符串,而 radix 英文是基数的意思,这里应该表示进制,即这个传入的字符串是多少进制的,那到底是不是呢,我们接着往下看;
2、这里先是对字符串 s 是否为空,以及 radix 的大小进行一个判断,不符合条件则抛出 NumberFormatException 异常,也就是数字格式化异常;

if (s == null){ throw new NumberFormatException("null"); } else if (radix < 2) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } else if (radix > 36) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } else { 复制代码 3、接着往下,再一次对长度进行一个校验, int len = s.length(); if (len <= 0) { throw NumberFormatException.forInputString(s); } else { ... }

我在这里只想到了一个能让它抛出异常的条件,

Integer.parseInt("");

运行结果:

Exception in thread "main" java.lang.NumberFormatException: For input string: "" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.base/java.lang.Integer.parseInt(Integer.java:662) at java.base/java.lang.Integer.parseInt(Integer.java:770)

4、接下来会检测第一个字符是啥,如果是 -,则将 negative 设置成 true,表示这是个负数,并且将边界 limit 设置成最小边界;
如果不是 +,则表示该字符既不是数字,不也是性质符号,因此抛出 NumberFormatException 异常;
如果字符串 s 的长度只有1,则表明这是非数字,不符合要求,也抛出 NumberFormatException 异常;
++i 是因为如果第一位是符号的话,那么在后续的循环中追加数字则直接跳过首位;

char firstChar = s.charAt(0); if (firstChar < '0') { if (firstChar == '-') { negative = true; limit = -2147483648; } else if (firstChar != '+') { throw NumberFormatException.forInputString(s); }

 if (len == 1) {
throw NumberFormatException.forInputString(s);
}

++i;

}

5、根据进制来调整边界,以防越界;

int multmin = limit / radix;

6、Character.digit() 用于将字符转为为对应进制的整数,如果该字符不是进制内的就返回-1,例如输入的字符是9,但是进制是2,那么就不符合,则会返回-1;
然后就是进行计算;

int result; int digit; for(result = 0; i < len; result -= digit) { digit = Character.digit(s.charAt(i++), radix); if (digit < 0 || result < multmin) { throw NumberFormatException.forInputString(s); }

result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}

}

7、最后判断是否为负数完成转换;

return negative ? result : -result;

 
valueOf
照例查看源码:

public static Integer valueOf(String s, int radix) throws NumberFormatException { return parseInt(s, radix); }

public static Integer valueOf(String s) throws NumberFormatException { return parseInt(s, 10); }

@HotSpotIntrinsicCandidate public static Integer valueOf(int i) { return i >= -128 && i <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[i + 128] : new Integer(i); }

可以看出 valueOf(String s, int radix) 和 valueOf(String s) 都是直接调用返回了 parseInt 方法,而 valueOf(int i) 则是一个 int 转成 Integer 的自动装箱;
接下来探究一下 IntegerCache ,可以看出这是 Integer 的成员内部类,来看源码:

private static class IntegerCache { static final int low = -128; static final int high; static final Integer[] cache; static Integer[] archivedCache;

private IntegerCache() {
}

static {
int h = 127;
String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
int size;
if (integerCacheHighPropValue != null) {
try {
size = Integer.parseInt(integerCacheHighPropValue);
size = Math.max(size, 127);
h = Math.min(size, 2147483518);
} catch (NumberFormatException var6) {
}
}

high = h;
VM.initializeFromArchive(Integer.IntegerCache.class);
size = high - -128 + 1;
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = -128;

for(int k = 0; k < c.length; ++k) {
c[k] = new Integer(j++);
}

archivedCache = c;
}

cache = archivedCache;

assert high >= 127;

}

}

整体就是初始化一个 IntegerCache.cache 数组,数组里面存储-128到127之间的数字当做是缓存,源码一开始是分析数组长度,然后给数组赋值;
总的来说,三个重构的 valueOf() 方法还是大同小异的:

Integer valueOf(int i):返回一个表示指定的 int 值的 Integer 实例;
Integer valueOf(String s):返回保存指定的 String 的值的 Integer 对象;
Integer valueOf(String s, int radix):返回一个 Integer 对象,该对象中保存了用第二个参数提供的基数进行解析时从指定的 String 中提取的值;


后记
看源码还是能学到很多东西的,源码自有黄金屋,多看多学,夯实基础,之后会轻松高效很多!

标签:radix,Java,int,valueOf,NumberFormatException,result,parseInt,Integer
From: https://blog.51cto.com/u_15773567/5715427

相关文章

  • Java基础(二)| 基础语法之运算输入与控制语句
    ⭐本专栏旨在对JAVA的基础语法及知识点进行全面且详细的讲解,完成从0到1的java学习,面向零基础及入门的学习者,通过专栏的学习可以熟练掌握JAVA编程,同时为后续的框架学习,进阶开......
  • javaweb核心之页面技术
    2页面技术2.1JSP基础2.1.1JSP简介JSP全称是JavaServerPage,它和Servlet一样,也是sun公司推出的一套开发动态web资源的技术,称为JSP/Servlet规范。JSP的本质其实就是一......
  • JavaScript异步加载的三种方式——async、defer、动态创建
    async和deferhtml4.0中定义了defer;html5.0中定义了async。如果没有defer和async,浏览器会立即加载并执行指定的JS脚本,并不会等待后续载入的文档元素。如果有async,加载后......
  • 查找java位置
    方法一:whichjava此方法是无法定位到java的安装路径的,只能定位到执行路径。 方法二:echo$JAVA_HOME 使用echo$JAVA_HOME命令可以定位到java安装路径,但前......
  • java学习笔记31
    java面向对象回顾方法的定义修饰符返回类型packageoop;//类publicclassDemo01{  //main方法  publicstaticvoidmain(String[]args){     ......
  • java学习笔记30
    java面向对象什么是面向对象java的核心思想就是面向对象编程定义面向对象编程(oop)面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据抽象:把很多个共同点......
  • JAVA目录简单操作
    packageCreateFILES;importjava.io.File;importjava.io.IOException;publicclassDirectory{publicstaticvoidmain(String[]args){......
  • 力扣349(java&python)-两个数组的交集(简单)
    题目:给定两个数组 nums1 和 nums2,返回它们的交集 。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。 示例1:输入:nums1=[1,2,2,1],num......
  • Java新手如何训练基本功?
    1.Java基本功1.1.Java入门(基础概念与常识)1.2.Java语法1.3.基本数据类型1.4.方法(函数)这里给大家推荐一个适合Java小白必看的教学视频!如何自学Java?当你准备开始接......
  • Java入门基础知识
    概念关键字:具有特殊用途的单词。保留字:未使用的关键字(gotoconst)。直接量:不可用作标识符(turefalsenull)。一、JAVA运行机制Java程序的运行必须经过编写、编译、运......