java.lang.String StringBuffer StringBuilder

来源:互联网 发布:rpg游戏制作软件 编辑:程序博客网 时间:2024/06/16 07:25

java.lang.String

构造函数

  • String(byte[] bytes, Charset charset)
    通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。

  • String(char[] value)
    分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。该字符数组的内容已被复制,后续对字符数组的修改不会影响新创建的字符串

方法

  • public String replace(char oldChar, char newChar)
    如果 oldChar 在此 String 对象表示的字符序列中没有出现,则返回对此 String 对象的引用。否则,创建一个新的 String 对象,它所表示的字符序列除了所有的 oldChar 都被替换为 newChar 之外,与此 String 对象表示的字符序列相同。
        String s = "123";        s.replace("1", "2");        System.out.println(s);        输出:123 是新建了一个String 对原来的String没有影响
  • public String intern()
    当调用 intern 方法时,如果字符串常量池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用

  • public String[] split(String regex)

  • public String toLowerCase()

  • public String toUpperCase()

  • public String trim()
    返回字符串的副本,忽略前导空白和尾部空白。

  • 重写了equal()方法 重写了hashcode方法

注意

  • 三种新建方式

    1. String s = “123”;
      JVM通过字符串常量池查找不到内容为123的字符串对象存在,那么会创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量s。

    2. String s = new String(“123”);
      当我们使用了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象的引用,新的字符串对象都会创建。

    3. 使用+串联,生成新的字符串

字符串常量池中存放的时引用还是对象,这个问题是最常见的。字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。常量池在方法区中,道理是一样的,方法区中也是静态变量的引用,具体是在堆上分布内存参照这篇,注意perm的大小。

  • 字符串的拼接+
      String name = "Andy";      String age = "24";      String job = "Developer";      String info = name + age + job;

实际上编译器做了优化,内部是这样处理的:
new StringBuilder()
StringBuilder.init()
StringBuilder.append()
StringBuilder.toString()

  1. 当使用任何方式来创建一个字符串对象时,运行中JVM会在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
  2. Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
  3. 使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个.
  4. 使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。
  • String a=”a”+”b”+”c”在内存中创建几个对象?

    知乎上的回答:javac会进行常量折叠,全字面量字符串相加是可以折叠为一个字面常量,而且是进入常量池的。

  • String str=new String("abc");

    这行代码究竟创建了几个String对象:
    public String(String original)
    初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。”abc”作为构造函数的参数先被初始化,然后是new过程。所以是两个对象。

  • 关于深入理解JVM书中的String.intern()的方法的理解

        String a = "qwer";        String b = new String("qwer");        System.out.println(a==b);        System.out.println(b==b.intern());        String c = new String("计算机");        String ci = c.intern();        System.out.println(ci==c);        String stri1 = new StringBuilder("计算机er").append("qw").toString();        System.out.println(stri1.intern()==stri1);        false        false        false        true

我的理解:文中提到了字符串常量池中存放的时引用还是对象,这个问题是最常见的。字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。我看了深入理解JVM,p57,在JDK1.6及之前的版本中,常量池分配在永久代,intern()方法会把首次遇到的字符串实例复制。记住是复制,到永久代,返回这个永久代中这个字符串实例的引用,所以在JVM这本书里面,他用了JDK1.6去实现永久代溢出。在JDK1.6之后,不再复制,只是在常量池中记录首次出现的示例引用,常量池中是引用,不再是对象,所以文章中的验证方式不会导致永久代溢出。

关于上述程序中,我这样理解String c = new String(“计算机”);

这句话编译的时候,遇到”计算机”的时候,编译器会把他放进常量池,运行的时候,堆中新建了一个String对象,此时内存中有两个地方可以找到”计算机”,c.intern()返回的引用是常量池中的引用(因为编译的时候,常量池中已经有”计算机了”),所以ci==c返回false.

但是String stri1 = new StringBuilder(“计算机er”).append(“qw”).toString();注意用了append(),编译器只能把”计算机er” “qw”放进常量池,运行的时候才有”计算机erqw”,编译后常量池里面的没有的,stri1.intern()==stri1返回的一个东西,(stri1.intern()这句话让常量池多了一个引用,指向我们的String对象)

java.lang.StringBuilder StringBuffer

构造函数

方法

  • 增:append() insert()
  • 删:delete()
  • 改:replace() reverse() substring()

方法比较面向对象。

注意

StringBuffer和StringBuilder这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。这是因为在源代码中StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。

0 0
原创粉丝点击