打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Java String类详解(一)

String类是一个字符串类型的类,使用“XXXX”定义的内容都是字符串,虽然这个类在使用上有一些特殊,但是String本身是一个类。

一、String的实例化两种方式

1、直接赋值实例化:

String StringName= 'xxx';
  • 1

以上是String对象的直接赋值,以上的代码并没有使用关键字new进行。String类也是类,所以也有构造方法。

2、使用构造方法实例化:

public String(String str);
  • 1

可以通过构造方法为String类对象实例化,但在构造里面依然要接收一个本类对象。

二、字符串的比较

如果要想知道两个int型变量是否相等,使用“==”进行验证,在String中也可以使用“==”来进行比较。我们来看一个例子:

public class StringDemo { public static void main(String args[]) { String str1 = 'Hello' ; String str2 = new String('Hello') ; String str3 = str2 ; // 引用传递 System.out.println(str1 == str2) ; System.out.println(str1 == str3) ; System.out.println(str2 == str3) ; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行结果:

falsefalsetrue
  • 1
  • 2
  • 3

发现使用“==”好象最终的判断结果是不一样的,为什么呢?下面通过内存关系图来分析:

通过以上分析可以发现,“==”比较的不是字符串对象包含的内容,而是两个对象所在的的内存对象的数值。所以“==”属于数值比较,比较的是内存地址

如果想比较字符串的内容,可以使用String类的equals()方法。

public class StringDemo { public static void main(String args[]) { String str1 = 'Hello' ; String str2 = new String('Hello') ; String str3 = str2 ; // 引用传递 System.out.println(str1.equals(str2)) ; System.out.println(str1.equals(str3)) ; System.out.println(str2.equals(str3)) ; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

运行结果:

truetruetrue
  • 1
  • 2
  • 3

于是,现在比较的不是字符串的内存地址的数值,而是字符串的内容。

小结:
(1) ==:比较的是两个字符串内存地址的数值是否相等,属于数值比较;
(2)equals():比较的是两个字符串的内容,属于内容比较。

三、字符串常量是匿名对象

在各个语言中并没有提供字符串的数据类型定义,很多语言都是使用字符数组来描述字符串的概念,在Java中也没有字符串的概念,只是Java自己做了简单处理。但是在Java中字符串依然不属于基本数据类型,字符串是作为String类的匿名对象的形式存在的。

字符串是匿名对象的验证:

public class StringDemo { public static void main(String args[]) { String str = 'Hello' ; // 通过字符串调用方法 System.out.println('Hello'.equals(str)) ; }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

运行结果:

true
  • 1

匿名对象可以调用类中的方法与属性,而以上的字符串调用了equals()方法,所以它一定是一个对象。

四、String类对象两种实例化方式的区别

String类对象存在两种实例化的操作形式,那么这两种有什么区别,在开发之中应该使用那一种更好呢?

1、直接赋值的实例化方式:

String str = 'Hello' ;
  • 1

此时,只分配了一块堆内存空间和一块栈内存空间:

再看一下代码:

public class StringDemo {         public static void main(String args[]) {                   String str1 = 'Hello' ;                   String str2 = 'Hello' ;                   String str3 = 'Hello' ;                   System.out.println(str1 == str2) ;                   System.out.println(str1 == str3) ;                   System.out.println(str2 == str3) ;         }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

运行结果:

truetruetrue
  • 1
  • 2
  • 3

我们发现以上所有直接赋值的String类对象的内存地址完全相同,内存分配图如下:

在设计String类的时候采用了一种称为共享设计模式的概念。在运行的JVM底层存在一个字符串的对象池(Object Pool),如果用户采用了直接赋值的方式时,会将字符串的内容放入池保存,如果以后其他String对象继续使用直接赋值方式实例化,并且设置了同样的内容时,那么将不会分配新的堆内存空间,而是使用已有对象的引用进行分配继续使用。如果新声明的字符串内容不在对象池中,则会分配一个新的,然后继续放到池中以供下次使用。

2、采用构造方法实例化的方式:

使用构造方法实例化一定要用到new关键字,而一旦使用了new就表示要分配新的内存空间。

 String str = new String('Hello') ;
  • 1

内存分配图如下:

从上可以发现,分配了两块堆内存空间,其中一块是垃圾。这样处理内存的浪费外,使用构造方法定义的String类对象,其内容不会保存在对象中(因为重新分配了新的一块堆内存)。

现在希望使用构造方法定义的String类对象,其内容要保存在对象中,该怎么办么?我们可以使用String类定义的一个手工入池的方法:

public String intern()
  • 1

范例如下:

public class StringDemo {         public static void main(String args[]) {                   String str1 = new String('Hello').intern() ;                   String str2 = 'Hello' ;  // 入池                   String str3 = 'Hello' ;  // 使用池对象                   System.out.println(str1 == str2) ;                   System.out.println(str1 == str3) ;                   System.out.println(str2 == str3) ;         }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行结果:

truetruetrue
  • 1
  • 2
  • 3

小结:String类对象两种实例化的区别?
(1)直接赋值实例化方式(String str = “xxx”):只会分配一块堆内存空间,并且对象内容自动入池,以供重复使用;
(2)构造方法实例化方式(String str = new String(“xxx”)):会分配两块堆内存空间,其中有一块是垃圾,并且不会自动入池,用户可以使用intern()方法手动入池。

五、字符串的内容一旦定义则不可改变

先看一段代码:

public class StringDemo {         public static void main(String args[]) {                   String str = 'Hello ' ;                   str += 'World ' ;                   str = str + '!!!' ;                   System.out.println(str) ;         }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

运行结果:

Hello World !!!
  • 1

我们通过内存分配图分析一下:

通过以上的分析可以发现:字符串内容的更改,实际上改变的是字符串对象的引用过程,并且会伴随有大量的垃圾出现,在实际开发中应该避免。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
JVM: JVM 内存划分
java内存管理机制
java的堆栈机制与String对象
java中String str=""与new String()的区别
Java基础知识面试题大集合
Java 基础知识面试题大集合
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服