我理解的Java栈与堆,String类
无意间在CSDN上看到一篇说栈与堆的文章,欣然取之,后来发现里面有些东西确实还有待推敲。
再看看评论,看到了高手的详解。我整合了一下,加上自己的理解,现在贴上来,希望多多赐教。
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
3. Java中的数据类型有两种。
一种是基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。
如int a = 3;
直接在栈中把3这个字面值交给a。由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
但有特殊情况:
Integer a = 3;
Integer b = 3;
System.out.println(a==b); //打印结果是true
但是,如果 Integer a = 266;Integer b = 266;System.out.println(a==b) ///这样就是false了
原因:
Integer i = 3;
sun的编译器是这样处理的:
Integer i=Integer.valueOf(3);
而不是通过new来创建了,因为Integer类中静态的创建了-128~+127之间的对象,需要的数在这个范围之内时,直接返回,此范围之外的数才通过new来创建.
这里:要插入一点我对"=="号和"equals"的理解。
对于==,假如是a==b 那么,它是直接比较a与b里面的内容。
而对于equals:它是比较a与b所真实代表的值,是否相等。
4. String是一个特殊的类。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建。
对于new的形式,大家应该想法都比较一致,它是在堆中开一片内存。只要见到new,就一定是在堆中开辟了空间。另外要注意,如果是一个类,它里面有基本类型,则基本类型也放在堆中。
着重说一下对于:String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
如果不用new的形式,则我们要分析的空间不再是堆,而是数据区了。在JVM中,一共分为四个部分:堆,栈,数据区,代码区。
首先呢,它应该在栈中开辟一个空间,名字就是str了。然后,java会到数据区中找值为abc的字符串,如果找到了,则把它的地址赋给栈中的已开辟空间的值。否则,它会先在数据区中开辟一块内存,值为abc,然后,再把它的地址赋给str.
为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。
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
str3这个对象的引用直接指向str1所指向的对象(注意,str3并没有创建新对象)。当str1改完其值后,再创建一个String的引用str4,并指向因str1修改值而创建的新的对象。可以发现,这回str4也没有创建新的对象,从而再次实现栈中数据的共享。
我们再接着看以下的代码。
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()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
5. 结论与建议:
(1)我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。
(2)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。
(3) java新增了StringBuilder来处理可变字符串,如果不需要多线程环境,应该首先选择这个。
我理解的Java栈与堆,String类相关推荐
- Java本质论之关于Java栈与堆的思考
来源:[http://www.csdn/1/2/3.com/html/20130308/83/80aa062b7f1f5537e075fa8893d4f189.htm] Java本质论之关于Java栈 ...
- Java里的字符串, String类简单介绍.
String类在java面试中也是1个常见的问题点. 所以也是写在这里方便以后查阅了. 大家都知道c语言里是没有String 字符串这个数据类型的. 只能用字符数组的1个特殊形式来表示一个字符串, 就 ...
- 关于Java栈与堆的思考
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度比堆要快,仅次于直接位于C ...
- java栈与堆_JAVA中的栈和堆
JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方法区.3:方法区.4:栈.5:堆. 基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了. ...
- java栈与堆的区别
栈与堆都是Java用来在RAM中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newar ...
- java栈、堆、方法区
1.java中的栈(stack)和堆(heap)是java在内存(ram)中存放数据的地方 2.堆区 存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令) ...
- java栈和堆的区别_java 栈 和 堆 的区别
转载: 一.java栈 Java 栈总是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的Java栈,在这个Java栈中又会含有多个栈(Frames),这些栈帧是与每个方法关联起 ...
- Java基本数据类型及String类
基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型.它们是我们编程中使用最频繁的类型.java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化. 一. Java ...
- java问题解读,String类为什么是final的
一.理解final 望文生义,final意为"最终的,最后的",我理解为"不能被改变的",它可以修饰类.变量和方法. 所以我是否可以理解为被它所修饰的类.变量和 ...
最新文章
- UNet为什么在医学图像分割表现好?
- python 条件选择语句_Python趣味入门4:选择往往是最重要的-条件语句
- 如何获得Oracle系统性能统计? Oracle大型数据库系统在AIXUNIX上的实战详解 集中讨...
- 电网电压波形是否失真?
- oracle添加分区语句_按照子分区模板添加子分区
- 萤石云 服务器错误 10017
- 单例设计模式详解+源代码+JDK源码应用——Java设计模式系列学习笔记
- Ubuntu18.04 LTS 安装nvidia驱动出现Ignoring CC version mismatch
- MapReduce 支持的部分数据挖掘算法
- strike F1 to retry boot,F2 for setup utility
- 英世曼 | 动量是否具有行为性?
- Adobe Originals的可变字体
- C# 实现国密SM4加解密封装
- java两级缓存框架J2cache
- C语言程序设计-班级档案管理系统
- VR MultiPass\SinglePass(Instanced)\MultiView 浅析和区分总结
- 今天开始学Java 如果统计的个数相同,则按照ASII码由小到大排序输出 。
- 解决VSTO EXCEL 设置合并单元格锁定时报错问题
- 脏话越多,代码越好!
- RHCA-RH436 V1.1.12-PCS集群
热门文章
- leetcode oj java Bulls and Cows
- 【课程汇总】OpenHarmony 成长计划知识赋能第三期系列课程(附链接)
- Ubuntu16.04安装youtub_dl
- c#截屏木马,发送到邮箱
- 用于2D动画的实时嘴型同步技术
- 【基于python+Django的物品协同过滤音乐推荐系统-哔哩哔哩】 https://b23.tv/V2zN54R
- 基于Java Web技术的动车购票系统
- node-addon-api 的简单使用,c++数值、字符串、对象、数组转化为js可用数据。
- python画图颜色设置_python画图--输出指定像素点的颜色值方法
- js 公历日期转农历带节假日