zoukankan      html  css  js  c++  java
  • java中String、StringBuilder和StringBuffer理解

    String、StringBuilder和StringBuffer理解

    1>String

    java.lang.String 类

    public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;
    
        /**
         * Class String is special cased within the Serialization Stream Protocol.
         *
         * A String instance is written initially into an ObjectOutputStream in the
         * following format:
         * <pre>
         *      <code>TC_STRING</code> (utf String)
         * </pre>
         * The String is written by method <code>DataOutput.writeUTF</code>.
         * A new handle is generated to  refer to all future references to the
         * string instance within the stream.
         */
        private static final ObjectStreamField[] serialPersistentFields =
                new ObjectStreamField[0];
      ......

    从以上JDK中String源码可以看出,String类被final修饰,在java中被final修饰的类是不能够被继承的,而且String类中的成员变量都被修饰成final。

    而且可以看出String是通过char数组来实现保存字符串的。

        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);
        }
    
        public String concat(String str) {
            int otherLen = str.length();
            if (otherLen == 0) {
                return this;
            }
            int len = value.length;
            char buf[] = Arrays.copyOf(value, len + otherLen);
            str.getChars(buf, len);
            return new String(buf, true);
        }
    
        public String replace(char oldChar, char newChar) {
            if (oldChar != newChar) {
                int len = value.length;
                int i = -1;
                char[] val = value; /* avoid getfield opcode */
    
                while (++i < len) {
                    if (val[i] == oldChar) {
                        break;
                    }
                }
                if (i < len) {
                    char buf[] = new char[len];
                    for (int j = 0; j < i; j++) {
                        buf[j] = val[j];
                    }
                    while (i < len) {
                        char c = val[i];
                        buf[i] = (c == oldChar) ? newChar : c;
                        i++;
                    }
                    return new String(buf, true);
                }
            }
            return this;
        }

    以上是String类的部分成员方法,可以看出他们都不是在原有的String对象上操作的。只要对String对象进行改变,则就会创建新的String对象,对原有的对象并没有改变。

    注意:String str1="abc" 和 String str2=new String("abc");有什么区别呢? 代码测试为证:

    public class stringTest {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            String str1 = "abc";
            String str2 = new String("abc");
            String str3 = new String("abc");
            String str4 = "abc";
            
            System.out.println(str1 == str2);
            System.out.println(str2 == str3);
            System.out.println(str1 == str4);
        }
    }

    结果是:

    所以:string str1="abc"; 这样的语句是在编译时生成了字面常量和字符引用,然后在运行时蒋"abc"保存放到了运行时的常量池中,当下一个语句执行的时候就会从运行时常量池中查找 是否存在,如果存在则将他的引用指向了字面常量,如果没有就新开辟一个空间存放字面常量,并将引用指向他。

      有关new语句创建对象时,都是在堆中进行的,不会检查对象是否存在,所以每一个new语句都会创建一个新的对象。

    2>StringBuilder

    StringBuilder对String的改变操作是对原有对象进行操作的。

    3>StringBuffer (线程安全)

    StringBuffer和StringBuilder是类似的,之不过StringBuffer下的方法被snychronized修饰,线程安全。

    这三个类是各有利弊,应当根据不同的情况来进行选择使用:

    当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;

    当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。

  • 相关阅读:
    1.Netty 实战前言
    8.Netty发送对象
    7.Netty中 handler 的执行顺序
    6.高性能NIO框架netty
    5.NIO_ Selector选择器
    4.NIO_Channel 通道
    3.NIO_Buffer缓冲区
    2.Java NIO 简介
    那些堪称神器的 Chrome 插件
    获取当前操作的IFrame 对象的方法
  • 原文地址:https://www.cnblogs.com/yuxin-555xt/p/6414843.html
Copyright © 2011-2022 走看看