Java String类实例化方式以及入池操作

 String类型是java中一种很重要的数据类型,但实际上,String是一个类,位于java.lang包下,定义如下:

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

 java.lang包存放着系统常用的基础类,例如String,Object等,JDK1.1之后自动导入,所以我们在创建字符串的时候不需要import依赖包。

 String类实现了Serializable接口,可以进行序列化和反序列化。而且也实现了Comparable接口,并且覆写了compareTo方法。CharSequence接口定义了字符序列相关的信息。

1. 实例化方式

 String有两种实例化方式,一种是直接赋值,另一种是使用String类的构造方法进行实例化。

直接赋值
String str = "Hello World" ; 

 在任何的语言的底层,都不会提供有直接的字符串类型。字符串类型只是高级语言提供给用户方便开发的支持而已。

 在java之中,本身也没有直接提供字符串类型的概念,java本身提供的只有八大基本数据类型,而所有使用双引号 ” “定义的字符串本质上来讲都是String的匿名对象。

 所以,String通过直接赋值所创建的字符串就是在堆上的一个String匿名对象。

构造方法构造:
String str = new String("Hello World");

 虽然使用构造方法创建对象是最标准的创建方式,但是字符串创建一般推荐使用第一种方式。

2. 两种实例化的区别

 String类的设计使用了共享设计模式。在JVM底层实际上会自动维护一个对象池(字符串对象池),如果现在采用了直接赋值的方式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。所谓的对象池就是一个对象数组(目的就是减少开销)。

 == 操作符两端为数字时,比较的是它们的值,如果是对象,比较的是它们的地址。那么用其进行String直接赋值的验证,如下:

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true

 流程图如下:

流程图

 但是,如果使用构造方法进行String的创建,那么每次new一次,就会直接在堆上创建新的字符串对象,而不会从池中获取,看下面的语句:

String str = new String("hello") ;

 上面的过程实际上开辟了两个字符串空间,首先是括号内的”hello”字符串,因为所有双引号引起的字符串都是String的匿名对象,然后是通过其new出来的新字符串,这两者内容一样,但是不是同一片空间,而且,str指向第二块空间,第一块字符串空间没有指向,称为垃圾空间,如下图所示:

流程

 另外,new出来的字符串是不会入池的,但是我们可以采用String提供的实例方法intern()将字符串进行入池操作。

 综上,可以看出两种方式的区别:

方式特点
直接赋值只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
构造方法会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中,可以使用intern()方法手工入池。

 推荐使用第一种,效率高而且语法简单。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值