课时44:String类对象两种实例化方式比较

简介: 本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。1.直接赋值的对象化模式2.字符串池的概念3.构造方法实例化

课时44:String类对象两种实例化方式比较

 

摘要:本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。

1. 直接赋值的对象化模式

2. 字符串池的概念

3. 构造方法实例化

 

现在已经清楚String类对象实例化过程之中,提供有我们的两种的处理模式。现在需要区分这两种处理模式到底该使用哪种会更好?我们从直观的角度上观察到,用直接赋值感觉会更好,那么除此之外,这两种模式还有哪些的差别所在?

 

01. 直接赋值的对象化模式

 

我们分析直接赋值的对象实例化模式。我们知道在我们的程序之中,只需要将一个字符串赋值给String类的对象,可以实现对象的实例化处理。现在假设只有如下一行代码:

public class StringDemo {
public static void main(String args[]) {
String str = "mldn"
}
}

这种情况下只是开辟出一块堆内存空间,此时的内存关系图如下。整个操作的程序代码之中,只会开辟有一块内存和一块栈内存空间。

image.png

除了这种内存模式之外,利用直接赋值实例化String的形式还可以实现同一个字符串对象数据的共享操作。现在观察String直接赋值时的数据共享,现在给出下面的代码:

public class StringDemo{
public static void main(string args[]){
String strA="mldn"String 
strB ="mldn"
System.out.println(strA=strB); //地址判断
}
}

这段代码描述的是地址判断,判断两个对象的地址相同,意味着这两个对象是同一个对象。现在来执行一下程序,结果如下图。

image.png

程序的判断结果返回了true,我们可以得出结论这两个对象所指向的堆内存是同一个。这个时候的内存关系如图所示

image.png

从整个程序代码而言,此时确实实现了数据共享那为什么可以共享呢?

之所以现在会有这样的一个叫的特点,主要的原因是因为在java 程序的底层里面提供有一个专门的字符串池字符串数组


既然是数组,数组的内容都是一个具体的数据。我们把程序的流程重新画在内存关系图上,当我们第一次把数据放的时候,数组有一个自己的维护过程,但是默认情况下,值全都是Null。


当我们第一次存一个字符串,里面有“mldn,那么这个时候 StrA指向的是“mldn”所在的池。当后面再有一个 StrB 的时候,它首先会查找池,如果池中有数据,那么这个时候会引用池中的数据,如果池中没有数据,它会放置一个新的字符串。

image.png

 

02. 字符串池的概念

 

我们分析一下字符串池的概念。下面以如下代码为例:

Class StringDemo{
public static void main(string args[]){
String strA="mldn";
String strB="mldnjava";
String strC="mldn"
System.out.println(strA=strB); //地址判断
}
}

现在分析代码程序运行过程,首先String strA="mldn"首先会发现了池中没有数据它要保存一个新的数据

image.png

当运行第二句代码String strB="mldnjava"时,池中仍然没有数据,那么既然池中没有数据,则这个程序的代码就要在池中再开一个空间存放"mldnjava"

image.png

当我们在执行第三句String strC="mldn"代码的时候,此时池中有数据,所以它不会开辟新的空间,它会指向池中的"mldn"

image.png

所以说之所以能有这样的一个主要的特征,是因为在整个直接赋值的过程之中,对于字符串而言,可以实现池数据的自动保存,这样如果再有相同数据定义时,可以减少对象的产生以提升操作性能。这就是第一种字符串池的概念的理解。

 

03. 构造方法实例化


构造方法进行的对象实例化,可以说是我们进行对象定义时的一种常见做法。之后String类为了满足于设计的结构要求,也提供有构造方法识别化的做法。下面以如下代码举例:

Class StringDemo{
public static void main(string args[]){
String str = new string("mldn");
}
}

那么此时,对于本程序而言。我们可以通过内存关系图进行观察。首先这个程序,按照刚才所说,第一点字符串是什么?一定要清楚,首先我们在整个过程中重点强调了字符串是一个匿名对象。我们认为在匿名对象只占据堆内存空间,那它应该会开辟堆内存。那么如果说现在要以匿名对象的形式要进行开辟,但是这个开辟的结果并不是我们要的,而是new


我们最终结果所要的东西是关键字 new 所带来的对象在这样的情况下,真正开辟的空间是关键字的 new 而关键性的问题是两个的内容一样的STR 指向的是new。此时会产生两块内存空间,能够明显的发现有一块内存空间就将成为垃圾空间。

image.png

这就是关键字 new 所带来的使用特征,那么这样的话,我们可以发现,如果以现在的程序为例,直接赋值要比关键字 new 开辟更加节约空间。此时会开辟两块堆内存空间,而后我们只会使用一块,而另外一个由于字符串的常量所定义的匿名对象将成为我们的垃圾空间。但是如果现在更换一种形式,代码如下:

