本章主题
我们从第二章的名字就能先得到结论:JAVA中一切都是对象。那么,我们就应该能知道这一章应该就是讲关于对象的知识。在看书过程中应该始终围绕对象这个关键词。
###1. 用引用操作对象
每种编程语言都有操纵内存数据的方式,那么程序员需要考虑怎样使用这些内存中的数据。比如是直接操纵数据单位,还是通过特殊语法间接使用这个数据单位。在C/C++中,程序员通过指针来间接使用数据单位。但是在JAVA中这一切得到了简化。一切都被视为对象,因此可采用单一固定的语法。操纵的标识符实际上是一个对象的引用。就像遥控器和电视机的关系
###2. 数据单位存在哪里? 然后就是上一章提到令人头疼的内存分配问题了。在JAVA主要有5类:
- 寄存器:CPU中,最快的存储区。但是空间太少(程序员无法操控)
- 堆栈:通用RAM(随机访问存储器),对象的引用存储在这里,通过堆栈指针来开辟/释放内存。[特殊情况是8种基本类型]
- 堆:通用内存池(也位于RAM区),存放所有JAVA对象
- 常量存储:存放在程序代码内部,或者可以选择ROM(只读存储器)。这一般是编译器的职责,在编译过程中可能会将使用该常量的地方进行替换
- 非RAM存储:数据存活在程序之外,它可以在程序运行中存在,也可以在程序终止时存在,不受程序的限制。
- 流对象:字节流在机器之间传输
- 持久化对象:持久化对象保存在磁盘上
但是也有例外,就是基本类型。在JAVA中,new出来的对象会存放在堆中。但是对于特别小的、简单的变量,往往效率很低。所以JAVA规定:
对于8种基本类型,是通过创建一个并非是引用的“自动”变量。这个变量的值直接存储“值”,放在堆栈中。
###3. 移植性的原因:一致性 JAVA会固定每种基本类型所占存储空间的大小。它们的大小并不像大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是JAVA程序比大多数其它语言编写的程序更具有移植性的原因之一。比如C/C++中,int的大小可能会是2字节或者是4字节,这就给平台移植带来了一定的麻烦。下面是JAVA的基本数据类型:
基本类型 | 大小(字节) | 包装器类型 |
---|---|---|
boolean | - | Boolean |
char | 2 | Character |
byte | 1 | Byte |
short | 2 | Short |
int | 4 | Integer |
long | 8 | Long |
float | 4 | Float |
double | 8 | Double |
创建的时候,会有默认值的:
基本类型 | 默认值 |
---|---|
boolean | false |
char | ‘\u0000’(null) |
byte | (byte)0 |
short | (short)0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
下面是一些tips:
- 在C/C++中,有unsigned类型,但是JAVA中没有。所有数值类型都有正负号,所以不要去寻找无符号的数值类型
- boolean仅仅定义了true和false,所以boolean类型所占存储空间的大小不确定
- 只有当变量作为类的成员变量时,Java才确保给它默认值。如果它是局部变量,Java是不会给它默认值的,是一个任意值。如果你没有显示初始化,编译的时候会报错的,但是C++仅仅会给与警告
- char的默认值是’\u0000’,\u代表这是Unicode字符,ASCII码是Unicode的一个子集,范围为\u0000到\u00FF,其中\u0000代表的就是一个null,输出到控制台是一个空格
###4. JAVA数组安全
对于数组而言一般有两大问题:
- 未初始化就使用
- 数组越界
在C/C++中,使用未初始化的数组元素或者数组越界是不会报错的,所以程序会出现莫名其妙的错误,不容易定位错误的地方。而JAVA的主要目标之一就是安全性,所以JAVA对于这两点有相应的处理方法:
- JAVA确保数组会被初始化后才能使用。如果是基本类型,直接用默认值初始化;如果是引用类型,就用null来初始化。如果不把引用指向对象,运行时会发现引用指向的是null,抛出NullPointerException
- JAVA对数组采用了少量的内存开销和运行时下标检查作为代价,我估摸就是对每个数组记录一下长度length,如果你使用的下标为index,JAVA会判断index是否小于length,如果小于,正常使用;反之抛出ArrayOutOfBoundsException(C++完全不管呀,就靠自觉- -)
###5. GC机制
C++饱受诟病的一点就是内存泄露,因为C++对于效率的追求较高,所以将内存处理也交付程序员自己处理。而对于内存操作不当,很容易就造成内存泄露。但JAVA解决了这个问题(当然,带来的影响就是JAVA程序性能会下降)。它采用一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象(就是引用个数为0),之后会释放它们占有的内存供其它新的对象使用。而且,GC只去堆上玩,所以堆栈上的引用、基本类型,寄存器里的,静态存储区ROM,非RAM存储的东西,它一个都不管
###6. 注释和嵌入式文档
对于很多公司来说,开发工作都是很紧的,这带来的问题就是程序没有详细的设计文档,别人无法从整体上把握程序。而JAVA运用javadoc工具,将程序和文档“链接”起来:程序员写特殊的注释语法,然后JAVA提取整理,输出一个html页面,可以用浏览器查看。
所有的javadoc命令都只能在/**
注释中出现,和通常一样,注释结束于*/
。使用javadoc的方式主要有两种:
- 嵌入html(很少用…)
- 使用独立文档标签(是一些以
@
字符开头的命令,且要置于注释行的最前面)
对应于类、域、方法,注释方法如下所示:
1
2
3
4
5
6
7
8
9
10
/** A class comment */
public class HelloWorld {
/** A field comment */
public int number;
/** A method comment */
public void function() {
}
}
但是对于private和包内可访问成员,javadoc会忽略。因为只有public和protected的成员才能在文件之外被使用,这是客户端程序员所期望的。
一些常用的@命令有:
@see:引用其他类
@version:版本说明信息
@author:作者
@param:方法的参数列表标识符描述
@return:函数返回值描述
@throws:抛出异常描述
@Deprecated:废弃的方法
举一个例子吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.*;
/**
* @author niushuai
* @version 1.0
*/
public class HelloWorld {
/** Entry point to class & application
* @param args array of string arguments
* @throws exceptions No exceptions thrown
*/
public static void mian(String[] args) {
System.out.println("Hello world!");
}
}
###7. 编码风格
在“Java编程语言编码约定”中,代码风格是这样规定的:
- 类名中所有单词首字母大写
- 几乎其他所有内容——方法、字段(成员变量)以及对象引用名称等,普遍采用首字母小写,后面单词首字母大写
- static final修饰的变量全部大写,单词之间用下划线分隔
- 括号在参数列表行内
- 最大行宽80字符
- 缩进(tab)2个字符