begin 2018年1月9日17:06:47
第二章 一切都是对象Java语言假设我们只进行面向对象的程序设计。
2.1 用引用操纵对象每种编程语言都有自己的操纵内存元素的方式
操纵内存元素的方式:直接操纵元素、基于特殊语法的间接表示(如C和C++里的指针)操纵元素
在Java中,一切都被视为对象,操纵对象的标识符的是引用。
可以将这一情形想像成用遥控器(引用)来操纵电视机(对象)。
当有人想改变频道或者减小音量时,实际操纵的是遥控器(引用),再由遥控器来调控电视机对象(对象)。
即使没有电视机,遥控器亦可独立存在。
创建一个String引用:
创建一个String引用并初始化:
存储数据的五个地方:
1)寄存器。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。
2)堆栈。位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接支持。
堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。
创建程序时,Java程序必须知道存储在堆栈内所有项的确切生命周期,以便上下移动堆栈指针。
3)堆。一种通用的内存池也位于RAM区,用于存放所有的Java对象。
堆不同于堆栈的好处是:编译器不需要知道存储的数据在堆里存活多久时间。
当需要一个对象时,只需用new写一行简单的代码。
用堆进行存储分配和清理可能要比用堆栈进行存储分配需要更多的时间。
4)常量存储。常量通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。
在嵌入式系统中,常量本身会和其他部分隔离开,所有这种情况下,可以选择将其存放在ROM(只读存储器)中。
5)非RAM存储。如果数据完全存活于程序之外,那么它就不受程序的任何控制,在程序没有运行是也可以存在。
其中两个基本例子是流对象和持久化对象。
在流对象中,对象转化成字节流,通常被发送给另一台机器。
在“持久化对象”中,对象被存放于磁盘上,因此,即使程序终止,它们仍可以保持自己的状态。
堆栈是栈。(重要的事情说三遍,这是第二遍)
堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。这句话之前一直都不理解,因为大学学习的数据结构中,栈底就是在底部,栈顶就是在顶部,所以堆栈指针向下移动的话,应该是释放内存的,所以这句话错了?当然不是!
linux中一个进程的虚拟内存分布:
图中0号地址在最下边,越往上内存地址越大。
以32位地址操作系统为例,一个进程可拥有的虚拟内存地址范围为0-2^32。分为两部分,一部分留给kernel使用(kernel virtual memory),剩下的是进程本身使用, 即图中的process virtual memory。
普通Java 程序使用的就是process virtual memory.
上图中最顶端的一部分内存叫做user stack. 这就是题目问的 stack(栈). 中间有个 runtime heap。就是题目中的heap(堆). 他们的名字和数据结构里的stack(栈) 和 heap(堆) 几乎没啥关系。
注意在上图中,stack(栈)是向下生长的; heap(堆)是向上生长的。
引用这个答案
所以呢,堆栈指针向下移动时分配内存,向上移动时释放内存。
2.2.2 特例:基本类型基本类型出现的原因:这种类型是小的、简单的变量,不需要用new在堆上分配空间,直接置于堆栈中,这样更高效。
Java要确定每种基本类型所占存储空间的大小。
基本类型 大小 最小值 最大值 包装器类型boolean - - - Boolean
char 16-bit Unicode 0 Unicode 2^16-1 Character
byte 8 bits -128 +127 Byte
short 16 bits -2^15 +2^15-1 Short
int 32 bits -2^31 +2^31-1 Integer
long 64 bits -2^63 +2^63-1 Long
float 32 bits IEEE 754 IEEE 754 Float
double 64 bits IEEE 754 IEEE 754 Double
void - - - void