substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们的差异有助于更好的使用它们。为了简单起见,下面所说的substring()指的 就是substring(int beginIndex, int endIndex)方法。
1.substring()是做什么的?
substring(int beginIndex ,int endIndex)方法返回一个子字符串,返回的是从原字符串的beginIndex到endIndex-1之间的内容。
String x = "abcdef"; x = x.substring(1,3); System.out.println(x);
输出:bc
2.当substring()被调用的时候,内部发生什么事?
你或许会认为由于x是不可变的对象,当x被x.substring(1,3)返回的结果赋值后,它将指向一个全新的字符串如下图:
然而,这个图并不完全正确,或者说并没有完全表示出java 堆中真正发生的事情。那么当调用substring()的时候到底发生的了什么事呢?JDK 6与JDK7的substring方法实现有什么不一样呢?
3. JDK6中的substring();
java中字符串是通过字符数组来支持实现的,在JDK6中,String类包含3个域,char[] value、int offset、int count。分别用于存储真实的字符数组、数组的偏移量,以及String所包含的字符的个数。
当substring()方法被调用的时候,它会创建一个新的字符串对象,但是这个字符串的值在java 堆中仍然指向的是同一个数组,这两个字符串的不同在于他们的count和offset的值。
下面是jdk6中的原代码,是简化后只包含用来说明这个问题的关键代码:
//JDK 6 String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; } public String substring(int beginIndex, int endIndex) { //check boundary return new String(offset + beginIndex, endIndex - beginIndex, value); }
4.jdk6中substring()将会导致的问题;
如果你有一个非常长的字符串,但是你仅仅只需要这个字符串的一小部分,这就会导致性能问题(译注:可能会造成内存泄露,这个bug很早以前就有提及),因为你需要的只是很小的部分,而这个子字符串却要包含整个字符数组,在jdk6中解决办法就是使用下面的方法,它会指向一个真正的子字符串。
x = x.substring(x, y) + ""
5.JDK7中的substring();
在JDK7中有所改进,substring()方法在堆中真正的创建了一个新的数组,当原字符数组没有被引用后就被GC回收了.因此避免了上述问题.
//JDK 7 public String(char value[], int offset, int count) { //check boundary this.value = Arrays.copyOfRange(value, offset, offset + count); } public String substring(int beginIndex, int endIndex) { //check boundary int subLen = endIndex - beginIndex; return new String(value, beginIndex, subLen); }
译注: 在最新的Oralce JDK 6u45中,substring的实现方式已经改进了,不过我查到openjdk的6-b14就是原来的实现方式,有兴趣的可以查查具体是哪个版改进的.
相关推荐
JDK6引入了全面的反射API,位于`java.lang.reflect`包下,它允许程序在运行时检查类、接口、字段和方法的信息,甚至动态调用方法和创建对象。同时,注解(Annotation)作为一种元数据,可以用于编译时或运行时进行...
而在JDK7中,实现了自动关闭资源的机制,只要资源实现了`java.lang.AutoCloseable`接口,就可以在try块中直接声明并使用,程序结束时会自动调用`close()`方法。 其次,多线程处理方面,JDK7引入了Fork/Join框架,它...
1. **多重异常捕获**:在Java 7中,你可以使用一个"catch"子句来捕获多个不同类型的异常,这样代码更简洁且易于维护。 2. **钻石操作符**:在创建泛型对象时,可以省略类型参数的显式指定,如`new ArrayList()`。...
这个版本在当时代表着Java编程语言的最新发展,尽管现在Oracle已经停止了对JDK 7的官方支持,但它仍然是许多开发者和企业中的常用版本,特别是那些仍然依赖于Java 7特性和兼容性的项目。 **Java 7的主要特性:** 1...
在JDK的不同版本中,`String`类经历了一些优化和改进,尤其是在性能和内存管理方面。这里我们将对JDK 1.6、1.7和1.8中的`String`类进行对比研究,探讨其中的关键变化。 ### JDK 1.6中的String 在JDK 1.6中,`...
3. **改进的字符串操作**:包括`switch`语句对字符串的支持,以及`String`类中新增的一些实用方法,如`join()`、`split()`和`substring()`的改进。 4. **文件系统API(NIO.2)**:Java 7引入了新的文件系统API,...
这份文档是Java程序员日常开发的重要参考资料,它包含了JDK6中的所有核心类库、接口、方法以及异常等详细信息。以下是基于该手册的一些关键知识点的概述: 1. **基础类和接口**: - `Object`类:所有Java类的基类...
9. **泛型**:JDK 6引入了泛型,增强了类型安全,允许在定义类、接口和方法时指定类型参数,如`List<String>`,减少了类型转换的错误。 10. **枚举类型**:JDK 6新增的枚举类型(`enum`)是一种特殊的类,用于定义...
在Java 6及更早版本中,你需要明确指定类型参数,如 `new ArrayList()`,但在Java 7中,你可以写成 `new ArrayList()`。 增强的for循环(也称为foreach循环)在Java 7中得到了扩展,可以用于遍历数组和集合,包括...
Java API(Application Programming Interface)是Java语言提供的标准库,包含了大量预先定义好的类和方法,覆盖了网络、I/O、多线程、图形用户界面(GUI)、数据库连接等众多功能。例如,`java.io`包用于输入输出...
这对于理解和使用Java库中的类和方法至关重要。例如,当你需要操作字符串时,可以查看String类的API,找到所需的方法,如substring()、indexOf()等。 **总结** JDK 6 API文档是Java程序员的重要参考资料,它详尽地...
8. **示例代码**:许多类和方法都有示例代码,帮助开发者了解如何正确使用。 9. **变更记录**:对于JDK 9,文档会列出相对于前一版本的变化和新增特性,例如模块系统(Project Jigsaw)、改进的HTTP客户端(`java...
6. **改进的字符串操作** - 包括`switch`语句对字符串的支持,以及`String`类中新增的一些便捷方法,如`substring()`、`trim()`等。 7. **动态类型语言支持** - 通过JSR 292,Java 7引入了对动态语言的支持,允许在...
在JDK6中,字符串被表示为`String`类的实例,这意味着它具有类的方法和属性,而不是简单的字符数组。 字符串在Java中是不可变的,这意味着一旦创建了一个字符串对象,就不能改变它的内容。例如,当我们执行`text +=...
这些只是JDK1.6中文开发API中一部分关键特性,通过这份文档,开发者可以深入了解每个类和方法的功能、用法和注意事项,从而编写出更高效、更可靠的Java程序。无论是初学者还是经验丰富的开发者,都应该熟练掌握这些...
Java的多线程模型在JDK 6中得到进一步完善,线程的创建、同步和通信有了更多的控制选项,如synchronized关键字、wait()和notify()方法。 八、Swing和AWT 作为Java的图形用户界面库,Swing和AWT在JDK 6中提供丰富的...
2. **类型推断**:在Java 7中,引入了`钻石操作符`(`<>`),使得在创建泛型实例时,编译器可以自动推断类型参数,减少了代码的冗余。 3. **字符串切片**:可以通过`substring()`方法的两个参数快速获取子字符串,而...
5. **泛型:**泛型用于创建可以处理多种数据类型的类、接口和方法。 6. **IO与NIO:**标准输入/输出流、文件操作、缓冲区、通道、选择器等,以及NIO(New IO)的非阻塞I/O特性。 7. **反射API:**允许在运行时检查...
6. **字符串切片**:Java 11提供了字符串的切片功能,可以通过`.substring()`方法的两个参数来获取子字符串的起始和结束索引。 7. **改进的JShell(REPL)**:Java 11对Java Shell(也称为jshell)进行了增强,使其...