执行to.charAt()遇索引越界-1,为何误解s.charAt()返回-1?
Java字符串转换时的索引越界错误分析
原代码
public class Main { public static void main(String[] args) { System.out.println(tr("November 2016","abcdefghijklmnopqrstuvwyz","ABCDEFGHIJKLMNOPQRSTUVWYZ")); } public static String tr(String s, String from, String to){ StringBuilder sb = new StringBuilder(); for(int i = 0; i < s.length(); i++){ if (from.contains(s.substring(i, i + 1)) || to.contains(s.substring(i, i + 1))){ sb.append(to.charAt(to.indexOf(s.charAt(i)))); }else { sb.append(s.charAt(i)); } } return sb.toString(); } }
问题现象
执行sb.append(to.charAt(to.indexOf(s.charAt(i))));时触发**索引越界:-1(数组长度为25)**错误,疑惑为什么s.charAt(i)会返回-1(预期返回1)。
错误根源
首先纠正:s.charAt(i)不会返回-1,它返回的是字符对应的Unicode码点(比如'o'返回111)。真正的问题是to.indexOf(s.charAt(i))返回了-1,调用charAt(-1)才触发索引越界。
举个具体例子:当遍历到"November"里的小写'o'时,from.contains("o")结果为true,进入分支逻辑。但to字符串里只有大写字母,to.indexOf('o')找不到对应字符,返回-1,此时to.charAt(-1)直接触发索引越界异常。
另外你的from和to字符串都遗漏了字母x/X,这是潜在问题,不过本次报错并非由此导致。
修复方案
核心逻辑错误是:应该先找到字符在from中的索引,再用该索引去to中取对应字符,而不是直接在to中查找原字符(大小写不匹配必然找不到)。修复后的代码如下:
public class Main { public static void main(String[] args) { // 补全from和to中的x/X,避免遗漏字符 System.out.println(tr("November 2016","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ")); } public static String tr(String s, String from, String to){ StringBuilder sb = new StringBuilder(); for(int i = 0; i < s.length(); i++){ char currentChar = s.charAt(i); int fromIndex = from.indexOf(currentChar); int toIndex = to.indexOf(currentChar); if (fromIndex != -1) { // 字符在from中,取to对应索引的字符完成转换 sb.append(to.charAt(fromIndex)); } else if (toIndex != -1) { // 字符在to中,可根据需求转成from对应字符(比如大写转小写) sb.append(from.charAt(toIndex)); } else { // 字符不在from/to中,直接保留 sb.append(currentChar); } } return sb.toString(); } }
修复点说明
- 先获取字符在
from和to中的索引,避免重复调用substring和contains,提升代码效率。 - 当字符在
from中时,用from的索引匹配to的对应位置,解决大小写不匹配导致的查找失败问题。 - 补全
from和to中的x/X,消除潜在的字符遗漏问题。 - 拆分分支逻辑,明确处理不同场景,代码可读性更强。
内容的提问来源于stack exchange,提问作者Shulhin Denys
相关产品推荐
相关产品推荐

