第2章 一切都是对象
这一章主要介绍跟对象相关的工作。包括一个对象的生成,销毁,作用域等等。都是一些细节的知识点。
2.1 用引用操作对象
在java中,一切都被看做对对象,但是操作的标识符实际上是对象的一个“引用(reference)”。
String s ;
这里的 s 只是一个引用,并没有和对象关联。
String s = "abc";
这里的引用 s 关联了 对象 "abc",即通过操作引用来操作对象(就好像用遥控器操作电视机一样)。
2.2 必须由你创建所有对象
对象存储位置
这里我们关注一下创建的对象存到什么地方。
有5个地方可以存储数据:
- 寄存器:最快的存储区,因为就在处理器中(贴身小口袋)。但是空间很有限,程序中无法指定相关存储。
- 堆栈 stack:第二快的存储。stack中通过堆栈指针上下移动来决定分配内存和释放内存。所以,创建程序时,java系统必须知道stack中每一项的生命周期,才可以上下移动指针。 对象引用存在于stack中。
- 堆 heap:java 对象引用存在于 heap 中。之前说过,与stack相比,这里系统并不需要知道对象的生存周期。需要一个对象时,直接 new 就完事了,这时候就在 heap 中动态分配内存(相比于stack中,heap中创建和销毁耗时更长)。
- 常量存储:常量值 const 一般是放在程序代码内部,因为其永远不变(就跟程序代码一样)。
- 非RAM 存储:数据完全存活于程序之外,不受程序的任何控制。这里有流对象和持久化对象。
明白一个点,引用在 stack中,对象在 heap 中。
对象特例:基本类型
除了上面说的需要 new 的存储于heap中的对象,java中还有一类很小的、简单的、不需要 new 来存储到heap中 的对象:基本类型。基本类型创建一个“自动”变量,直接存储“值”在 stack 中,更加高效(前面说到 stack 中比 heap 中更快)。
明白一个点,基本类型不需要new一个对象,直接存储值在 stack 中

看到,所有的基本类型都是有正负号的。不存在没有无符号的数值类型。
boolean 类型所占的存储大小没有指定(具体要看虚拟机和实现)。
这里当然也可以使基本类型在 heap 中创建对象。
Character ch = new Character('x');
这么做的用处以后会说到。
除了上面的基本类型外,java 还提供了两个类来做高精度计算:BigInteger & BigDecimal。
- BigInteger:支持任意精度的整数,计算中可以表示任意大小的整数值,不丢失信息。
- BigDecimal:支持任意精度的定点数。可以做精确的货币计算。
java 中的数组
java 确保数组可以被初始化(相对于c/c++中可能存在的初始化之前使用数组引起错误而言),并且不能在它的范围之外被访问。
- 数组对象,实际上就是一个引用数组,每个元素 初始化为 nulll
- 基本类型,编译器将所占内存置0
- 越界会抛出,[java.lang.ArrayIndexOutOfBoundsException] 异常
2.3 永远不需要销毁对象
正如前面说的,java不需要考虑合适销毁对象,垃圾回收器帮我们做了这一项工作,使得程序的 bug 大大减少。
{
String s = new String("Test");
}
这里引用s在括号(作用域)之外就消失了。但是s指向的String对象仍然占用空间。垃圾回收器就会监视用 new 创建的对象,辨别不被引用的对象,释放相应的内存空间。
2.4 创建新的数据类型:类
其实在 java 中所做的所有工作都是在自定义类。
类中可以有,数据成员、成员函数。
类中的数据成员可以是任何类型的对象。如果是基本数据类型,不需要初始化,系统会对其自动赋默认值;如果是某个对象的引用,必须初始化(一般用new),使其与某个对象实例相关联。
如果在成员函数中,基本类型的对象需要初始化的,不然会报错。
记住两个点:
(1)类中的非基本类型对象需要初始化(系统会自动初始化)
(2)成员函数中的基本类型需要初始化
2.5 方法、参数和返回值
2.6 构建一个 java 程序
static 关键字
通常而言,只有 new 一个对象,相关的类方法才可以被调用。
但是 用static 关键字声明的方法或成员数据,可以不用创建对象,就进行访问。
class StaticTest{
static int i = 47;
}
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
这里 st1.i 和 st2.i 指向同一存储空间,因此他们具有相同的值 47。
StaticTest.i++;
这就是所谓不用创建对象,直接通过类名. 来访问。
这里记住两个点:
(1)静态数据成员指向同一存储空间
(2)静态数据和函数可以不通过对象,直接用类名进行访问
public static void main(String args[])
主函数都是这么写。这里虽然没有用到 args,但是编译器是这么要求的。args要用来存储命令行参数。
网友评论