Java 编程思想 - 第二章 - 一切都是对象
尽管Java是基于C++的,但是相比之下,Java是一种更纯粹”的面向对象程序设计语言。
用引用操纵对象
尽管一切都看作对象,但操纵的标识符实际上是对象的一个“引用”(reference)。
可以将这一情形相像成用遥控器(引用)来操纵电视机(对象)。
一个引用并不一定需要有一个对象与它关联。
即使没有电视机,遥控器亦可以独立存在。
必须由你创建所有对象
存储到什么地方
程序运行时,对象是怎么进行放置安排的呢?特别是内存是怎样分配的呢?
- 寄存器。最快的存储区,因为它位于处理器内部。但寄存器的数量极其有限,所以寄存器根据需求进行分配。不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。
- 堆栈。位于通用RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。创建程序时,Java系统必须知道存储在堆栈内所有项的确切生命周期,以便上下移动堆栈指针。某些Java数据存储于堆栈中——特别是对象引用,但Java对并不存储于其中。
- 堆。一种通用的内存池(也位于RAM区),用于存放所有的Java对象。编译吕不需要知道存储的数据在堆是存活多长时间。
new将对象存储在“堆”里。
- 常量存储。常量值通常直接存放在程序代码内部。
- 非RAM存储。两个基本的例子:流对象和持久化对象
特例:基本类型
基本类型 | 大小 | 最小值 | 最大值 | 包装器类型 |
boolean | – | – | – | Boolean |
char | 16-bit | Unicode o | Unicode 216−1 2 16 − 1 | Character |
byte | 8 bits | -128 | +127 | Byte |
short | 16 bits | −215 − 2 15 | +215−1 + 2 15 − 1 | Short |
int | 32 bits | −231 − 2 31 | +231−1 + 2 31 − 1 | Integer |
float | 32 bits | IEEE754 | IEEE754 | Float |
double | 64 bits | IEEE754 | IEEE754 | Double |
void | – | – | – | Void |
- 所有数值类型都有正负号。
- boolean类型所占存储空间的大小没有明确指定,仅定义为能够取字面值true或false。
- BigInteger支持任意精度的整数。
- BigDecimal支持任何精度的定点数。
Java中的数组
- 创建对象的数组时,实际上是创建了一个引用数组,每个引用都会自动被初始化为null。
- 创建用来存放基本数据类型的数组时,将这种数组所占的内存全部置零。
永远不需要销毁对象
作用域
在作用域里定义的变量只可用于作用域结束之前。
对象的作用域
{
String s = "a string";
} //End of scope
引用s在作用域终点就消失了。然而,s指向的String对象仍继续占据内存空间。
由new创建的对象,只要需要就会一直保留下去。
Java有一个垃圾回收器,释放不会再被引用的对象的内存空间。
static关键字
通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则,实际上并未获得任何对象。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。
有两种情形用上述方法是无法解决的:
- 只想为某特定域分配单一存储空间,而不去考虑空间要创建多少对象,甚至根本就不创建任何对象。
- 希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用这个方法。
通过static关键字可以满足这一方面的需要。
class StaticTest {
static int i = 47;
}
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
在这里,st1.i和st2.i指向同一存储空间。
使用类名是引用static变量首选方式,类似逻辑也应用于静态方法。
StaticTest.i++;
尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说只有一份存储空间,而非static字段则是对每个对象有一个存储空间),但是如果static作用于某个方法,差别却没有那么在。static方法的一个重要的用法就是在不创建任何对象的前提下就可以调用它。