引言
之前朋友让我本地计算一个值的方法给他,然后我就把我的Android代码给他了,然后他在idea上直接跑了那段Java代码,然后计算的结果一直和App上计算的不匹配。一直觉得同样都是Java怎么可能会跑出不一样的结果,所以以为是参数的问题过了好久通过断点发现问题出现在一句
1 | String.split("") |
idea 上运行
执行代码
1 | String testStr = "1234567"; |
执行结果
1 | split_res: 1 |
成功的将”1234567”分割成了[“1”, “2”, “3”, “4”, “5”, “6”, “7”]
Android 上运行
执行代码
1 | String testStr = "1234567"; |
注意,如果使用Log输出的话,在msg参数加上一个默认的字符串,Log在msg为””的时候是不会输出内容的。
Log的输出代码
1 | Log.v("TAG", "res" + str); |
执行结果
1 | System.out: split_res: |
“1234567”分割成了[“”, “1”, “2”, “3”, “4”, “5”, “6”, “7”]
可以看到和idea上不一样的是Android上的执行结果多了一个 “” 空字符串
分析
本地JDK 环境为1.8, 两边代码相同,不同的地方的就是IDE不同,然后一个用的Android SDK一个用的JDK。
Android -> android-28\java\lang\String.java
Idea -> jdk1.8.0_144\src.zip!\java\lang\String.java
本来想着都是java开发的String.split还能不一样,结果一看源码,呵呵哒。
代码
下面是相关的核心代码
两边split(“”)本质都是跳转到split的一个重载方法
1 | public String[] split(String regex) { |
从这个重载方法开始两边就开始不一样的。不过的是,我们的regex = “”的条件,这个俩方法最终都只进了最后的
1 | Pattern.compile(regex).split(this, limit); |
Android端的代码
1 | public String[] split(String regex, int limit) { |
Java端的代码
1 | public String[] split(String regex, int limit) { |
Pattern中的split,对比了两边的代码发现JDK1.8里面多了一个判断条件
1 | public String[] split(CharSequence input, int limit) { |
核心区分逻辑
1 | // 就是这个判断Android SDK里面是没有的。 就是因为这个判断。 |
这里把首位的””给过滤了, 而Android_SDK中是没有这段逻辑的所以就导致了Android中执行split(“”)会多出一个””了
2019-10-12 更新
今天刚好有后台的同学要算一个东西直接把线上的代码考下来的,然后发现怎么执行结果都不一样,后来发现和我之前用的是同一个类,所以问题也就同样处在了split(“”)这个的问题上。但是线上是正常的很奇怪,后来发现线上的服务器的JDK环境是1.7的,又去翻了一下1.7的String.split方法发现最终的Pattern.split和Android一样的没有index==0的逻辑的。