I学霸官方免费教程十九:Java常用类之String类
2015-08-11 17:44
441 查看
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_SUPER Constant 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_SUPER Constant 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_SUPER Constant 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"
版权声明:本文为博主原创文章,未经博主允许不得转载。
相关文章推荐
- java要在命令行运行eclipse的项目的方法
- 将Map转换为Java 对象
- JDK API下载
- myeclipse错误处理
- [leetcode-113]Path Sum II(java)
- 在JAVA中线程到底起到什么作用
- Java基础-ArrayList中ConcurrentModificationException错误解决
- java虚拟机原理图解1
- JAVA并发编程学习笔记之CAS操作
- Java单例设计模式
- java书籍
- 【Java代码保护技术】代码混淆
- 如何通过MyEclipse生成含有第三方包的jar包
- springMVC 【@response 返回对象自动变成json并且防止乱码】 & 【配置支持实体类中的@DateTimeFormat注解】
- jdk自带的jvm监控工具
- 字符串分割--java中String.split()用法
- 字符串排序问题
- eclipse的WEB项目无理由错误
- JAVA,Play framework 入门,打印hello word
- eclipse Android关联源码