堆与栈
堆(heap)与栈 (stack) 都是java用来在Ram(random access memory 随机存储器)中存放数据的地方。
java中自动管理heap 和 stack,程序员不能直接设置。
stack : 都是虚拟机stack。
堆是一个运行时数据区,对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式地释放。堆是由垃圾回收来负责的.
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收 集器会自动收走这些不再使用的数据。
堆缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String、数组、对象等等)但不存放对象内容。
栈的优势是,存取速度比堆要快,仅次于寄存器,(不是寄存器)。栈数据可以共享。
缺点是,存在栈中的数据大小与生存期必须是 确定的,缺乏灵活性。
栈中主要存放一些基本类型的变量数据(int,short,long,byte,float,double,boolean,char)和对象引用。
引用在白皮书中直接指出是实际就是一个C的"指针"。
假设我们同时定义:
int a = 3; int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。
这时,如果再令 a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b,它是由编译器完成的,它有利于节省空间。
字符串
1. String不是基本数据类型,String是一个对象。因为对象的默认值是null,所以String的默认值也是null。它是一种特殊的对象,有其它对象没有的一些特性。
2. new String()和new String("")都是申明一个新的空字符串,是空串不是null。
3. String str="helloword"和String str=new String("helloword")的区别
示例:
String s0="helloword"; String s1="helloword"; String s2="hello" + "word"; System.out.println(s0==s1); System.out.println(s0==s2);
结果为:
true
true
因为例子中的s0和s1中的"word"都是字符串常量,它们在编译期就被确定了,所以s0==s1为true。而"hello"和"word"也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中"helloword"的一个引用。
所以得出s0==s1==s2。用new String()创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。
示例:
String s0="helloword"; String s1=new String("helloword"); String s2="hello" + new String("word"); System.out.println(s0==s1); System.out.println(s0==s2); System.out.println(s1==s2);
结果为:
false
false
false
s0还是常量池中"helloword"的应用。s1因为无法在编译期确定,所以是运行时创建的新对象"helloword"的引用。s2因为有后半部分new String("word")所以也无法在编译期确定,所以也是一个新创建对象"helloword"的应用。
4. 关于equals()和==
这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true。而==是比较两字符串的地址是否相同,是否是同一个字符串的引用。
5. 关于String是不可变的
String的实例一旦生成就不会再改变了。比如说:String str="hello"+"word"+" "+"ans"; 就是有4个字符串常量,首先"hello"和"word"生成了"helloword"存在内存中,又和"ans"生成了"helloword ans";并把这个字符串的地址赋给了str,就是因为String的"不可变"产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的。
下面是一些String相关的常见问题:
String中的final用法和理解
final StringBuffer a = new StringBuffer("111"); final StringBuffer b = new StringBuffer("222"); a=b;//此句编译不通过 final StringBuffer a = new StringBuffer("111"); a.append("222");//编译通过
可见,final只对引用的"值"(即内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化,final是不负责的。
总结
栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String、数组、对象等等)但不存放对象内容。
堆中存放使用new关键字创建的对象。
字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定义(常量池和堆)。有的是编译期就已经创建好,存放在字符串常量池中,而有的是运行时才被创建。
相关推荐
堆(heap)与栈(stack)是计算机内存管理中的两种基本数据结构,用于存储程序运行时产生的临时变量。在C语言中,这两种内存区域有非常明确的区分,对于理解程序的内存分配和回收具有重要意义。 首先,栈是一种特殊...
"Java 中堆(heap)和堆栈(stack)的区别" Java 中堆(heap)和堆栈(stack)是两个不同的内存区域,分别用于存储不同的数据类型和对象。堆栈(stack)是 Java 中的一种内存区域,用于存储基本类型的变量和对象的...
堆(heap)和栈(stack)的区别 堆(heap)和栈(stack)是计算机科学中两个基本的内存分配概念,它们之间的区别是非常重要的。本文将详细介绍堆和栈的概念、差异、特点和应用场景。 一、预备知识—程序的内存分配 一个由...
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据...
与栈不同,堆内存是不连续的,由操作系统维护一个空闲内存链表来分配和回收。分配内存时,系统会在找到足够大的内存块后将其从链表中移除,并返回内存起始地址。如果忘记释放内存,可能导致内存泄漏,直到程序结束或...
程序运行时所使用的内存主要分为两类:堆内存(Heap Memory)和栈内存(Stack Memory)。理解这两种内存类型的工作原理及其区别对于优化程序性能、避免内存泄漏等问题至关重要。本文将深入探讨Java中堆内存与栈内存...
在IT领域,尤其是在操作系统与编程语言的运行时环境中,“运行时堆和栈”(The Run-time Heap and Stack)是理解程序内存管理的核心概念。本文旨在深入解析这一主题,结合提供的部分文档内容,详细阐述堆和栈的区别...
首先,让我们来了解什么是栈(Stack)和堆(Heap)。栈是计算机内存中一个特殊区域,它按照后进先出(LIFO)的原则工作,主要用于存储程序运行时的临时变量。例如,函数调用时,函数参数、局部变量等都会被存储在栈...
在计算机科学领域,内存管理是实现程序高效运行的关键技术之一,而其中的堆(Heap)与栈(Stack)是两种核心的内存分配方式。本文将深入探讨这两种内存区域的分配区别,以及它们在程序中的作用机制,帮助读者理解C/...
在C语言的学习过程中,理解堆(Heap)与栈(Stack)的概念及其区别是非常重要的。本文将详细介绍这两种数据结构的特点、用途以及它们之间的主要区别,帮助初学者更好地掌握C语言中的内存管理技巧。 #### 一、栈...
### 堆与栈的区别(非常经典) #### 一、预备知识—程序的内存分配 在探讨堆与栈的区别之前,我们首先需要了解一个由 C/C++ 编译的程序是如何进行内存分配的。通常情况下,一个程序可以分为以下几个部分: 1. **...
1. 栈区(stack):由编译器自动分配释放,存放函数的参数值、局部变量的值等。 2. 堆区(heap):一般由程序员分配释放,用于存储程序的动态内存申请。 3. 全局区(static):用于存储全局变量和静态变量。 4. 文字...
##### 示例2:字符串常量池与堆的区别 ```java String s0 = "kvill"; String s1 = "kvill"; String s2 = "kv" + "ill"; System.out.println(s0 == s1); System.out.println(s0 == s2); ``` 这里涉及到字符串常量池...
本文将深入探讨Java中的两种主要内存区域:堆内存(Heap Memory)和栈内存(Stack Memory)。这两种内存分别承担着不同的角色,对于程序员理解和优化Java程序至关重要。 #### 二、栈内存 栈内存主要用于存储方法的...
在C语言中,栈与堆的使用有以下几点需要注意: 1. 局部变量默认在栈上分配,当函数执行完毕,其对应的栈空间会被自动回收。而全局变量和静态变量则在数据段或BSS段分配,不占用栈空间。 2. 动态分配的内存必须使用...
- 分配方式类似于链表,与数据结构中的堆不同。 3. **全局区(静态区)(static)** - 存储全局变量和静态变量。 - 初始化的全局变量和静态变量位于同一区域。 - 未初始化的全局变量和静态变量则位于相邻的另一块...
对于程序中的变量存储位置,通常可以分为几个部分:堆(Heap)、栈(Stack)、静态区(Static)以及代码区等。其中,堆和栈是最为常见的两种内存区域,它们在程序运行时发挥着不同的作用。 1. **栈 (Stack)**:是一...