String.subString引发的StringIndexOutOfBoundsException

首先看两个例子,通过subString方法获得字符串t,再通过t.charAt(3)方法获得字符串t的值中的第四个字符。其中会利用反射机制,改变字符串s的值。

例子1:

public class Test {
    public static void main(String[] args) throws Exception {
        String s="0123456789";
        String t = s.substring(1); // 注意看这里
        System.out.println("t.charAt(3)为" + t.charAt(3));
        Field f = s.getClass().getDeclaredField("value");
        f.setAccessible(true);
        f.set(s, new char[]{‘a‘,‘b‘,‘c‘});
        System.out.println("t.charAt(3)为" + t.charAt(3));
    }
}

例子1 结果:

t.charAt(3)为4
t.charAt(3)为4

例子2:

public class Test {
    public static void main(String[] args) throws Exception {
        String s="0123456789";
        String t = s.substring(0);  //注意看这里
        System.out.println("t.charAt(3)为" + t.charAt(3));
        Field f = s.getClass().getDeclaredField("value");
        f.setAccessible(true);
        f.set(s, new char[]{‘a‘,‘b‘,‘c‘});
        System.out.println("t.charAt(3)为" + t.charAt(3));
    }
}

例子2 结果:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3
    at java.lang.String.charAt(String.java:658)
    at com.elong.mobile.guide.Test.main(Test.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

分析原因

首先看一下java doc中对public String substring(int beginIndex)方法的说明

Returns a new string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string.

文档中说明subString方法会返回一个新的String对象,但上面两个例子中,只有beginIndex值不同,结果确不同,例1能正常运行,例2却抛出了StringIndexOutOfBoundsException异常。我们再看一下String当中subString方法的源码,一探究竟。

public String substring(int beginIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

注意最后一行,原因就出现在这里,当beginIndex等于0时,Java会返回当前对象的引用,不会创建新的String对象,当我们通过反射改变字符串s的值时,再通过t.charAt方法获取值的时候,就可能会抛出StringIndexOutOfBoundsException异常。

(完)

时间: 2024-10-06 20:26:56

String.subString引发的StringIndexOutOfBoundsException的相关文章

Android和Java中String.substring的不同实现

今天有幸去搜狗霸笔,有一题很有意思 String str1 = "test for sougou"; String str2 = str1.substring(5); 考点是str2是否生成新的字符数组来保存"for sougou" 当时我认为String内部是封装了一个char[],无法像cpp一样首地址加上一个数字来做到char[]的重用 新的字符串必须进行一次ArrayCopy才能实现substring功能,所以肯定有新的内存生成 回来看了下实现 因为andr

JavaSE8基础 String substring 返回字符串中指定索引值区间内的字符

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0)        code: package jizuiku.t00; public class Demo5 { public static void main(String[] args) { //索引值 012345 String str = "abc01234543210cba"; int beginIndex = 2

String.split引发的“内存泄露”

一直赞叹Sun对待技术的严谨和优雅(bless Sun).Sun JDK中Java库的源代码,连注释都清清楚楚.规规范范,javadoc注解的使用也一丝不苟,读起来很熟舒服.因此,在日常工作和学习中,经常读读 Java库的源代码,不亦乐乎?如果遇到诡异问题,源代码的帮助就更大了. 闲话少说,回归正题.这几天,一直在为Java的“内存泄露”问题纠结.Java应用程序占用的内存在不断的.有规律的上涨,最终超过了监控阈值. 福尔摩斯不得不出手了! 说起Java的内存泄露,其实定义不是那么明确.首先,如

Java String.substring内存泄露?

String可以说是最常用的Java类型之一了,但是最近听说JDK6里面String.substring存在内存泄露的bug,伙惊呆!一起来看看到底是啥情况吧. 这个是可以导致Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 的代码: public class TestGC {     private String largeString = new String(new byte[100000

String.IndexOf String.IndexOf String.Substring

String.IndexOf String.IndexOf 方法 (Char, Int32, Int32)报告指定字符在此实例中的第一个匹配项的索引.搜索从指定字符位置开始,并检查指定数量的字符位置.String.IndexOf(value, startIndex, count) 参数value:要查找的 Unicode 字符. startIndex:搜索起始位置. count:要检查的字符位置数.返回值(Int32):如果找到该字符,则为 value 的索引位置:否则如果未找到,则为 -1.

[string]Substring with Concatenation of All Words

Total Accepted: 45534 Total Submissions: 226763 Difficulty: Hard You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexact

String subString方法

package 字符串2; public class TestString { public static void main(String[] args) {   String str = "Returns a new character sequence that is a subsequence of this sequence";      int count = 0;   int index = 0;   String strTofind = "sequence&q

String.subString的用法

在做项目的时候,碰到一个过滤字符串的问题,因为一直无法正常的描述完整这个字符串的信息,所以想到截取部分差异化的字符来解决这个问题 String,substrinf(start,end); 这个函数的使用的时候,可以很方便的截取到你想的的部分字符串 再结合String.equals();来做一个比较,就可以很轻松的过滤掉含有这类字符串的信息了 例如: String text = "MobileTV Not testl...dsada"; if(text.substring(0,3).eq

Java中由substring方法引发的内存泄漏

在Java中我们无须关心内存的释放,JVM提供了内存管理机制,有垃圾回收器帮助回收不需要的对象.但实际中一些不当的使用仍然会导致一系列的内存问题,常见的就是内存泄漏和内存溢出 内存溢出(out of memory ):通俗的说就是内存不够用了,比如在一个无限循环中不断创建一个大的对象,很快就会引发内存溢出. 内存泄漏(leak of memory):是指为一个对象分配内存之后,在对象已经不在使用时未及时的释放,导致一直占据内存单元,使实际可用内存减少,就好像内存泄漏了一样. 由substring