Java之字符串

在我们编程的过程中,发现字符串做操是很常见的行为,最近在研读《Java编程思想》,结合一下自己所学总结一下Java中的字符串。

让我们看一下Java中最常见的几个与字符串相关的类的UML图:


其中String是不可变的(only read),所谓是不可变是因为每一次改变的操作都回新new一个对象

看java源码:

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);//如果beginIndex == 0就返回自己,不然就new一个新对象
    }
</pre><pre name="code" class="java">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);//new一个新对象
    }

而StringBuilder和StringBuffer是可变的字符串,前者是线程不安全,后者是线程安全的,根据自己的需求进行选择

也看一下java源码:

public AbstractStringBuilder deleteCharAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        System.arraycopy(value, index+1, value, index, count-index-1);
        count--;
        return this;//返回的是自己
    }
有一点我这里需要特别说明的是String中的运算符重载 "+"和"+=",java中仅有的重载的运算符,java本身不支持运算符重载。

例如:String str = "a" + "b" + "c" +10;

问这里面产生了多少字符串呢?

我记不清在哪里看的了,说每次+就会产生新的String对象,昨天看《Java编程思想》时,才知道自己错,JVM知道String字符串连接效率低下,对它做了优化!

请看代码!

public class Main {
    public static void main(String[] args) {
        String str = "a";
        String string = "b" + str + "c" + 47;
        System.out.println(string);
    }
}
经过   javac Main.java       

   javap -c Main之后

public class Main {
  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String a
       2: astore_1
       3: <span style="font-size:24px;color:#ff6600;">new           #3                  // class java/lang/StringBuilder</span>
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: ldc           #5                  // String b
      12: invokevirtual #6                  // Method java/lang/StringBuilder.<span style="font-size:24px;color:#330099;">append</span>:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: aload_1
      16: invokevirtual #6                  // Method java/lang/StringBuilder.<span style="font-size:24px;color:#330099;">append</span>:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: ldc           #7                  // String c
      21: invokevirtual #6                  // Method java/lang/StringBuilder.<span style="font-size:24px;color:#330099;">append</span>:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: bipush        47
      26: invokevirtual #8                  // Method java/lang/StringBuilder.<span style="font-size:24px;color:#330099;">append</span>:(I)Ljava/lang/StringBuilder;
      29: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      32: astore_2
      33: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
      36: aload_2
      37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      40: return
}
我们可以看到是new了一个StringBuilder来优化String的"+"操作,并调用append来连接字符串

要注意:

1.一次String的"+"的操作和StringBuilder操作在JVM是一样的,但此在循环中String的连接时创建多个StringBuilder,而StringBuilder的append只创建一次.

2.不要这样使用StringBuilderd的append()方法:sb.append(str1 + "-"+ str2);会令创建对象

String,StringBuilder和StringBuffer上的操作,帮助文档和源码中写的很清楚,可以自行查阅!


字符串中的操作有一个容易被我们忽略的地方:toString()


无意识的递归:
请看下面代码:

<span style="white-space:pre">	</span>public class Main {
		public static void main(String[] args) {
			Main main = new Main();
			System.out.println(main);
		}
		public String toString() {
			return "Main address: " + this + "\n";// 这里的this与字符串连接会先调用toString(),就造成了递归,然后就StackOverFlow
			//                        super.toString()   修改方法
		}
	 }


字符串还有格式化输出,这部分只做blog的完成性补充!
System.out.printlf();
System.out.format();
以及专门为格式化封装的Fomatter类!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值