一切都是对象

在本章,我们将看到 Java 程序的基本组成部分,并体会到在 Java 中(几乎)一切都是对象。

用引用操纵对象

尽管将一切都看作对象,但操纵的标识符实际上是对象的一个 引用(reference)。可以将这一情形想象成用遥控器(引用)来操纵电视机(对象)。此外,即使没有电视机,遥控器亦可独立存在,也就是说,拥有一个引用,并不一定需要有一个对象与它相关联。

1
2
3
String s1;  //仅仅只创建了一个引用

String s2 = new String("hello"); //创建一个引用并与一个新的对象相关联

必须由你创建所有对象

一旦创建了一个引用,就希望它能与一个新的对象相关联,通常用 new 操作符来实现。

存储到什么地方

一般有五个不同的地方可以存储数据:

  • 寄存器(Registers):这是最快的存储区,位于处理器内部
  • 堆栈(The stack):速度仅次于寄存器,位于通用 RAM(随机访问存储器)中。存储在堆栈内的所有项必须知道确切的生命周期,一般将对象的引用存储于堆栈中
  • 堆(The heap):一种通用的内存池(也位于 RAM 区),用于存放所有的 Java 对象
  • 常量存储(Constant storage):一般直接存放于程序代码内部。在嵌入式系统中,可以选择存放在 ROM(只读存储器)中
  • RAM 存储(Non-RAM storage):数据完全存活于程序之外,例如 流对象持久化对象。在流对象中,对象转化成字节流,发送给另一台机器。在持久化对象中,对象被存放于磁盘上。这种存储方式,可以在需要时,将数据恢复成常规的、基于 RAM 的对象。

特例:基本类型

new 创建一个对象(特别是小的,简单的变量),往往不是很有效。对于这一系列的类型,称之为基本类型。Java 不用 new 来创建一个并非引用的自动变量,而是直接存储值,并且置于堆栈中。

Java 要确定每种基本类型所占存储空间的大小,并且不会随着机器硬件架构的变化而变化。这种不变性,也是 Java 编写的程序更具可移植性的原因之一。

基本类型 大小 最小值 最大值 包装器类型
$boolean$ $-$ $-$ $-$ $Boolean$
$char$ $16 \; bits$ $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$

所有数据类型都有正负号,所以不要去寻找无符号的数据类型。boolean 类型所占存储空间大小没有明确指定,仅定义为能够取字面值 truefalse

基本类型具有包装器类,可以在堆中创建一个非基本对象。

1
2
3
4
Character character = new Character('x');

Character ch = 'X'; //自动包装,将基本类型转换成包装器类型
char c = ch; //也可以反向转换

Java 提供了两个用于高精度计算的类:BigIntegerBigDecimal

Java 中的数组

当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会自动被初始化为一个特定的值,该值拥有自己的关键字 null

永远不需要销毁对象

大多数过程型语言都有 作用域(scope)的概念。作用域决定了在其内定义的变量名的可见性和生命周期。尽管以下代码在 C 中是合法的,但是在 Java 中不能这样书写。

1
2
3
4
int x = 12;
{
int x = 96; // Variable 'x' is already defined in the scope
}

在以下代码中,在作用域外无法访问这个对象,但是这个对象仍继续占据内存空间。Java 主要使用 垃圾回收器 来监视用 new 创建的所有对象,并辨别那些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。

1
2
3
4
{
String s = new String("hello");
}
System.out.println(s); // Cannot resolve symbol 's'

创建新的数据类型:类

一旦定义了一个类,就可以在类中设置两种类型的元素:字段(数据成员)和 方法(成员函数)。若类的某个字段是基本数据类型,即使没有进行初始化,Java 也会确保它获得一个默认值。

基本类型 默认值
boolean false
char ‘\u0000’ (null)
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0.0d

上述确保初始化只适用于 类的字段,并不适用于 局部变量

1
2
int x;
System.out.println(x); // Variable 'x' might not have been initialized

方法、参数和返回值

方法的基本组成部分包括:名称,参数,返回值和方法体。除了某些特殊数据类型,通常方法参数传递的是对象的引用。

构建一个 Java 程序

在每个程序文件的开头,必须声明 import 语句,以便引入在文件代码中需要用到的额外类。注意,在这里说额外类,是因为有一个特定类会自动被导入到每一个 Java 文件中:java.lang

注释

有三种注释的方式:

1
2
3
4
5
6
7
8
9
/* This is a comment
* that continues
* across lines
*/


/* This is a comment that
continues across lines */


// This is a one-line comment

通过 javadoc 可以生成良好的程序文档,以 HTML 的形式展现。所有的 javadoc 命令都只能在 /** 注释中出现,以 */ 结束,文档标签以 @ 字符开头。例如:

1
2
3
4
/**
*
* @param args
*/

编码风格

类名的首字母要大写,标识符的第一个字母采用小写,例如:

1
2
3
4
5
6
7
8
class AllTheColorsOfTheRainbow {

int anIntegerRepresentingColors;

void changeTheHueOfTheColor(int newHue) {

}
}