`
chenchuangfeng
  • 浏览: 79992 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Java中字符串探索----String ,StringBuffer ,StringBuilder及字符串缓存池

    博客分类:
  • Java
阅读更多

 

      字符串是编程中应用到最多的一个数据类型,简单实用,但是深入理解它们,会给我们带来更多好处。

 

 

 

字符串缓存池:

 

    为了节省内存,提高资源的复用,java中引入了字符串缓存池的概念。

 

 

 

    缓存池中的字符串是不可回收的:

 

在缓存池中的字符串是不会被垃圾回收机制回收的,基本都是常驻内存,所以过多食用String类,可能会出现内存溢出(下面会讲)。

 

 

 

    怎么样才会存进缓存池:

 

  1. 直接量赋值创建对象
    在Java,基本包装类型String,Long,Float,Boolean.......都可以利用直接量创建对象。
    String用直接量进行创建对象的时候,会先在缓存池找到字符串相同的对象,然后指向缓存池中该对象,这样就避免了重新为该对象分配内存,从而提高了复用,所以建议多用直接量去创建对象,这个也是上篇博文所推荐的。
  2. 调用构造器创建对象
    这种方法调用构造器,凡是new出来的对象都要进行内存分配,所以是不会指向缓存池之前已有的对象,这样就导致缓存池里面可能有多个值相同的String对象。

 

  
package biaodashi;
/**
 * 字符串关于缓存池
 * 
 * @author ccf
 * 
 */
public class StringHuanCunChi {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        StringHuanCunChi huanCunChi = new StringHuanCunChi();
         huanCunChi.test1();
       }
    public void test1() {
        String str1 = "ccf";
        String str2 = "ccf";
        String str3 = new String("ccc"); // new 会有新的地址分配,所以不会指向缓存池的"ccc"
        String str4 = new String("ccc");
        System.out.println("str1==str2?" + (str1 == str2));
        System.out.println("str3==str4?" + (str3 == str4));
    }
   }


运行结果
str1==str2?true
str3==str4?false
 

结果:看出str1 和str2都是指向同一个对象   而str3和str4就不是同一个对象了。


  怎么样才能指向缓存池已有的对象:
    
    
要指向缓存池对象,改对象必须是直接赋直接量,也可以是多个直接量的运算值,而不能调用方法或者其他变量,但是被final修饰的可以进行宏替换的常量也可以看成直接赋值,因为以上这一些都能在加在类的时候,就被虚拟机计算出来其值。所以能指向缓存池。
public void test1() {
        String str1 = "ccf";
        String str2 = "c" + "c" + "f";//三个直接量进行运算
        System.out.println("str1==str2?" + (str1 == str2));
        
结果:str1==str2?true   多个直接量进行连接,也可以指向缓存池
 
    
上面的代码中 String str2 = "c" + "c" + "f";一共创建了几个对象?????
可能有人会说n个,但是其实只有一个,因为虚拟机对他们进行直接的计算,不需要创建对象,这也是使用直接量的好处。
public void test1() {
        String str1 = "ccf" + "长度为:" + "3";
        String str2 = "ccf" + "长度为:" + str1.length();
        System.out.println("str1==str2?" + (str1 == str2));
        // 

结果:  str1==str2?false 

结论:str2调用了方法str1.length(),故不能再虚拟机加在类的时候就计算确定str的值,所以打印结果如下


    }

public void test1() {
        final String length1 = "3";
        String length2 = "3";
        String str1 = "ccf" + "长度为:" + "3";
        String str2 = "ccf" + "长度为:" + length1;//调用final变量
        String str3 = "ccf" + "长度为:" + length2;//调用普通变量
        System.out.println("str1==str2?" + (str1 == str2));
        System.out.println("str1==str3?" + (str1 == str3));
    
结果:  
str1==str2?true
str1==str3?false  
可以得出结论:被final修饰的 length1效果是和直接量一样的,在虚拟机加在时候,length1是直接替换"3",之后就跟length1没关系了,效果可以说跟str1中一摸一样,这也是final变量和其他变量的不同之处,称为宏替换。
 
关于String的不可变问题:
String
} 类是个不可变的类,创建对象后,不可以改变对象,但是日常代码经常对String进行操作,这对于String不可变这一说法是不是相悖了?
 
看下这段代码:
public void testString() {
        String str1 = "Hello";
        int OldId = System.identityHashCode(str1);
        str1 = str1 + " ccf!";//对字符串进行操作
        int NewId = System.identityHashCode(str1);
        System.out.println("OldId=" + OldId + "\nNewId=" + NewId);
           } 

结果:
OldId=854453928
NewId=584020407 
其中System.identityHashCode(str1);函数是打印出对象的HashCode,每个对象都有一个唯一的HashCode
,是对象的唯一标识,很明显,前后两个HashCode是不同的,
 
    得出一些结论:对String对象进行操作后,其返回的是一个新的对象,之前那个对象是没有改变的,改变的是str这个引用所指的对象,这时候的对象已经是新的对象,然而之前那个对象被废弃了,但是他存在缓存池,因此不会被垃圾回收机制回收,所以这里会出现内存泄漏,所以操作字符串,尽量不用String。
 
但是StringBuffer和StringBuilder进行字符串操作的时候,就不会去new出现对象,引用的都是同一个对象,就可以减少String带来的弊端。
 
 
public void testStringBuilder() {
        StringBuilder builder = new StringBuilder("Hello");
        System.out.println("ID=" + System.identityHashCode(builder));
        builder.append(" ccf!");
        System.out.println("ID=" + System.identityHashCode(builder));
        System.out.println(builder);
       
    } 
结果:
ID=854453928
ID=854453928
Hello ccf!
 

 

4
2
分享到:
评论
3 楼 zsw2zkl 2014-03-13  
nice artical
2 楼 chenchuangfeng 2013-01-25  
hjj20040849 写道
“字符串是编程中用到最多的一个类”,严重错误!!!!字符串类型是编程中用到的最多的一个类型!!!

已经修正...谢谢鸡鸡的指正!
1 楼 hjj20040849 2013-01-25  
“字符串是编程中用到最多的一个类”,严重错误!!!!字符串类型是编程中用到的最多的一个类型!!!

相关推荐

    java 创建字符串缓存类

    总结一下,Java中创建字符串缓存类的主要目的是减少内存消耗和提高性能,特别是在频繁字符串操作的场景下。通过使用`StringBuffer`或`StringBuilder`以及自定义缓存类,我们可以有效地管理字符串对象,避免不必要的...

    第5讲 String、StringBuffer、StringBuilder有什么区别1

    在Java中,我们有三种主要的字符串类:String、StringBuffer和StringBuilder,它们各自具有不同的特性和适用场景。 首先,`String`类是Java中的一个基础且不可变的类,被声明为`final`,其内部属性也是`final`的。...

    java三种字符串处理差别

    根据不同的应用场景和需求,Java提供了多种处理字符串的方式,其中最为常见且重要的三种方式分别为:`String`(字符串常量)、`StringBuffer`(线程安全的字符串变量)以及`StringBuilder`(非线程安全的字符串变量...

    StringBuffer、StringBuilder、String

    在Java中,有几种不同的方式可以用来创建和修改字符串,其中最常用的是`String`、`StringBuffer`和`StringBuilder`。本文将详细介绍这三种类型的字符串及其区别,特别是`StringBuffer`和`StringBuilder`之间的差异。...

    java面试笔试题String 和StringBuffer的区别

    2. **缓存效率**:当创建相同的字符串时,如果该字符串已经存在于字符串池(String Pool)中,则不会创建新的实例,而是返回已存在的引用。这避免了内存中存在多个相同字符串副本的情况,提高了空间效率。 3. **性能...

    java-API-String类

    字符串在Java中是不可变的对象,也就是说一旦创建了一个`String`对象,它的内容就不能被改变。这使得`String`对象非常适合用于缓存和其他需要保持数据不变性的场景。 #### 二、Java中的包(Package) Java中的包是...

    java 字符串概述和使用(基础)(csdn)————程序.pdf

    在实际编程中,字符串的拼接经常使用`+`运算符或者`StringBuilder`/`StringBuffer`类,因为`+`在多次操作时会产生新的字符串对象,效率较低,而`StringBuilder`和`StringBuffer`则提供可变的字符序列,更适合于字符...

    java基础知识总结大全

    - **字符串池** 是 Java 虚拟机 (JVM) 内部的一个特殊缓存区域,用于存储字符串常量。当创建一个新的字符串时,JVM 首先检查字符串池中是否存在相同的字符串,如果存在,则直接返回该字符串的引用;如果不存在,则会...

    JAVA中关于String的一些注意点

    如果字符串池中已存在这个字符串,则返回字符串池中的引用,否则在字符串池中创建一个新的字符串,并返回它的引用。 示例代码: ```java String hello = "Hello"; System.out.print((hello == ("Hel" + "lo")) + "...

    5讲String、StringBuffer、Stri...1

    Java中的字符串处理是编程中常见的任务,涉及到三个主要的类:String、StringBuffer和StringBuilder。它们之间的主要区别在于线程安全、性能和可变性。 首先,`String`类是不可变的,这意味着一旦创建了一个`String...

    Java面试八股文001-Java-Java基础

    首先,字符串 `"abc"` 会被检查是否已经存在于字符串常量池中。如果不存在,则在常量池中创建一个字符串 `"abc"` 对象。之后,在堆内存中通过 `new String("abc")` 创建一个新的字符串对象。如果 `"abc"` 已经存在于...

    Java常用类与基础API-String的理解与不可变性

    利用 `StringBuilder` 或 `StringBuffer` 修改字符串: ```java String s = "abc"; StringBuilder sb = new StringBuilder(s); sb.setCharAt(0, 'd'); s = sb.toString(); ``` 这段代码首先使用 `StringBuilder` ...

    Java中的String为什么是不可变的?-String源

    此外,编译器和JIT(Just-In-Time)编译器可以进行更多的优化,如字符串连接操作(+操作符)可以通过StringBuilder或StringBuffer的append方法在后台优化,避免了每次连接时创建新的String对象。 2. **线程安全**:...

    java面试题全覆盖-顺序调整版.pdf

    - `String c = "A"`会直接从字符串常量池中获取或创建"A"的对象,`String a = new String("A")`则会先在常量池创建"A",然后在堆中创建一个新的`String`对象,其值与常量池中的"A"共享。 - `String s = "a" + "b" ...

    字符串缓冲区

    字符串缓冲区,通常称为“字符串缓冲”或“字符串缓存”,是一个内存区域,用于存储和管理字符串数据。它的主要目标是避免频繁地创建和销毁字符串对象,因为在许多编程语言中,字符串是不可变的,每次修改都会生成一...

    老生常谈Java字符串进阶(必看篇)

    本文将深入探讨Java中的三个主要字符串类:String、StringBuilder和StringBuffer,以及它们各自的特点和常用方法。 首先,`String`类是最基础的字符串类,它代表不可变的字符序列。这意味着一旦创建了`String`对象...

    3160104875_杨樾人_homework31

    在Java编程语言中,String、StringBuilder和StringBuffer都是用来处理字符串的重要类,它们各自具有不同的特性和使用场景。本文将对这三个类进行源代码分析,探讨它们的主要数据组织、功能实现以及性能差异。 1.1 ...

Global site tag (gtag.js) - Google Analytics