• 字符串


    String类

    概念:String是不可变类,即一但一个String对象被创建,包含在这个对象的字符序列是不可改变的,直至该对象被销毁。

    1 //String的主要成员变量
    2 private final char value[];
    3 /**
    4 value指向的是一个字符串数组,字符串中的字符就是用这个value变量存储起来的,并且用final修饰,说明value一旦赋予初始值之后,value指向的地址就不能再改变了,虽然value指向的数组是可以改变的,但是String也没有提供相应的方法让我们去修改value指向的数组的元素,所以说String是一个不可变类,String对象的不可变还有一点就是对String类型的所有改变内部存储结构的操作都会new出一个新的String对象
    5 */

    String类是被final修饰的,不能有子类,里面的一些方法也加上了final

    例子:也就是说创建"abc"字符串后,"abc" 自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"

    注意:"abc" 这是一个字符串对象,字符串在java中有优待,不需要new也是一个对象,属于String类型。

    在java中随便使用双引号括起来的都是String对象。

    例如:"abc","def","hello world!",这是3个String对象

    在JDK当中双引号括起来的字符串,例如:"abc" "def"都是直接存储在“方法区”的“字符串常量池”当中的。

    注解:在JDK1.7时,把字符串常量池移动到了堆内存中

    为什么SUN公司把字符串存储在一个“字符串常量池”当中呢。因为字符串在实际的开发中使用太频繁。

    为了执行效率,所以把字符串放到了方法区的字符串常量池当中

    当使用Sring str = "abc";这种形式创建字符串,那么String就不会在堆内存中创建对象,"abc"存储在字符串常量池中,而str存储的是"abc"在字符串常量池中的地址

    当使用String str = new String("abc");这种形式创建字符串,需要在堆内存中创建字符串对象,而在String对象在堆内存中保存的是"abc"在字符串常量池中的内存地址,而str保存的是对象在堆内存中的地址

    例子:

    1. 第一个例子

      1 String str1 = "abc";
      2 String str2 = "abc";
      3 System.out.println(str1 == str2);//true
      4 //为true原因:在字符串常量池中相同的字符串只会存储一份,不会重复,而str1和2都是同一个地址
    2. 第二个例子

      1 String str1 = "abc";
      2 String str2 = "abc";
      3 String str3 = "ab" + "c";
      4 System.out.println(str1 == str3);//true
      5 //为true原因:"ab"和"c"都是字面值常量,在编译时直接编译成"abc",而"abc"在字符串常量池中存在了,就不会再创建,直接把地址赋值给str3
    3. 第三个例子

      1 String str1 = "abc";
      2 final String s1 = "ab";
      3 final String s2 = "c";  
      4 String str4 = s1 + s2;
      5 System.out.println(str1 == str4);//true
      6 //为true原因:s1 和s2都是常量,在编译时直接编译成"abc"
    4. 第四个例子

      1 String str1 = "abc";
      2 String s3 = "ab";
      3 String s4 = "c";
      4 String str5 = s3 + s4;
      5 System.out.println(str1 == str5);//false
      6 //为false的原因:s3、s4时变量,字符串拼接时,如果有变量参与的情况下,String底层使用的是StringBuilder,所以内存地址不一样了
      7 //String str5 = s3 + s4;拼接new StringBuilder(s3).append(s4).toString()

      注意:频繁的字符串拼接最好不要使用 +,因为java中的字符串是不可变的,每一次拼接都会new StringBuilder拼接产生新字符串。这样会占用大量的内存。造成内存空间的浪费。

      如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的:

      • java.lang.StringBuffer

      • java.lang.StringBuilder

    5. 第五个例子

      1 String s5 = new String("hello");
      2 String s6 = new String("hello");
      3 //上面两行一共创建了3个对象:
      4 //字符串常量池中有1个:"hello"
      5 //堆内存当中有两个String对象。

    通过例子,字符串对象之间的比较不能使用“==”,"=="不保险。应该调用String类的equals方法,String类已经重写了toString()和equals()方法

    注解:使用equals()方法进行比较时,把已知道的放在前面,未知的放在equals()方法中,这样可以避免空指针异常

    String类的构造方法

    1 String s = "abc";
    2 String s = new String("abc");
    3 String s = new String(byte数组);//将整个数组转换为字符串
    4 String s = new String(byte数组, 起始下标, 长度);//将数组中的一部分转换为字符串
    5 String s = new String(char数组);
    6 String s = new String(char数组, 起始下标, 长度);
    7 ...

     

    valueOf()方法,参数是一个对象的时候,会自动调用该对象的toString()方法

    没有重写toString()方法之前打印输出的是对象内存地址

    为什么输出一个引用的时候,会调用toString()方法?

    通过源代码可以看出println()这个方法,先调用了String中的valueOf()方法,然后valueOf()方法调用了toString()方法

    注解:在输出任何数据的时候println()都是先转换成字符串,再调用toString(),然后输出,当println()里的是对象,也是先转换为字符串,然后调用toString(),只不过调用的是对象的toString()方法,如果对象没有重写,就打印对象内存地址

    StringBuffer类

    含义:StringBuffer代表可变的字符序列,StringBuffer称为字符串缓冲区,实现了序列化接口

    继承了AbstractStringBuilder

    工作原理:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer是可变对象,与String最大的不同在StringBuilder中是提供了响应的方法让我们去修改value指向的数组的元素,这也是StringBuffer的字符串序列可变的原因。

    JDK1.8,StringBuffer底层是一个char数组,StringBuffer默认的初始化容量是16

    StringBuffer是线程安全的,StringBuffer中的每个方法都加上了synchronized锁

    StringBuffer拼接字符使用的是append()方法,在字符串的末尾追加,不会新建对象

    append()在进行字符串追加的时候,会调用有ensureCapacityInternal()方法判断是否需要进行扩容

    而ensureCapacityInternal()方法中扩容调用的是Arrayys数组中copyOf()方法

    如何优化StringBuffer的性能?

    • 在创建StringBuffer的时候尽可能给定一个初始化容量。

    • 最好减少底层数组的扩容次数。预估计一下,给一个大一些初始化容量。

    • 关键点:给一个合适的初始化容量。可以提高程序的执行效率。

    StringBuilder类

    含义:StringBuilder代表可变的字符序列,称为字符串缓冲区,实现了序列化接口

    继承了AbstractStringBuilder

    工作原理:和StringBuffer相同

    StringBuilder不是线程安全的

    JDK1.8,StringBuilder底层是一个char数组,StringBuilder默认的初始化容量是16

  • 相关阅读:
    MVC @Url.Action 小示例
    Eclipse快捷键
    MVC视频下载/文件上传
    MySQL数据库备份/导出
    C#文件下载
    C#正则表达式匹配字符串中的数字
    常用的LINQ to SQL 用法
    C# 实现抓取网页内容(一)
    C# 繁体字和简体字之间的相互转换
    我到底会什么??
  • 原文地址:https://www.cnblogs.com/thesky-wfei/p/14124127.html
Copyright © 2020-2023  润新知