龙空技术网

谈谈你对String对象的了解

强函数 81

前言:

目前同学们对“string创建的对象在哪里”都比较着重,小伙伴们都需要了解一些“string创建的对象在哪里”的相关知识。那么小编在网上汇集了一些有关“string创建的对象在哪里””的相关知识,希望兄弟们能喜欢,看官们快快来学习一下吧!

在Java编程中字符串应用最广泛,Java提供了String类创建和操作字符串。String的值是不可变的,这就导致了String每次操作字符串对象都会生成新的对象,这样就会导致效率低下,而且大量浪费珍贵且有限的内存空间。

String是被final修饰的类,不能被继承,不能被修改;String实现了Serializable和Comparable 接口,表示String支持序列化和可以比较大小;String底层是通过char类型的数据实现的,如下图String类源码:

String类是不可变类,一旦创建一个String对象,包含在这个对象中字符序列是不可改变的,直到这个对象被销毁。

举个列子来看一下内存空间有什么变化:

		// 通过直接赋值的形式进行实例化		String name = "乔峰";		name = "虚竹";		// 输出结果:虚竹		System.out.println(name);				// 通过构造方法实例化String类对象		String username = new String("段誉");		// 输出结果:段誉		System.out.println(username);

来StringTest.class看一下源码:

public class com.saq.day01.main.StringTest  minor version: 0  major version: 49  flags: (0x0021) ACC_PUBLIC, ACC_SUPER  this_class: #1                          // com/saq/day01/main/StringTest  super_class: #3                         // java/lang/Object  interfaces: 0, fields: 0, methods: 2, attributes: 1Constant pool:   #1 = Class              #2             // com/saq/day01/main/StringTest   #2 = Utf8               com/saq/day01/main/StringTest   #3 = Class              #4             // java/lang/Object   #4 = Utf8               java/lang/Object   #5 = Utf8               <init>   #6 = Utf8               ()V   #7 = Utf8               Code   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V   #9 = NameAndType        #5:#6          // "<init>":()V  #10 = Utf8               LineNumberTable  #11 = Utf8               LocalVariableTable  #12 = Utf8               this  #13 = Utf8               Lcom/saq/day01/main/StringTest;  #14 = Utf8               main  #15 = Utf8               ([Ljava/lang/String;)V  #16 = String             #17            // 乔峰  #17 = Utf8               乔峰  #18 = String             #19            // 虚竹  #19 = Utf8               虚竹  #20 = Fieldref           #21.#23        // java/lang/System.out:Ljava/io/PrintStream;  #21 = Class              #22            // java/lang/System  #22 = Utf8               java/lang/System  #23 = NameAndType        #24:#25        // out:Ljava/io/PrintStream;  #24 = Utf8               out  #25 = Utf8               Ljava/io/PrintStream;  #26 = Methodref          #27.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V  #27 = Class              #28            // java/io/PrintStream  #28 = Utf8               java/io/PrintStream  #29 = NameAndType        #30:#31        // println:(Ljava/lang/String;)V  #30 = Utf8               println  #31 = Utf8               (Ljava/lang/String;)V  #32 = Class              #33            // java/lang/String  #33 = Utf8               java/lang/String  #34 = String             #35            // 段誉  #35 = Utf8               段誉  #36 = Methodref          #32.#37        // java/lang/String."<init>":(Ljava/lang/String;)V  #37 = NameAndType        #5:#31         // "<init>":(Ljava/lang/String;)V  #38 = Utf8               args  #39 = Utf8               [Ljava/lang/String;  #40 = Utf8               name  #41 = Utf8               Ljava/lang/String;  #42 = Utf8               username  #43 = Utf8               SourceFile  #44 = Utf8               StringTest.java{  public com.saq.day01.main.StringTest();    descriptor: ()V    flags: (0x0001) ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: invokespecial #8                  // Method java/lang/Object."<init>":()V         4: return      LineNumberTable:        line 8: 0      LocalVariableTable:        Start  Length  Slot  Name   Signature            0       5     0  this   Lcom/saq/day01/main/StringTest;  public static void main(java.lang.String[]);    descriptor: ([Ljava/lang/String;)V    flags: (0x0009) ACC_PUBLIC, ACC_STATIC    Code:      stack=3, locals=3, args_size=1         0: ldc           #16                 // String 乔峰         2: astore_1         3: ldc           #18                 // String 虚竹         5: astore_1         6: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;         9: aload_1        10: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V        13: new           #32                 // class java/lang/String        16: dup        17: ldc           #34                 // String 段誉        19: invokespecial #36                 // Method java/lang/String."<init>":(Ljava/lang/String;)V        22: astore_2        23: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;        26: aload_2        27: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V        30: return      LineNumberTable:        line 10: 0        line 11: 3        line 13: 6        line 15: 13        line 17: 23        line 18: 30      LocalVariableTable:        Start  Length  Slot  Name   Signature            0      31     0  args   [Ljava/lang/String;            3      28     1  name   Ljava/lang/String;           23       8     2 username   Ljava/lang/String;}  

从文件中可以看出字符串常量池(Constant pool)有两个对象。可以看出,再次给name对象赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“虚竹”这个字符串,name则指向新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。

String类对象实例化的方式有两种:

1.通过直接赋值的形式进行实例化

String name = "乔峰";

2.通过构造方法实例化String类对象

String name = new String("段誉");

两种实例化String类对象虽然结果一样,但是本质上有很多区别,通过直接赋值的方式为字符串赋值时,此时的字符串存储在方法区的字符串常量池中;

通过构造器方式实例化字符串时,字符串对象存储在堆中,但是字符串的值仍然存储在方法区的常量池中。

标签: #string创建的对象在哪里