I学霸官方免费教程十九:Java常用类之String类

来源:互联网 发布:php怎么防止xss攻击 编辑:程序博客网 时间:2024/05/18 01:33

String类

首先,String是引用类型,也是唯一一个可以不使用关键字new创建对象的引用类型,因为有字符串常量值,使用英文格式的双引号""括起来就是字符串常量值。
创建对象的两种方式
      方式一、String  s1 = “abc”;
      方式二、String  s2 = new  String(“abc”);
      这两种方式都是创建了一个字符串对象,值都是字符串abc;
不同的是
      方式一是直接使用字符串常量abc赋值给变量s1,此时系统先到常量池中查找有没有字符串常量abc,如果有将字符串常量abc在常量池中的地址赋值给变量s1,如果没有会将字符串常量abc加入到常量池中,并把地址赋值给变量s1。
      而方式二是在堆内存中创建一个String类型的对象,在这个对象中存储着字符串abc
其次,String类型被设计成不可变的,即对象不可变;一旦对象被创建,这个对象将无法被修改,引用(变量)是可以修改;如上例中s1是引用(变量),它可以存储其他字符串的地址,但是字符串abc本身被创建后无法再改变了。

实例:
      //创建一个String类型的对象
      String  s = "abc";
      //如果要将变量s的修改为"abcxyz",代码如下
      s = s+"xyz";
      //输出结果为:abcxyz
      System.out.println(s);
      //由于这里使用两个字符串常量相连接,系统会默认当成一个字符串,即"abcxyz" 
      String  s1 = "abc" + "xyz"; 
      String  s2 = "abcxyz";
      其中第二行代码会先到常量池中查找有没有字符串xyz,如果没有将字符串xyz加入到常量池中,此时常量池中有abc和xyz两个字符串常量;
      然后系统底层会默认在堆中创建一个StringBuilder类型的对象;然后用StringBuilder对象的append方法,将两个字符串连接到一起,最后再调用toString方法返回连接后的字符串abcxyz,并将返回的字符串abcxyz的地址赋值给变量s。

接下来验证实例中变量s、s1和s2三个变量,引用的是不是一个对象。可以使用双等号来进行判断。
      //输出结果为:false
      System.out.println(s == s1); 
      //输出结果为:true
      System.out.println(s1 == s2); 
      由以上结果可以看出,变量s1和s2中存储的是同一字符串对象的地址,而变量s中存储的是另一字符串对象的地址,但这两个字符串对象的内容是相同的(都是abcxyz);那么如何判断两个字符串的内容是否相同呢?

在String类中已经重写了父类Object中的equals方法,通过equals方法可以判断两个字符串内容是否相同
      //输出结果为:true
      System.out.println(s.equals(s1)); 


总结:
当使用字符串常量时,系统会先到常量池中寻找,如果没找到,将字符串常量加入到常量池中。
使用关键字new创建的字符串对象保存在堆内存中。
使用字符串连接符+连接两个字符串常量时,系统会自动将它们当成一个字符串常量,并将其存储在常量池中
使用字符串连接符+字符串变量时,连接后的字符串存储在堆内存中
比较两个字符串的内容是否相同使用equals方法 

所有引用类型使用双等号==比较时,比较的是对象地址是否相同,即是否是同一对象


以下内容初学者选读
//类A的源码public class A{String s = "abc" + "d";}
//打开字节码文件的命令:javap -verbose A//以下是类A编译后class文件的内容//关键行#2和5: ldc,可以看到Java编译器是将"abc" + "d"当做"abcd"来处理的Classfile /H:/A.class  Last modified 2015-5-29; size 239 bytes  MD5 checksum 271095a9d37f742c9bdefa883c6b9a00  Compiled from "A.java"public class A  minor version: 0  major version: 52  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #5.#14         // java/lang/Object."<init>":()V   #2 = String             #15            // abcd   #3 = Fieldref           #4.#16         // A.s:Ljava/lang/String;   #4 = Class              #17            // A   #5 = Class              #18            // java/lang/Object   #6 = Utf8               s   #7 = Utf8               Ljava/lang/String;   #8 = Utf8               <init>   #9 = Utf8               ()V  #10 = Utf8               Code  #11 = Utf8               LineNumberTable  #12 = Utf8               SourceFile  #13 = Utf8               A.java  #14 = NameAndType        #8:#9          // "<init>":()V  #15 = Utf8               abcd  #16 = NameAndType        #6:#7          // s:Ljava/lang/String;  #17 = Utf8               A  #18 = Utf8               java/lang/Object{  java.lang.String s;    descriptor: Ljava/lang/String;    flags:  public A();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=2, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method java/lang/Object."<init>":()V         4: aload_0         5: ldc           #2                  // String abcd         7: putfield      #3                  // Field s:Ljava/lang/String;        10: return      LineNumberTable:        line 1: 0        line 2: 4}SourceFile: "A.java"

