笔试题总结——String类的两种实例化方式

笔试题总结——String类的两种实例化方式

  首先看String类的实例化方式
   直接赋值,在上分配空间存储字符串,在上存储引用变量,只有String可以直接赋值进行实例化,其他类必须new一个对象出来才能完成实例化。
	String str = "hello";
   构造方法:通过new 构造方法()实例化String对象。
	String str = new String("hello");
  除了会使用String类的两种实例化方式,最重要的是要知道这两种方式背后所对应的细节,这些细节多出现在笔试题中。
  另外多说一点,像"hello" 这样的字符串字面值常量, 类型也是 String。(其本质上就是将⼀个匿名的String类对象,且匿名对象⼀定保存在堆内存中)
  1、直接赋值法实例化String对象:
   String类的设计使⽤了共享设计模式,JVM底层会自动维护一个字符串的对象池(对象数组)。

  如果采用直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.
  如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容直接进行引用
  如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用

   String中的"=="比较的不是字符串的内容,而是比较两个引用是否指向同一个对象,而此时由于"对象池"的存在,使得两次直接赋值若内容相同则会指向同一字符串对象。如果代码中有多个地方引用(采用直接赋值法)都需要使用 “hello” 的话, 就直接引用到常量池的这个位置就行了, 而没必要把 “hello” 在内存中存储两次,举个栗子:
	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	
   str1在堆内存上创建新的String对象,由于是直接赋值的方式,该String对象被加入JVM的"对象池"中,而后str2,str3再通过直接赋值的方式访问相同的字符串对象"hello",访问到的都是"对象池"中由str1创建的那个String对象,此时三个引用指向的是同一个String对象,因此"=="的结果都为true。背后的过程如下图:

在这里插入图片描述

  2、传统构造方法实例化String对象:
	String str = new String("hello");
   由于"hello"(字符串字面值常量/String的匿名对象)也是一个String对象,因此,JVM会现在堆上创建一个"hello"字符串,再将这个字符串复制一份并由str指向,这就导致出现了垃圾空间(匿名String对象"hello"),并且如果采用构造方法的话,也不会将该字符串对象加入到JVM的"字符串常量池"中,导致字符串共享问题。

   如果使用String构造方法就会开辟两块堆内存空间,并且其中一块堆内存将成为垃圾空间(字符串常量 "hello"也是一个匿名对象, 用了一次之后就不再使用了, 就成为垃圾空间, 会被 JVM 自动回收)
  字符串共享问题. 同一个字符串可能会被存储多次, 比较浪费空间。
在这里插入图片描述

   为了解决"字符串共享"问题,可以使用String类的intern方法将以构造方法方式创建的String对象手动加入到"字符串常量池"中。(采用构造方法方式实例化时默认不会将该String对象入池)
	//	使用intern()手动入池前后的区别
	String str1 = new String("hello") ;
	String str2 = "hello" ;
	System.out.println(str1 == str2);

	// 执行结果
	false
	
	String str1 = new String("hello").intern() ;
	String str2 = "hello" ;
	System.out.println(str1 == str2);
	
	// 执行结果
	true
	
   此时背后所做的处理应该如下图:

在这里插入图片描述

  最后说一下两种对象实例化的区别
   1、直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
   2、构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,默认不会自动保存在对象池中,可以使用intern()方法手工入池。

  总结,使用构造方法实例化对象,即便是使用了intern()方法手动入池,但仍无法解决垃圾空间的问题,因此,一般采用直接赋值的方式创建String对象。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值