首页 > 代码库 > Java编程思想 2-1 一切都是对象
Java编程思想 2-1 一切都是对象
尽管 Java 是基于 C++ 的,但是相比之下,Java 是一种更纯粹的面向对象程序设计语言。
在本章,将看到 Java 程序的基本组成部分,并体会到在 Java 中几乎一切都是对象。
2.1 用引用操纵对象
Java 中通过引用(遥控器)操纵对象(电视机)。
引用可以独立存在,并不一定需要有一个对象与之关联。比如:String s; 这里创建的只是引用,而不是对象。如果此时向 s 发送消息,就会返回一个运行时错误。因为此时 s 实际上没有和任何事物关联。
因此,一种安全的做法是:创建引用的同时便进行初始化,即 String s = "asdf";(这里直接赋值了一个字符串字面量,一般使用一种更通用的方式)。
2.2 必须由你创建所有对象
通常用 new 操作符创建新对象。所以,前面的例子可以写成:String s = new String("asdf");
2.2.1 存储到什么地方?
- 寄存器
- 是最快的存储区,位于处理器内部,不能直接控制。
- 堆栈
- 存储对象引用;JVM需要知道存储在堆栈中的所有项的确切生命周期。
- 堆
- 存放所有的 Java 对象;编译器不需要知道存储在堆中的数据存活多久;效率没有使用堆栈高。
- 常量存储
- 常量值通常直接存放在程序代码内部。
- 非RAM存储
- 流对象和持久化对象。
2.2.2 特例:基本类型
之所以将基本类型作为特例,是因为 new 将对象存储在堆中,所以用 new 创建小的、简单的对象时,往往不是很有效。
Java 对于基本类型,不使用 new 创建变量,而是创建一个并非是引用的变量。该变量直接存储值,并置于堆栈中,因此更加高效。
Java 中基本类型所占存储空间的大小不会随机器硬件架构的变化而变化。这也是 Java 编写的程序更具有可移植性的原因之一。
基本类型 | 比特位数 | 包装器类型 |
boolean | Boolean | |
char | 16 | Character |
byte | 8 | Byte |
short | 16 | Short |
int | 32 | Integer |
long | 64 | Long |
float | 32 | Float |
double | 64 | Double |
boolean 类型所占存储空间的大小没有明确指定,仅定义为能够取字面值 true 或 false。
JavaSE5 的自动包装功能能够实现基本类型和包装器类型之间的自动转换。
Character ch = ‘x‘; char c = ch;
Java 提供了两个用于高精度计算的类:BigInteger 和 BigDecimal。这两个类提供的操作与对基本类型所能执行的操作相似。只不过必须以方法调用的形式代替运算符的形式。
BigInteger 支持任意精度的整数,可以准确表示任意大小的整数值;BigDecimal 支持任何精度的定点数,可以用来进行货币运算。详细使用方法查看文档。
2.2.3 Java中的数组
Java 确保数组会被初始化,而且不能在它的范围之外被访问。这种范围检查,是以每个数组上少量的内存开销以及运行时的下标检查为代价的。换来了安全性和效率的提高。
创建一个数组对象时,实际就是创建一个引用数组,并且每个引用都会自动被初始化为一个特定值,该值有自己的关键字 null。一旦 Java 看到 null,就知道这个引用还没有指向某个对象。
在使用任何引用前,必须为其指定一个对象;如果试图使用一个为 null 的引用,运行时就会报错。
2.3 永远不需要销毁对象
2.3.1 作用域
大多数过程型语言都有作用域的概念。作用域决定了在其内定义的变量名的可见性和生命周期。Java 中,作用域由花括号的位置决定。
在作用域中定义的变量,只可用于作用域结束之前。
以下代码在 C 和 C++ 中是合法的,但 Java 中不能这么写:
{ int x = 1; { int x = 2; } }
Java 编译器会报告变量 x 已经定义过。C 和 C++ 中将一个较大作用域的变量“隐藏”起来的做法,在 Java 里是不允许的,因为 Java 设计者认为这样会导致程序混乱。
2.3.2 对象的作用域
通过 new 创建的对象可以存活于作用域之外。如下代码:
{ String s = new String("asdf"); }
引用 s 在作用域终点就消失了。然而 s 指向的对象仍然占据内存空间。在上述方法中,我们无法在这个作用域之外访问这个对象,因为该对象的唯一引用已经超出了作用域的范围。
所以,由 new 创建的对象,只要你需要,就会一直保留下去。这就带来一个问题:如何防止这些对象填满内存空间,进而阻塞你的程序?
Java 有一个垃圾回收器,用来监视 new 创建的所有对象,并识别出不会再被引用的对象。随后,释放这些对象的内存空间,以便供新对象使用。
2.4 创建新的数据类型:类
大多数面向对象的程序设计语言都是用 class 关键字定义新的类型。格式如下:
class ATypeName { /* class body */ }
创建该类型的对象:
ATypeName a = new ATypeName();
在 Java 中,你所做的全部工作就是定义类,创建这些类的对象,以及向对象发送消息。
类有字段和方法。字段可以是任何类型的对象,可以通过引用与其进行通信;也可以是基本类型中的一种。每个对象都有用来存储其字段的空间,普通字段不能在对象间共享。
如何引用一个对象的成员:obj.member;嵌套情况:obj.innerObj.member;
若类的某个成员是基本类型,即使没有进行初始化,Java 也会确保它获得一个默认值。如下表所示:
基本类型 | 默认值 |
boolean | false |
char | ‘\u0000‘ |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0d |
2.5 方法、参数和返回值
Java 的方法决定了一个对象能够接收什么样的消息。方法的基本组成包括:名称、参数类型、返回值和方法体。具体格式如下:
returnType methodName( /* arguments list */ ){ /* method body */ }
返回类型描述的是调用方法之后从方法返回的值。参数列表给出了要传给方法的信息的类型和名称。方法名和参数列表(合称为方法签名)唯一的标识一个方法。
Java 中的方法只能定义在类中。
通过对象调用方法:obj.methodName( arg1,arg2,arg3)
return 关键字的作用:① 结束此方法;② 返回方法的结果值。
2.6 构建一个 Java 程序
2.6.1 名字可见性
翻转域名,包名小写。
2.6.2 运用其他构件
如果想在程序中使用预定义的类,那么编译器就必须知道如何定位这些类。如果这个类就在发出调用的那个源文件中,就可以直接使用该类。即使这个类在文件的后面才被定义(Java 消除了向前引用的问题)。
如果那个类位于其他文件中,就需要通过 import 关键字导入。
单独导入:import java.util.Date;
批量导入:import java.util.*;
2.6.3 static 关键字
声明一个事物是 static 时,意味着这个字段或方法不会与包含它的那个类的任何对象实例联系在一起。所以,即使没有创建某个类的任何对象,也可以调用其 static 方法或访问其 static 字段。
可以通过对象访问其 static 字段和方法,推荐使用类名直接访问。
2.7 你的第一个 Java 程序
Java编程思想 2-1 一切都是对象