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

关于字符串缓冲池的讨论

    博客分类:
  • Java
阅读更多

 

看到一个关于字符串缓冲池的讨论

(转)
大家先来看看一段奇怪的程序:
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = "Monday";
    }
}
这个程序真是简单啊!可是有什么问题呢?

 

 

1. 来自 String 的忧虑
上面这段程序中,到底有几个对象呢?
可能很多人脱口而出:两个,s1 和 s2
为什么?
String 是 final 类,它的值不可变。
看起来似乎很有道理,那么来检测一下吧,稍微改动一下程序
就可以看到结果了:

public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = "Monday";
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
    }
}
呵呵,很多人都会说已经不止两个对象了
编译并运行程序,输出:s1 == s2
啊!
为什么 s1 == s2 ?
== 分明是在说:s1 与 s2 引用同一个 String 对象 -- "Monday"!

 

 

2. 千变万化的 String
再稍微改动一下程序,会有更奇怪的发现:
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = new String("Monday");
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
我们将 s2 用 new 操作符创建
程序输出:
s1 != s2
s1 equals s2
嗯,很明显嘛
s1 s2分别引用了两个"Monday"String对象
可是为什么两段程序不一样呢?

 

 

3. 在 String 的游泳池中游泳
哈哈,翻了翻书终于找到了答案:
原来,程序在运行的时候会创建一个字符串缓冲池
当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会
在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被
放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1
将 s2 引用 s1 所引用的对象"Monday"

第二段程序中,使用了 new 操作符,他明白的告诉程序:
“我要一个新的!不要旧的!”与是一个新的"Monday"Sting对象被创
建在内存中。他们的值相同,但是位置不同,一个在池中游泳
一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?

 

 

4. 继续潜水
再次更改程序:
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = new String("Monday");
        s2 = s2.intern();
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
这次加入:s2 = s2.intern();
哇!程序输出:
s1 == s2
s1 equals s2
原来,程序新建了 s2 之后,又用intern()把他打翻在了池里
哈哈,这次 s2 和 s1 有引用了同样的对象了
我们成功的减少了内存的占用

 

 

5. == 与 equals() 的争斗
String 是个对象,要对比两个不同的String对象的值是否相同
明显的要用到 equals() 这个方法
可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,
哦,天哪,真慢啊
更好的办法:
把所有的String都intern()到缓冲池去吧
最好在用到new的时候就进行这个操作
String s2 = new String("Monday").intern();
这样大家都在水池里泡着了 。

import java.*;
import java.io.*;

public class hashcode
    {
    public static void main(String args [])
        {
        String o1 = new String("Hello");

        String o2 = new String("Hello");

        if (o1.equals(o2))
            System.out.println("equal");                 //equal

        System.out.println(o1.hashCode());               //69609650
        System.out.println(System.identityHashCode(o1)); //18581223
        System.out.println(o2.hashCode());               //69609650
        System.out.println(System.identityHashCode(o2)); //3526198

        o2 = "hello";

        if (!o1.equals(o2))
            System.out.println("not equal");             //not equal

        System.out.println(o1.hashCode());               //69609650
        System.out.println(System.identityHashCode(o1)); //18581223
        System.out.println(o2.hashCode());               //99162322
        System.out.println(System.identityHashCode(o2)); //7699183

        o1 = "Hello";
        o2 = "hello";

        if (!o1.equals(o2))
            System.out.println("not equal");             //not equal

        System.out.println(o1.hashCode());               //69609650
        System.out.println(System.identityHashCode(o1)); //14285251
        System.out.println(o2.hashCode());               //99162322
        System.out.println(System.identityHashCode(o2)); //7699183

        o1 = "Hello";
        o2 = "Hello";

        if (o1.equals(o2))
            System.out.println("equal");                      //equal

        System.out.println(o1.hashCode());                    //69609650
        System.out.println(System.identityHashCode(o1));      //14285251
        System.out.println(o2.hashCode());                    //69609650
        System.out.println(System.identityHashCode(o2));      //14285251

        System.out.println("hello".hashCode());               //99162322
        System.out.println("hello".hashCode());               //99162322
        System.out.println(System.identityHashCode("hello")); //7699183
        System.out.println("Hello".hashCode());               //69609650
        System.out.println("Hello".hashCode());               //69609650
        System.out.println(System.identityHashCode("Hello")); //14285251

        java.lang.System.exit(0);
        }
    }
 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lidengzhi0000/archive/2009/04/17/4087236.aspx

 

分享到:
评论

