Day017 String类

Posted 南方风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day017 String类相关的知识,希望对你有一定的参考价值。

String


String类特点


  • String类:代表字符串。Java程序中所有的字符串字面值(如“abc”)都作为此类的实例实现。
  • String是一个final类,代表不可变的字符序列。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改
  • String对象的字符内容是存储在一个字符数组value[]中的
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

注意点:


  1. String声明为final,不可以被继承。

  2. String实现了Serializable接口:表示字符串是支持序列化的。

    实现了Comparable接口:表示String可以比较大小

  3. String内部定义了final char[] value用于存储字符串数据

  4. String:代表不可变的字符序列。简称:不可变性。

    体现:

    1. 当对字符串重新复制时,需要重写指定内存区域赋值,不能使用原有的value[]赋值。

    2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能在原有的value[]上拼接。

    3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值。

  5. 通过字面量的方式(区别于new),给一个字符串赋值,此时的字符串声明在字符串常量池中。

  6. 字符串常量池中是不会存储相同内容的字符串的。

     String s1="abc";//字面量的定义方式
     String s2="abc";
    
     System.out.println(s1==s2);//比较s1和s2的地址值
     
     s1="hello";
    
     System.out.println(s1);
     System.out.println(s2);
    
     System.out.println("*********************");
    
     String s3="abc";
     s3+="def";
     System.out.println(s3);//abcdef
     System.out.println(s2);
    
     System.out.println("*********************");
    
     String s4="abc";
     String s5=s4.replace(\'a\',\'m\');//把a改成m
     System.out.println(s4);//abc
     System.out.println(s5);//mbc
    

    输出结果

    true
    hello
    abc
    *********************
    abcdef
    abc
    *********************
    abc
    mbc
    

    分析:

    • s1==s2,说明s1和s2指向的是同一块内存,而将s1赋为hello之后,没有影响到s2,说明不是改了s1的内存里的值,而是重新开辟了一块内存空间,里面存的是hello,s1指向hello的地址。

    • 同理,s2和s3刚开始都是指向同一片内存,而拼接后s2没有改变,说明拼接也是新开辟了一块内存空间。

    • s4改了之后,s4还是abc,说明也是重新开辟了一块内存空间,再s5指向该内存空间。


String对象的创建

方式一:字面量的方式赋值

String str = "hello";

方式二:本质上 this.value=new char[0];

String s1 = new String();

方式三:本质上 this.value=original.value;

String s2 = new String(String original);

方式四:本质上 this.value=Array.copyOf(value,value.length)

String s3 = new String(char[] a);

String s4 = new String(char[] a,int startIndex,int count);
 //字面量方式定义,值放在常量池中
 String s1="javaEE";
 String s2="javaEE";

 //new创建,值放在堆中
 String s3=new String("javaEE");
 String s4=new String("javaEE");

System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false

输出结果

true
false
false
false

String的不同拼接


String s1 = "javaEE";
String s2 = "hadoop";

String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + 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
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false

String s8=s5.intern();//返回值得到的s8使用的常量值中已经存在的"javaEEhadoop"的地址
System.out.println(s8==s4);//true

输出结果

true
false
false
false
false
false
false
true

结论:

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

  • 只要拼接的有变量参与,结果就在堆中。

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


一道面试题


public class StringTest {
    String str=new String("good");
    char[] ch={\'t\',\'e\',\'s\',\'t\'};

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

    public static void main(String[] args) {
        StringTest ex=new StringTest();
        ex.change(ex.str,ex.ch);
        System.out.println(ex.str+" and ");
        System.out.println(ex.ch);
    }
}

输出结果

good and 
best

分析:

  • 对于基本数据类型,是值传递,引用类型,是传递引用类型的地址,所以char[]数组被改了。
  • 为什么String没改,因为String在赋值时有不可变性,会新开辟一片内存空间。

尚硅谷

以上是关于Day017 String类的主要内容,如果未能解决你的问题,请参考以下文章

017day--python基础作业

原Java学习笔记017 - 面向对象

017.3 集合

2018/12/05 PAT刷题 L1-017. 到底有多二 Java

day06-jsp

Day019 String与其它类型之间的转换