Java中String类最详细

1、简介

String代表的是字符串常量,他们的值在创建后不能更改。字符串缓冲区支持可变的字符串。因为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

String类继承了序列化,所以String类是可以被序列化的,另外,他的底层组成其实是个char 类型的数组,并且是final 类型的,这也进一步解释了为什么String的值一旦创建了之后是不能被修改的,String类中所有方法返回的都是一个新的String对象

// 也就是说
String str = "ABCD";      // 定义一个字符串对象,其实等价于:
char[] cr = new char[]{'A','B','C','D'};

String类中每一个看起来会修改String值得方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串对象.
Java中String类最详细_第1张图片

2、创建字符串对象的方式

String str = “hello word” //直接引用常量区
String str = new String(“hello world”) //在堆内存创建对象

在字符串中,如果采用直接赋值的方式(String str=“123”)进行对象的实例化,则会将匿名对象“123”放入对象池,每当下一次对不同的对象进行直接赋值的时候会直接利用池中原有的匿名对象.

总结:两种实例化方法的区别

1)直接赋值:只开辟一块堆内存空间,并且会自动入池,不会产生垃圾

2)构造方法:会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收,而且不能够自动入池,需要通过public String intern();方法进行手工入池。

== 和public boolean equals()比较字符串的区别

==在对字符串比较的时候,对比的是内存地址,而equals比较的是字符串内容,在开发的过程中,equals()通过接受参数,可以避免空指向。


String str = null;
if(str.equals("hello")){//此时会出现空指向异常
    ...
}
if("hello".equals(str)){//此时equals会处理null值,可以避免空指向异常
    ...
}

string类对象一旦声明则不可改变,改变的只是地址,原来的字符串还是存在的,并且产生垃圾

3、String的常用方法

判断功能

boolean equals(Object obj):比较字符串的内容是否相同
boolean equalsIgnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
boolean startsWith(String str): 判断字符串对象是否以指定的str开头
boolean endsWith(String str): 判断字符串对象是否以指定的str结尾
boolean contains(CharSequence s): 判断字符串包含指定的字符值序列
@Test
public void test(){
    String str1 = "abc";
    String str2 = new String("abc");
    String str3 = "ABC";
	//以下全部为true
    System.out.println(str1.equals(str2));		
    System.out.println(str1.equalsIgnoreCase(str3));
    System.out.println(str1.startsWith("ab"));
    System.out.println(str1.endsWith("bc"));
    System.out.println(str1.contains("abc"));
}

获取功能

int length():获取字符串的长度,其实也就是字符个数
char charAt(int index):获取指定索引处的字符
int indexOf(String str):获取str在字符串对象中第一次出现的索引
String substring(int start):从start开始截取字符串
String substring(int start,int end):从start开始,到end结束截取字符串。包括start,不包括end
@Test
public void test(){
    String str = "abcd";
    System.out.println(str.length());  //4
    System.out.println(str.charAt(0));  //a
    System.out.println(str.indexOf("a"));   //0
    System.out.println(str.substring(2));   //cd
    System.out.println(str.substring(1,3)); //bc
}

转换功能

char[] toCharArray():把字符串转换为字符数组
String toLowerCase():把字符串转换为小写字符串
String toUpperCase():把字符串转换为大写字符串
@Test
public void test(){
    String str = "AbCdEf";
    char[] chars = str.toCharArray();
    for (char o : chars) {
        System.out.print(o);
    }       //AbCdEf
    System.out.println();
    System.out.println(str.toLowerCase());  //abcdef
    System.out.println(str.toUpperCase());  //ABCDEF
}

其他方法

String trim():去除字符串两端空格
String[] split(String str):按照指定符号分割字符串
@Test
public void test5(){
    String str = "  A bCdEf ";      //A bCdEf
    System.out.println(str.trim());
    String str2 = "a/b/nh/c";
    String[] strs = str2.split("/");
    for (String o : strs) {
        System.out.print(o+" ");    //a b nh c 
    }
}

4、String的不可变性

Strings are constant; their values cannot be changed after they are created
//String 是个常量,从一出生就注定不可变。

因为String太过常用,JAVA类库的设计者在实现时做了个小小的变化,即采用了享元模式,每当生成一个新内容的字符串时,他们都被添加到一个共享池中,当第二次再次生成同样内容的字符串实例时, 就共享此对象,而不是创建一个新对象,但是这样的做法仅仅适合于通过=符号进行的初始化。

  • 从内存角度:创建字符串时,如果该字符串已经存在于池中,则返回现有字符串的引用,而不是创建新对象。多个String变量引用指向同一个地址。如果字符串是可变的,用一个引用更改字符串将导致其他引用的值错误。这是危险的。
  • 缓存Hashcode:字符串的Hashcode在Java中经常配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap、HashTable。不可变性的特性保证了hashcode永远是相同的。不用每次使用hashcode就需要计算hashcode。这样更有效率。因为当向集合中插入对象时,是通过hashcode判别在集合中是否已经存在该对象了(不是通过equals方法逐个比较,效率低)
  • 方便其他类使用:其他类的设计基于String不可变,如set存储string,改变该string后set包含了重复值。
  • 安全性:String呗广泛用作许多Java类的参数,例如网络连接、打开文件。如果对string的某处改变一不小心就影响了该变量所有引用的表现,则连接或文件将被更改,这可能导致严重的安全威胁。不可变对象不能被写,所以不可变对象自然是线程安全的,因为不可变对象不能更改,它们可以在多个线程之间自由共享。

后set包含了重复值。

  • 安全性:String呗广泛用作许多Java类的参数,例如网络连接、打开文件。如果对string的某处改变一不小心就影响了该变量所有引用的表现,则连接或文件将被更改,这可能导致严重的安全威胁。不可变对象不能被写,所以不可变对象自然是线程安全的,因为不可变对象不能更改,它们可以在多个线程之间自由共享。

你可能感兴趣的:(笔记)