天天看点

java基础-java常用类-String、StringBuffer、StringBuilder-String类(1)Java常用类之String、StringBuilder、StringBuffer

Java常用类之String、StringBuilder、StringBuffer

String类

String的特性

1.String类:代表字符串。Java程序中的所有字符串字面值(如:“abc”)都作为此类的实例实现

2.String是一个final类(不可被继承),代表不可变的字符序列

3.字符串是常量,用双引号引起来表示,它们的值在创建之后不能更改

4.String对象的字符内容是存在一个字符数组char value[]中的;

public final class String implements java.io.Serializable,Comparable, CharSequence{

​ private final char value[];

​ private int hash;

String:字符串,使用一对""引起来
* 1.String类是声明为final的,不可被继承
* 2.String实现了Serializable接口,表示字符串是支持序列化的
*          实现了Comparable接口,表示String可以比较大小
* 3.String内部定义了final char[] value用于存储字符串数据
* 4.String类代表不可变的字符序列。简称:不可变性
*      体现:1.当对字符创重新赋值时,需要重新指定内存区域赋值,不能使用原有的value修改
*           2.当对字符串重新拼接时,需要重新指定内存区域生成拼接后的值,不能拼接原有的值
*           3.当调用String的replace()方法时(修改字符或字符串),需要重新指定内存区域生成replace后的字符串
* 5.通过字面量的形式(区别于new)给字符串赋值,此时的字符串值声明在字符串常量池中
* 6.字符串常量池中是不会维护相同的字符串的
           

String s1 = “abc”;

String s2 = “abc”;

该图基于jdk1.6及以前 jdk1.7及以后已将字符串常量池移入堆中

java基础-java常用类-String、StringBuffer、StringBuilder-String类(1)Java常用类之String、StringBuilder、StringBuffer

String对象的创建

String str = "hello";
    //本质上this.value = new char[0];(源码) 1.8  this.value = "".value;
    String s1 = new String();
    //this.value = original.value;
    String s2 = new String(String original);
    //this.value = Arrays.copyOf(value,value.length);
    String s3 = new String(char[] a);
    
    String s4 = new String(char[] a,int startIndex,int count);
           

问题:

String str1 = “abc” 与 String str2 = new String(“abc”)的区别?

1.字符串常量存储在字符串常量池中,目的是共享

2.字符串非常量存储在堆中

两者的区别在于,String str1 = “abc” 直接将字符串常量池中的abc地址值赋值给了str1变量。而String str2 = new String(“abc”)是在堆中先创建了一个String对象,将这个String 对象中的 value属性指向了字符串常量池中的abc地址值,然后将堆中的String对象的地址值赋值给st2变量

该图基于jdk1.6及以前 jdk1.7及以后已将字符串常量池移入堆中

java基础-java常用类-String、StringBuffer、StringBuilder-String类(1)Java常用类之String、StringBuilder、StringBuffer

String对象的拼接

小测试

@Test
public void test2(){
    String s1 = "my";
    String s2 = "JavaBase";

    String s3 = "myJavaBase";
    String s4 = "my"+"JavaBase";
    String s5 = s1 + "JavaBase";
    String s6 = "my" + s2;
    String s7 = s1 + s2;

    System.out.println(s3 == s4);//true 都指向字符串常量池中的myJavaBase对象
    System.out.println(s3 == s5);//false s5指向的是堆中的String对象
    System.out.println(s3 == s6);//false s6指向的是堆中的String对象
    System.out.println(s3 == s7);//false s7指向的是堆中的String对象
    System.out.println(s5 == s6);//false s5 和 s6 指向的是不同的堆中的String对象

    String s8 = s5.intern();//获取常量池中的值
    System.out.println(s3 == s8);//true
}
           

问题:String a = new String(“abc”); 这种方式,在内存中创建了几个对象

答:两个,1.new String()放在堆中的对象 2.放在字符串常量池中的"abc"对象

拼接问题二:

@Test
public void test2(){
    String s1 = "my";
    String s2 = "JavaBase";

    String s3 = "myJavaBase";
    String s4 = "my"+"JavaBase";
    String s5 = s1 + "JavaBase";
    String s6 = "my" + s2;
    String s7 = s1 + s2;

    System.out.println(s3 == s4);//true
    System.out.println(s3 == s5);//false
    System.out.println(s3 == s6);//false
    System.out.println(s3 == s7);//false
    System.out.println(s5 == s6);//false

    String s8 = s5.intern();//获取常量池中的值
    System.out.println(s3 == s8);//true
}
           
java基础-java常用类-String、StringBuffer、StringBuilder-String类(1)Java常用类之String、StringBuilder、StringBuffer

结论:

1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。

2.字符串拼接中,只要有一个是变量,拼接后的对象就在堆中

3.如果拼接的结果调用intern()方法,返回值就在常量池中。

面试题:

public class StringTest2 {


    String str = new String("abc");
    char[] a = {'h','e','l','l','o'};

    public void change(String str1,char[] a){
        str1 = "test ok";
        a[0] = 'b';
    }


    public static void main(String[] args) {
        StringTest2 test = new StringTest2();

        test.change(test.str,test.a);
        System.out.println(test.str );//abc
        System.out.println(test.a);//bello

    }
}
           

分析:

1.在change方法中,值传递,str1变量获取到的是abc,再修改str1变量值,不会修改StringTest2.str的值

2.char[] a获取的是char[]的地址值,所以修改的是对中char[]对象的内容。