//类B源码public class B{String s = "abc";String s1 = s+"d";}
//类B的class文件//首先看#2和#7,这里不在是当做一个字符串来处理的了//然后看5: ldc和25: ldc,这两行是将两个字符串常量压栈//11: new,这里创建了一个StringBuilder类的对象//22: invokevirtual和27: invokevirtual调用了StringBuilder对象的append方法,将两个字符串追加到一起//最后30: invokevirtual,调用了StringBuilder对象的toString方法,获得连接后的字符串"abcd"Classfile /H:/B.class  Last modified 2015-5-29; size 443 bytes  MD5 checksum 3eaa63a1c104ccfe26e2a6f9df85d93c  Compiled from "B.java"public class B  minor version: 0  major version: 52  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #11.#21        // java/lang/Object."<init>":()V   #2 = String             #22            // abc   #3 = Fieldref           #10.#23        // B.s:Ljava/lang/String;   #4 = Class              #24            // java/lang/StringBuilder   #5 = Methodref          #4.#21         // java/lang/StringBuilder."<init>":()V   #6 = Methodref          #4.#25         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   #7 = String             #26            // d   #8 = Methodref          #4.#27         // java/lang/StringBuilder.toString:()Ljava/lang/String;   #9 = Fieldref           #10.#28        // B.s1:Ljava/lang/String;  #10 = Class              #29            // B  #11 = Class              #30            // java/lang/Object  #12 = Utf8               s  #13 = Utf8               Ljava/lang/String;  #14 = Utf8               s1  #15 = Utf8               <init>  #16 = Utf8               ()V  #17 = Utf8               Code  #18 = Utf8               LineNumberTable  #19 = Utf8               SourceFile  #20 = Utf8               B.java  #21 = NameAndType        #15:#16        // "<init>":()V  #22 = Utf8               abc  #23 = NameAndType        #12:#13        // s:Ljava/lang/String;  #24 = Utf8               java/lang/StringBuilder  #25 = NameAndType        #31:#32        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;  #26 = Utf8               d  #27 = NameAndType        #33:#34        // toString:()Ljava/lang/String;  #28 = NameAndType        #14:#13        // s1:Ljava/lang/String;  #29 = Utf8               B  #30 = Utf8               java/lang/Object  #31 = Utf8               append  #32 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;  #33 = Utf8               toString  #34 = Utf8               ()Ljava/lang/String;{  java.lang.String s;    descriptor: Ljava/lang/String;    flags:  java.lang.String s1;    descriptor: Ljava/lang/String;    flags:  public B();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=3, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method java/lang/Object."<init>":()V         4: aload_0         5: ldc           #2                  // String abc         7: putfield      #3                  // Field s:Ljava/lang/String;        10: aload_0        11: new           #4                  // class java/lang/StringBuilder        14: dup        15: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V        18: aload_0        19: getfield      #3                  // Field s:Ljava/lang/String;        22: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        25: ldc           #7                  // String d        27: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        30: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;        33: putfield      #9                  // Field s1:Ljava/lang/String;        36: return      LineNumberTable:        line 1: 0        line 2: 4        line 3: 10}SourceFile: "B.java"

//类C源码public class C{String s = new String("abc");String s1 = s+"d";}
//C.class文件内容//这里主要演示类B中String s = "abc";和类C中String s = new String("abc");的区别//首先5: new 这里创建了一个String对象//然后9: ldc 字符串常量"abc"被压栈//最后11: invokespecial 初始化String对象//而类B只有ldc将常量压栈这一步Classfile /H:/C.class  Last modified 2015-5-29; size 506 bytes  MD5 checksum 97026d45729fe35e1f470e17e1b5f0e0  Compiled from "C.java"public class C  minor version: 0  major version: 52  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #13.#23        // java/lang/Object."<init>":()V   #2 = Class              #24            // java/lang/String   #3 = String             #25            // abc   #4 = Methodref          #2.#26         // java/lang/String."<init>":(Ljava/lang/String;)V   #5 = Fieldref           #12.#27        // C.s:Ljava/lang/String;   #6 = Class              #28            // java/lang/StringBuilder   #7 = Methodref          #6.#23         // java/lang/StringBuilder."<init>":()V   #8 = Methodref          #6.#29         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   #9 = String             #30            // d  #10 = Methodref          #6.#31         // java/lang/StringBuilder.toString:()Ljava/lang/String;  #11 = Fieldref           #12.#32        // C.s1:Ljava/lang/String;  #12 = Class              #33            // C  #13 = Class              #34            // java/lang/Object  #14 = Utf8               s  #15 = Utf8               Ljava/lang/String;  #16 = Utf8               s1  #17 = Utf8               <init>  #18 = Utf8               ()V  #19 = Utf8               Code  #20 = Utf8               LineNumberTable  #21 = Utf8               SourceFile  #22 = Utf8               C.java  #23 = NameAndType        #17:#18        // "<init>":()V  #24 = Utf8               java/lang/String  #25 = Utf8               abc  #26 = NameAndType        #17:#35        // "<init>":(Ljava/lang/String;)V  #27 = NameAndType        #14:#15        // s:Ljava/lang/String;  #28 = Utf8               java/lang/StringBuilder  #29 = NameAndType        #36:#37        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;  #30 = Utf8               d  #31 = NameAndType        #38:#39        // toString:()Ljava/lang/String;  #32 = NameAndType        #16:#15        // s1:Ljava/lang/String;  #33 = Utf8               C  #34 = Utf8               java/lang/Object  #35 = Utf8               (Ljava/lang/String;)V  #36 = Utf8               append  #37 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;  #38 = Utf8               toString  #39 = Utf8               ()Ljava/lang/String;{  java.lang.String s;    descriptor: Ljava/lang/String;    flags:  java.lang.String s1;    descriptor: Ljava/lang/String;    flags:  public C();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=4, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method java/lang/Object."<init>":()V         4: aload_0         5: new           #2                  // class java/lang/String         8: dup         9: ldc           #3                  // String abc        11: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V        14: putfield      #5                  // Field s:Ljava/lang/String;        17: aload_0        18: new           #6                  // class java/lang/StringBuilder        21: dup        22: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V        25: aload_0        26: getfield      #5                  // Field s:Ljava/lang/String;        29: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        32: ldc           #9                  // String d        34: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;        37: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;        40: putfield      #11                 // Field s1:Ljava/lang/String;        43: return      LineNumberTable:        line 1: 0        line 2: 4        line 3: 17}SourceFile: "C.java"


0 0
原创粉丝点击