`
heisalittlebird
  • 浏览: 20158 次
文章分类
社区版块
存档分类
最新评论

堆栈的知识

 
阅读更多

堆栈相关知识

由于stack是以队列的形式存储的,即先进后出,后进先出,所以经常有面试会让你模拟一下栈的存储过程:

Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时 动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类 型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

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, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

String是一个特殊的包装类数据。可以用:

String str = newString("abc");

String str = "abc";

两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。

而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。

String str1 = "abc";

String str2 = "abc";

System.out.println(str1==str2);//true

可以看出str1和str2是指向同一个对象的。

String str1 =new String("abc");

String str2 =new String("abc");

System.out.println(str1==str2);// false

用new的方式是生成不同的对象。每一次生成一个。

因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。

另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。

由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

我的理解是:

首先来了解java程序中内存的结构:

堆:存放所用new出来的对象

栈:存放对象的引用(也就是地址),基本数据类型产生的变量

常量池:(这个比较特殊)是用来存放String常量,如“abc”

你的例子:

String a = newString("abcdef");

因为有new,调用了String类的构造,在堆中产生了一个对象,值为“abcdef”,

然后在栈中声明一个引用a,把产生的对象的引用赋值给a;

String a = "abcdef";

这是声明一个字符串常量,首先在池中查找有没有这个“abcdef”,如果没有,在池中产生一个“abcdef”,然后把引用赋值给栈中的a

你的第二个问题

SomeClass a=new SomeClass();

这个就是在堆中构造一个对象,然后把引用传给栈中的a

a=new SomeClass();

这个语法是错误的,因为a没有声明

new SomeClass();

直接在堆中产生一个对象,但是没有传给栈中的一个引用(根据JAVA的垃圾回收机制,长时间不用,JVM会调用System.gc()方法析构掉这个对象)。

总结一下,你的第一种和第三种方法都可以产生一个对象,如果你只想产生一个对象然后只运行一次,可以用第3个,不过因为没有引用指向它,以后想使用这个对象而找不到;第一种是常见的方法,产生一个对象,并且声明栈中的一个引用指向它,以后可以用这个引用随时使用这个对象。

(其实有些不是绝对的,比如除了用new,反射机制也可以产生对象;而有时对象会放在栈中,这些你不用管)

说的有点啰嗦,大概就是这些。

分享到:
评论

相关推荐

    数据结构课程堆栈知识应用

    ### 数据结构课程堆栈知识应用 #### 一、概述 在计算机科学中,**数据结构**是一门重要的基础学科,它研究的是数据的组织方式以及这些数据在其上进行的操作。其中,**堆栈**(Stack)作为一种特殊的线性数据结构,在...

    C++/C堆栈知识

    在编程领域,尤其是在C++和C这样的语言中,理解堆栈(Stack)的概念至关重要,因为它们直接影响程序的执行效率和内存管理。...在实际编程中,掌握堆栈知识可以提高我们对内存管理的理解,从而编写出更加健壮的C++程序。

    51单片机期末试卷及基础知识复习.docx

    这道题考查了单片机的堆栈知识。单片机的堆栈是指单片机中负责存储数据的寄存器。 8. MCS-51有4组工作存放器,它们的地址范围是一00H到FH。这道题考查了单片机的存储器知识。单片机的存储器是指单片机中负责存储...

    单片机堆栈指针的基础知识

    文章带大家了解一下单片机的堆栈指针。

    dongzuoji.zip_labview做堆栈_labview有堆栈吗

    标题“dongzuoji.zip_labview做堆栈_labview有堆栈吗”暗示了这个压缩包包含的是关于如何在LabVIEW中实现堆栈功能的源代码。堆栈是一种特殊的线性数据结构,遵循“后进先出”(LIFO,Last In First Out)的原则,...

    C++高效获取函数调用堆栈

    要实现高效获取函数调用堆栈,需要了解函数调用堆栈和异常处理的背景知识。 1.1 函数调用堆栈 函数调用堆栈是一种重要的数据结构,在程序执行过程中,它记录了函数的调用关系和参数信息。C++中有多种调用约定,如_...

    易语言申请进程堆栈内存

    本文将详细解析"易语言申请进程堆栈内存"这一主题,以及相关知识点。 1. **进程与堆栈内存**: - **进程**:是操作系统中正在运行的一个程序实例,拥有自己的独立内存空间,包括代码段、数据段、堆区和栈区。 - *...

    C++写括号匹配堆栈

    本题目以"C++写括号匹配堆栈"为标题,旨在通过实现一个程序来检查输入的字符串或文件中的括号是否正确配对。下面将详细讨论相关知识点。 首先,我们要了解C++语言。C++是一种强大的、面向对象的编程语言,具有高效...

    arm堆栈的操作之我见

    ARM 堆栈操作指南 ARM 堆栈操作是 ARM 架构中的一种基本操作方式,了解 ARM 堆栈操作是学习 ARM 的基础。下面是关于 ARM 堆栈操作的详细...通过了解 ARM 堆栈操作的这些知识点,您将可以更好地学习和理解 ARM 架构。

    VC++创建堆栈

    下面将详细介绍如何在VC++中创建堆栈以及相关知识点。 1. 堆栈的基本概念: 堆栈是一种线性数据结构,它有两个基本操作:压入(Push)和弹出(Pop)。压入操作将元素添加到堆栈的顶部,而弹出操作则移除并返回堆栈...

    C51堆栈构成与空间需求分析

    在C51单片机开发中,堆栈管理是基本且关键的知识点,它关系到程序的稳定运行和资源的有效利用。 部分文中内容提供了关于如何使函数成为可重入函数的方法。只需要在函数定义后添加关键字“reentrant”,C51编译器就...

    堆栈实现的java计算器

    通过这个项目,我们可以学习到如何将理论知识应用到实际编程中,特别是如何使用堆栈解决计算表达式的问题。 首先,堆栈的基本操作包括压栈(push)、弹栈(pop)、查看栈顶元素(peek)以及检查栈是否为空(isEmpty...

    ST32堆栈测试代码

    本文将围绕“ST32堆栈测试代码”这一主题,详细解析相关知识点。 首先,ST32是一款基于ARM Cortex-M内核的微控制器系列,由意法半导体(STMicroelectronics)生产。它广泛应用于各种嵌入式系统,如物联网设备、工业...

    关于堆栈的论文

    综上所述,“关于堆栈的论文”可能涵盖了这些核心知识点,并深入研究了它们在不同场景下的实现与优化。通过学习和理解堆栈的工作原理,我们可以更有效地设计和实现各种算法,提高程序的效率和可维护性。对于计算机...

    vC 堆栈 异常处理

    理解和熟练掌握这些知识,将有助于编写更加健壮和可靠的vC++应用程序。在实际开发中,应该注重代码的异常安全性,合理使用try-catch结构,并时刻关注可能引发堆栈溢出的情况,以确保程序的稳定运行。

    堆栈类的实现(C++源代码)

    #### 重要知识点 1. **初始化方法**:`init()`方法将`position`设置为0,表示堆栈为空。 2. **压栈操作**:`push(char ch)`方法将一个字符添加到堆栈的顶部。如果堆栈已满(即`position`等于`SIZE`),则输出...

    FPGA堆栈的VHDL实现

    #### 二、堆栈基础知识 堆栈(Stack)是一种特殊的线性表,它只允许在一端进行插入和删除操作。这一端称为“栈顶”,另一端称为“栈底”。堆栈遵循“后进先出”(Last In First Out,LIFO)的原则,因此也被称为...

    QT窗口管理之堆栈窗体

    通过上述知识点的学习,我们不仅能够理解如何在Qt中实现堆栈窗体的管理,还能够掌握信号与槽机制在实现用户交互时的应用,以及布局管理在创建美观界面时的重要性。这对于我们构建复杂用户界面是非常有帮助的。

    linux 堆栈溢出的问题

    堆栈溢出的基础知识: 1. **堆栈的结构**:堆栈是内存中一块连续的空间,用于存储程序中的局部变量、函数调用时的返回地址和帧指针(EBP)。在Intel汇编语言中,堆栈是从高地址向低地址增长的,即“向下”生长。 2....

    堆栈溢出技术从入门到精通

    为了理解堆栈溢出,我们首先需要了解一些预备知识。这些包括但不限于汇编语言、寄存器功能、堆栈操作和内存分配。在intel汇编语言中,寄存器是处理器的内部存储单元,其中ESP(扩展堆栈指针)用于指向堆栈顶部,而...

Global site tag (gtag.js) - Google Analytics