Class StringDemo{
public static void main(string args[]){
String strA = "mldn";
String strB = new string("mldn");
}
}

按照上述代码,下面分析String内存分析。字符串池也是堆内存,当我们执行String strA = "mldn"的时候,他要开辟一个字符串常量保存在池之中,直接赋值的最大特征在于可以自动将对象保存到字符对象池之中,这是进行直接赋值操作的一个最主要的是特征。

image.png

当再运行String strB = new string("mldn")代码时,这个字符串是否有对应的一块堆内存空间?这个对象是匿名对象,这个对象在池中一定会有,因为此时 STRA 指向着这个内容,那么此时会引用池中对象。STRB 在整个过程中开辟自己的堆内存空间,在堆内存中开辟新的字符串对象,而另外一个它是可以实现对象的重用。

image.png

除了上述特点之外,使用构造方法实例化String类对象时,不会自动出现入保存到字符串池的处理,我们观察构造方法实例化对象时的实操作。此时代码如下:

Class StringDemo{
public static void main(string args[]){
String strA = "mldn";
String strB = new string("mldn");
System.out.println(strA=strB); //地址判断
}
}

上述代码要判断地址相同,如果地址相同,就意味着 STRB 所指向的空间已经入池了但是事实上,我们经过刚才的分析没有入池现在编译运行代码查看结果。

image.png

这个操作是不会自动入池,它是属于一个自己专用的空间。可以发现构造方法实例化的对象是属于一种自己专用的内存空间有些时候在String里面也提供有帮助开发者实现手工入池的处理情况。这个方法是:public String intern(),下面观察手工入池,代码如下:

Class StringDemo{
public static void main(string args[]){
String strA = "mldn";
String strB = new string("mldn").intern();
System.out.println(strA=strB); //地址判断
}
}

此时编译运行代码查看结果如图所示。结果为ture,意味着这个对象的处理过程现在实现了入池,它也占了池中的引用,加入intern()之后在使用构造方法定义对象之后由于使用intern()的方法即便使用了构造出来的String类对象的内容也可以实现入对象池的统一管理,但这种方法太麻烦。

image.png

若有以下面试题:请解释String类两种对象实例化方式的区别?

1. 直接赋值:只会产生一个实例化对象,可以自动保存到对象池之中,以实现字符串实例的重用。

2. 构造方法:会产生两个实例化对象,不会自动入池,无法实现对象重用。

但是可以利用intern()的方法进行手工入池处理这个就是String类两种对象的使用方式,当然最终结果可以发现以后不要用 new 直接赋值是最稳妥的方式

相关文章
|
1月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
64 11
|
1月前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、"+"操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
|
1月前
|
Java 开发者
课时45:String对象常量池
本次课程的主要讨论了对象池的概念及其在Java开发中的应用。首先,介绍了静态常量池和运行时常量池的区别。讨论了静态常量池和运行时常量池在实际开发中的作用,以及如何理解和应用这些概念。 1.常量池的分类 2.静态常量池和运行时常量池的区别
|
1月前
|
Java 程序员
课时16:String字符串
课时16介绍了Java中的String字符串。在Java中,字符串使用`String`类表示,并用双引号定义。例如:`String str = "Hello world!";`。字符串支持使用“+”进行连接操作,如`str += "world";`。需要注意的是,当“+”用于字符串与其他数据类型时,其他类型会先转换为字符串再进行连接。此外,字符串中可以使用转义字符(如`\t`、`\n`)进行特殊字符的处理。掌握这些基本概念对Java编程至关重要。
|
7月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
78 0
java基础(13)String类
|
5月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
165 2
|
6月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
125 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
7月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①
|
6月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
175 2
|
6月前
|
数据可视化 Java
让星星月亮告诉你,通过反射创建类的实例对象,并通过Unsafe theUnsafe来修改实例对象的私有的String类型的成员属性的值
本文介绍了如何使用 Unsafe 类通过反射机制修改对象的私有属性值。主要包括: 1. 获取 Unsafe 的 theUnsafe 属性:通过反射获取 Unsafe类的私有静态属性theUnsafe,并放开其访问权限,以便后续操作 2. 利用反射创建 User 类的实例对象:通过反射创建User类的实例对象,并定义预期值 3. 利用反射获取实例对象的name属性并修改:通过反射获取 User类实例对象的私有属性name,使用 Unsafe`的compareAndSwapObject方法直接在内存地址上修改属性值 核心代码展示了详细的步骤和逻辑,确保了对私有属性的修改不受 JVM 访问权限的限制
114 4