相关推荐

    狐狸与兔子·java源码-StringTheory-ZCW:70个Java字符串练习,用于字符串练习

    70个练习可能涵盖了以上所有概念,甚至包括更高级的主题,如正则表达式、Unicode字符处理、字符串缓冲区同步等问题。通过实践这些练习,开发者能更好地理解字符串的底层工作原理,提高在实际开发中处理字符串问题的...

    JAVA精华.docJAVA精华.doc

    在Java中,字符串常量池是一个特殊区域,存储了所有字面量字符串。当创建两个引用相同的字符串,如`String s1 = "hello"; String s2 = "hello";`,它们实际上是同一个对象的引用,所以`s1 == s2`会返回true。然而,...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    varchar2 1~4000字节 可变长度字符串,与CHAR类型相比,使用VARCHAR2可以节省磁盘空间,但查询效率没有char类型高 数值类型 Number(m,n) m(1~38) n(-84~127) 可以存储正数、负数、零、定点数和精度为38位的浮点数...

    C语言的Android binary XML(AXML)解析代码

    - **解析字符串池**:字符串池存储所有字符串资源,包括标签名、属性名和属性值。解析器需要查找并解析这个池,以便后续引用。 - **解析资源ID表**:资源ID表映射了字符串到整型资源ID的对应关系,这对于查找和...

    MMP内存池_源码.pdf

    字符串分配也是内存管理的一部分,特别是当字符串经常被创建和销毁时。合理的字符串分配策略可以显著提高性能。 #### 4. MMP内存池 MMP内存池是针对特定项目需求设计的一种内存池实现。 - **MMP内存分配特点**:...

    java实用课件附含代码示例

    字符串在Java中是特殊的对象,会涉及到String类、字符串池以及字符串的操作方法。 5. **输入输出及数据库操作** (PPT07输入输出及数据库操作.ppt) - 这部分可能包括I/O流的使用,如文件读写,标准输入输出流,以及...

    90个高质量的java问答.pdf

    - **字符串池**:探讨字符串常量池在字符串传递中的作用。 #### 15. FileOutputStream 与 FileWriter 的区别 - **输出流概述**:介绍 `FileOutputStream` 和 `FileWriter` 的基本用途。 - **数据类型**:解释两者...

    core java 视频源码

    5. **第10章** - 这章可能涉及字符串(String)类的使用,包括字符串的创建、操作(如concatenation、substring、replace等)以及字符串池的概念。 6. **第11章** - 可能会讲解文件和I/O流。Java的I/O流允许程序进行...

    db2开发参考

    **数据类型**在DB2中是多种多样的,包括数值类型(如INT、FLOAT、DECIMAL)、字符串类型(如VARCHAR、CHAR)、日期/时间类型(如DATE、TIME、TIMESTAMP)以及二进制类型(如BLOB、CLOB)等。选择合适的数据类型对于...

    马士兵老师的Java课件

    5. **字符串处理**:讲解String类的特性,字符串常量池,以及StringBuilder和StringBuffer的使用。 6. **异常处理**:学习如何使用try-catch-finally语句块来捕获和处理运行时异常。 接下来是"J2SE下半部分",这...

    数据结构答案清华版

    第四章“串”讨论了字符串这种一维数据结构,包括串的基本操作,如串的模式匹配,以及字符串的存储方式——定长数组和链表。 第五章“数组和广义表”主要讲述数组的特性,包括一维数组、二维数组和多维数组。广义表...

    Java基础教程.zip_java

    5. **字符串**:Java中的String类,字符串的操作方法,以及字符串池的概念。 6. **异常处理**:理解Java中的异常处理机制,包括try-catch-finally语句块,throw和throws关键字,自定义异常。 7. **集合框架**:...

    Java核心技术卷1+卷2+第8版

    6. **字符串处理**:讲解String类,字符串池,以及常用的字符串操作方法。 7. **异常处理**:解释如何使用try-catch-finally语句块进行异常处理,以及自定义异常。 8. **输入/输出(I/O)**:涵盖流的概念,文件...

    Java语言程序设计-基础篇(原书第8版)

    6. **字符串处理**:Java中的String类是不可变的,书中有专门章节讨论字符串的创建、比较、操作方法,以及字符串池的概念。 7. **输入/输出流**:Java的I/O流系统是处理数据输入和输出的关键,包括文件操作、网络...

    严蔚敏《数据结构(c语言版)习题集》一书中所有算法设计题目的解决方案

    本章会讨论串的各种操作,如模式匹配、字符串连接和子串查找,以及如何高效地实现这些操作。 第5章“数组和广义表”探讨了一维和多维数组,以及更复杂的广义表结构。广义表可以表示复杂的数据关系,例如图的顶点...

    CoreJava

    7. **字符串处理**:讲解String类的常用方法,字符串池的概念,以及StringBuilder和StringBuffer的使用。 Volume II则进一步探讨了更高级的主题: 1. **泛型**:介绍泛型的使用,如何定义泛型类、接口,以及泛型...

    Java面试宝典全稿PDF

    7. **字符串处理**:讲解String类的常用方法,如concat、substring、equals、indexOf等,以及字符串池的概念。 8. **异常处理**:阐述try-catch-finally语句块的使用,以及自定义异常的创建。 第二章:进阶与实战 ...

    14.9 InnoDB Row Storage and Row Formats

    如果更多的行能够被存储在单个磁盘页中,则查询和索引查找的速度将更快,InnoDB缓冲池所需的缓存内存将更少,而且对数值型和短字符串列的写操作所需的I/O也会减少。InnoDB存储引擎将每个表的数据分割到多个数据页中...

    oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86-64

    对于SQL*Plus,还需要配置TNS_ADMIN环境变量,指向包含tnsnames.ora文件的位置,以便解析数据库连接字符串。 **6. 连接数据库** 使用SQL*Plus,用户可以通过指定用户名、密码和连接字符串来连接到Oracle数据库。...

Global site tag (gtag.js) - Google Analytics