堆与栈(JAVA)——以String str="abc"的深度含义解释
int a=3;
int b=3;
编译器先处理int a= 3;首先它会在栈中创建一个变量为a的内存空间,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b= 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。
String str1="abc";
String str2="abc";
System.out.println(str1==str2);//true
注意,我们这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。
结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。
String str1="abc";
String str2="abc";
str1="bcd";
System.out.println(str1+","+str2);//bcd,abc
System.out.println(str1==str2);//false
这就是说,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为"bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。事实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
再修改原来代码:
String str1="abc";
String str2="abc";
str1="bcd";
String str3=str1;
System.out.println(str3);//bcd
String str4="bcd";
System.out.println(str1==str4);//true
我们再接着看以下的代码。
String str1 = new String("abc");
String str2 = "abc";
System.out.println(str1==str2); //false
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2); //false
创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。
以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。
结论与建议:
(1) 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。
(2) 使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于Stringstr = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。
堆与栈(JAVA)——以String str="abc"的深度含义解释的更多相关文章
- 关于String str =new String("abc")和 String str = "abc"的比较
String是一个非常常用的类,应该深入的去了解String 如: String str =new String("abc") String str1 = "abc&qu ...
- java中String s="abc"及String s=new String("abc")详解
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度比堆要快,仅次于直 ...
- 关于String str =new String("abc")和 String str = "abc"的比较--转
原文地址:https://www.cnblogs.com/OnlyCT/p/5433410.html String是一个非常常用的类,应该深入的去了解String 如: String str =new ...
- Java中String str=new String("a")和String str = "a"有什么区别?
Q: String A="ABC"; String B=new String("ABC"); 这两个值,A,B 是否相等,如果都往HashSet里面放,能放下吗 ...
- String str="abc";和String str2=new String("abc");有什么区别?
- Java堆、栈和常量池以及相关String的详细讲解(经典中的经典) (转)
原文链接 : http://www.cnblogs.com/xiohao/p/4296088.html 一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的 ...
- Java堆、栈和常量池以及相关String的详细讲解
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
- Java堆、栈和常量池以及相关String详解
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
- Java堆、栈和常量池以及相关String的详细讲解(转)
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
随机推荐
- 事件和委托: 第 6 页 .Net Framework中的委托与事件
原文发布时间为:2008-11-01 -- 来源于本人的百度文章 [由搬家工具导入] .Net Framework中的委托与事件 尽管上面的范例很好地完成了我们想要完成的工作,但是我们不仅疑惑:为什么 ...
- UITextInputMode currentInputMode is deprecated. 警告的解决
如果你的工程最低支持版本为7.0 你会发现有警告 : 'currentInputMode' is deprecated: first deprecated in iOS 7.0 替换方案:UIText ...
- how-do-i-access-windows-event-viewer-log-data-from-java
https://stackoverflow.com/questions/310355/how-do-i-access-windows-event-viewer-log-data-from-java
- 09-js数组常用方法
<html> <head> <title>js数组的常用操作</title> <meta charset="UTF-8"/&g ...
- 转 asterisk拨号规则
asterisk拨号规则 一.前言 本文档以asterisk-1.4.32为基础写作而成,可能和其他版本有些区别. 二.Asterisk dialplan 基本结构 Asterisk dial ...
- ArcEngine影像图配准
转自原文ArcEngine影像图配准 影像图配准主要包括以下几个方面 1.打开影像图 2.配准 3.影像图入库/保存 1.打开影像图的代码以前已经写过了. 2.配准 配准 主要使用IGeoRefe ...
- guava缓存设置return null一直报错空指针
guava缓存设置return null一直报错空指针 因为缓存不允许返回为空
- json转xml报[java.lang.NoClassDefFoundError: nu/xom/Serializer]
原文:http://blog.csdn.net/figo645/article/details/48413571 开始学习JSON了,那么很自然的,我开始要熟悉一些基本的JSON语法 {}代表对象,[ ...
- Citrix XenServer
Citrix XenServer xenserver-test cpu特性码:77fafbff-bfebfbff-00000021-2c100800 xe snapshot-list xen还原快照 ...
- Android中AsyncTask使用具体解释
在Android中我们能够通过Thread+Handler实现多线程通信.一种经典的使用场景是:在新线程中进行耗时操作.当任务完毕后通过Handler向主线程发送Message.这样主线程的Handl ...