• java string(转)


    初探Java字符串

    优化变成了忧患:String.split引发的“内存泄露”

    String是java中的无处不在的类,使用也很简单。初学java,就已经有字符串是不可变的盖棺定论,解释通常是:它是final的。

    不过,String是有字面量这一说法的,这是其他类型所没有的特性(除原生类型)。另外,java中也有字符串常量池这个说法,用来存储字符串字面量,不是在堆上,而是在方法区里边存在的

    字符串对象内部是用字符数组存储的,那么看下面的例子:

    String m = "hello,world";
    
    String n = "hello,world";
    
    String u = new String(m);
    
    String v = new String("hello,world");

    这些语句会发生什么事情? 大概是这样的:

    1. 会分配一个11长度的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串。

    2. 用n去引用常量池里边的字符串,所以和n引用的是同一个对象。

    3. 生成一个新的字符串,但内部的字符数组引用着m内部的字符数组。

    4. 同样会生成一个新的字符串,但内部的字符数组引用常量池里边的字符串内部的字符数组,意思是和u是同样的字符数组。

    如果我们使用一个图来表示的话,情况就大概是这样的(使用虚线只是表示两者其实没什么特别的关系):

    对象在内存中的布局

    结论就是,m和n是同一个对象(m=n 为true),但m,u,v都是不同的对象(m=u,u=v,m=v均为false),但都使用了同样的字符数组,并且用equal判断的话也会返回true

    • 任何时候,比较字符串内容都应该使用equals方法
    • 修改字符串操作,应该使用StringBuffer,StringBuilder(在字符串修改的时候,会产生一个新的对象,如果执行很频繁,就会导致大量对象的创建,性能问题也就随之而来了)
    • 可以使用intern方法让运行时产生字符串的复用常量池中的字符串
    • 字符串操作可能会复用原字符数组,在某些情况可能造成内存泄露的问题(我们知道像substring、split等方法得到的结果都是引用原字符数组的。 如果某字符串很大,而且不是在常量池里存在的,当你采用substring等方法拿到一小部分新字符串之后,长期保存的话(例如用于缓存等), 会造成原来的大字符数组意外无法被GC的问题,所以可以使用java.io.StreamTokenizer解决大字符串截取的问题。
  • 相关阅读:
    HTML5新特性,新的 Input 类型
    HTML5新特性,拖放(Drag 和 Drop)
    剑指 Offer 32
    剑指 Offer 28. 对称的二叉树
    993. 二叉树的堂兄弟节点
    897. 递增顺序查找树
    872. 叶子相似的树
    637. 二叉树的层平均值
    617. 合并二叉树
    559. N叉树的最大深度
  • 原文地址:https://www.cnblogs.com/SamuelSun/p/5276090.html
Copyright © 2020-2023  润新知