2.1用引用操作对象
在java里一切都被视为对象,但操作的标识符实际上是对象的一个"引用(reference)"。可以将这一情形想象成遥控器(引用)来操纵电视机(对象)。只要握住遥控器就可以保持与电视机的连接。另外即使没有电视机,遥控也可以独立存在。也就是说你有一个引用,并不一定需要有一个对象与它关联。如果想操作一个词或句子,则可以创建一个String引用:
String s;
创建的不是对象是引用。如果此时向s发一个消息,就会返回一个错误。所以我们有一种更安全的做法是:创建一个引用的同时并进行初始化:
String s = "asdf";
2.2必须由你创建所有对象
一但创建了一个引用,就希望它能与一个新的对象相关联。通常用new操作符来实现这一目的。
String s = new String("asdf");
它不仅表示一个“给我一个新的字符串”,还提供了一个初始字符串,给出了怎样产生这个String的信息。
-
2.2.1存储到了什么地方
- 寄存器 这是最快的存储区,它位于处理器内部(与其他存储区的地方不一样)。但寄存器的数量有限,所以必须根据需求进行分配。不能用于直接控制,也不能在程序中感觉到寄存器的存在任何迹象。
- 堆栈 位于通用的RAM(随机访问存储器)中,但通过堆栈指针可以从处理器那里获得直接的支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些内存。
- 堆 一种通用的内存池(也位于RAM区),用于存放所有的java对象。堆不同于堆栈的好处是:编译器不需要知道存储的数据埋在堆里多长时间。因此分配堆有很大的灵活性。当需要一个对象时,直接用new写一个简单的代码,当执行这行代码时,会自动在堆里进行存储分配。这种灵活性的代价:用对进行存储分配和清理可能比用堆栈进行存储分配需要更多的时间。
- 常量存储 常量值放直接放在程序代码内部,这样做是安全的。在嵌入式系统中,常量本身也会和其他部分分隔离开,可以选择将其放在ROM(只读存储器中)。
- 非RAM存储 数据完全存活于程序之外,不受任何程序的控制。其中基本的两个例子是流对象和持久化对象。a.在流对象中,对象转化为字节流,通常被发送给另一台机器。b.在“持久化对象”中,对象被存放于磁盘上,因此程序终止,它也可以保持自己的状态。这种存储方式技巧在于:把对象转化为可以存储在其他媒介上的事物,在需要时恢复成常规的、基于RAM的对象。
-
2.2.2特例:基本类型
我们可以把他们想象成“基本”类型。之所以特殊对待是因为new将对象存储在“堆”类,故用new创建一个对象—特别是小的、简单的变量。不用new来创建变量,而是创建一个并非是引用的“自动”变量。这个变量直接存储“值”,并置于堆栈中。
所有数值类型都有正负号,所以不要去寻找无符号的数值类型。
基本类型具有的包装器类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。例如:
char c = 'x' ;
Character ch = new Character(c);
也可以这样:
Character ch = new Character('x');
Java SE5的自动包装功能将自动地将基本类型转化为包装器类型:
Character ch = 'x' ;
并可以反向转换:
char c = ch;
-
2.2.3 Java中的数组
当创建一个数组对象时,实际上是创建了一个引用数组,在使用任何引用前,必须为其指定一个对象。
2.3永远不需要销毁对象
-
2.3.1 作用域
作用域决定了在其自定义的变量名的可见性和生命周期,在C、C++和java中,作用域是由花括号的位置决定的。例如:
{
int x = 12;
// Only x avaliable
{
int q = 96;
// Both x & q available
}
// Only x available
// q is "out of scope"
}
尽管以下代码在C和C++中是合法的,但是在java中不能这样写:
{
int x = 12;
{
int x = 96;
}
}
编译器将会在报告变量x已经定义过,在java里是不允许的。
-
2.3.2 对象的作用域
Java对象不具备和基本类型一样的生命周期。当用new创建一个Java对象时,他可以存活于作用域之外。
{
String s = new String("a string");
}
Java不用担心内存回收的问题,它有一个垃圾回收器,用来监视用new创建的所有对象,并辨别哪些不会再被引用的对象。随后,释放这些对象的内存空间。
2.4 创建新的数据类型:类
如果一切都是对象,那么是什么决定过了某一个类对象的外观和行为呢?你可能期望有一个名为“type”的关键字,但是我们一般习惯用class关键字来表示“我准备告诉你一种新类型的对象看起来像什么样子”。
class ATypeName{/* Class body goes here */};
你也可以通过 new来创建这种类型的对象:
ATypeName a = new ATypeName();
-
2.4.1 字段和方法
一旦定义了类,就可以在类中设置两种类型的元素:字段(有时被称作数据成员)和方法(有时被称作成员函数)。字段可以是任何类型的对象,可以通过其引用与其进行通信;也可以是基本类型的一种。如果字段是对某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象(使用new来实现)相关联。每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。下面是定义了一些数据成员的类示例:
class DataOnly {
int i;
float f;
boolean b;
}
创建一个它的对象
DataOnly d = new DataOnly();
然后引用对象成员并赋值。
d.i = 47;
d.f = 1.1f;
d.b = false;
基本成员默认值
若类的某个成员是基本数据类型,即使没有进行初始化,java也会确保它获得一个默认值。
2.5 方法、参数和返回值
java中的方法决定了一个对象能够接受什么样的消息。方法的基本组成部分包括:名称、参数、返回值和方法体。它的最基本的形式如下:
ReturnType methodName(/* Argument list */){
/* Method body */
}
返回类型描述的是在调用方法之后从方法返回的值。参数列表给出了要传给方法的信息的类型和名称。方法名和参数列表(她们合起来被称为“方法签名”)唯一的标识某个方法。
例如,假设有一个方法f(),不带任何参数,返回类型是int。如果有个名为a的对象,可以通过它调用f(),就可以这样写:
int x = a.f();
-
2.5.1 参数列表
假设某个方法接受String为其参数,必须置于某个类的定义内才能被正确的编译。
int storage(String s){
return s.length() * 2;
}
return 关键字的用法包括两方面:首先,它代表“已经做完,离开此方法”。其次,如果方法产生了一个值,这个值要放在return语句后面。
你可以定义返回任意想要的类型,如果不想返回任何值,可以指示此方法返回我void。
boolean flag() { return true; }
float naturalLogBase() { return 2.718; }
void nothing() { return; }
void nothing2() {}
若返回类型为void,则return 关键字唯一的作用就是退出方法。如返回类型不是void,那么无论从何地返回,编译器都会确保我们返回的是正确的类型。
2.6 构建一个Java程序
-
2.6.1 名字可见性
由于采用全新的机制,所以Java 能完全避免这些问题。为了给一个库生成明确的名字,采用了与Internet
域名类似的名字。事实上,Java 的设计者鼓励程序员反转使用自己的Internet 域名,因为它们肯定是独一
无二的。由于我的域名是BruceEckel.com,所以我的实用工具库就可命名为
com.bruceeckel.utility.foibles。反转了域名后,可将点号想象成子目录。 -
2.6.2 运用其他构件
如果想在自己的程序里使用预先定义好的类,那么编译器就必须知道怎么去定义它们。
如果你想讲某个新类添加到类库中,但却与已有的某个类名冲突。
为了解决这个问题,必须消除所有可能的混淆情况。可以使用import关键字来准确的告诉编译器你想要的类是什么。import指示编译器导入一个包,也就是一个类库(在其他语言中,一个库不仅包含类,还可能包括方法和数据;但是java中所有的代码都必须写在类里面。)
有了这些java标准类库构件,就不必写一长串的反转域名,例如:
import java.util.ArrayList;
-
2.6.3 static关键字
有两种情形,一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。另一种情形是,希望某个方法不与包含它的类的任何对象实例关联在一起。也就是说,即使没有创建对象,也能够调用这个方法。
static关键字可以满足这两方面的需要。当声明一个事物是static时,意味着这个域对象或方法不会与包含它的那个类的任何对象实例关联在一起。所以即使不创建某个类的任何对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法,因为非static域和方法必须知道它们一起运作的特定对象。
static字段,并对其初始化:
class StaticTest{
static int i = 47 ;
}
尽管我们制作了两个StaticTest 对象,但它们仍然只占据StaticTest.i的一个存储空间。这两个对
象都共享同样的i。请考察下述代码:
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
引用static变量有两种方法,①可以通过一个对象去定位它,如st2.i;②也可以通过其类名直接引用,而这对于非静态成员则不行。
StaticTest.i++;
2.7 你的第一个java程序
//HelloDate.java
import java.util.*;
public class HelloDate{
public static void main(String[] args){
System.out.println("Hello,it's:");
System.out.println(new Date());
}
}
类的名字必须和文件名相同。如果你像现在这样创建一个独立运行的程序,那么文件必须存在某个类与该文件同名(否则,编译器会报错),且那个类必须包含一个名为main()的方法形式如下所示:
public staitc void main (String[] args){}
其中,public关键字意指这是一个可由外部调用的方法。main()方法的参数是一个String对象的数组。在这个程序中并未用到args,但是Java编译器必须这么做,因为args要用来存储命令行参数。
2.8 注释和嵌入式文档
Java 里有两种类型的注释。第一种是传统的、C 语言风格的注释,是从 C++继承而来的。这些注释用一个
“/”起头,随后是注释内容,并可跨越多行,最后用一个“/”结束。注意许多程序员在连续注释内容的
每一行都用一个“*”开头,所以经常能看到象下面这样的内容:
/* This is a comment
* that continues
* across lines
*/
以一个“//”起头,表示这一行的所有内容都是注释。单行注释如下:
// This is a one-line comment
-
2.8.1 注释文档
代码注释文档是对文档的维护。方便在每次修改代码都能修改相应的文档,将代码同文档“链接”起来。
javadoc便是用于提取注释的工具,它是JDK安装的一部分,它采用了Java编译器的某些技术,查找程序内的特殊注释标签。 -
2.8.2 语法
所有所有javadoc命令都只能出现于“/”注释中。但和平常一样,注释结束于一个“/”。主要通过两种方式
来使用javadoc:嵌入的HTML,或使用“文档标记”。其中,“文档标记”(Doc tags)是一些以“@”开头
的命令,置于注释行的起始处(但前导的“”会被忽略)。
有三种类型的注释文档,它们对应于位于注释后面的元素:类、变量或者方法。也就是说,一个类注释正好位于一个类定义之前;变量注释正好位于变量定义之前;而一个方法定义正好位于一个方法定义的前面。如下面这个简单的例子所示:
/** 一个类注释 */
public class docTest {
/** 一个变量注释 */
public int i;
/** 一个方法注释 */
public void f() {}
}
- 2.8.3 嵌入式HTML
/**
* <pre>
* System.out.println(new Date());
* </pre>
*/
-
2.8.4 一些标签示例
详细可以查看代码一些可用于代码文旦搞的javadoc标签,以学习javadoc的各种不同的使用方法。
2.9 编码风格
代码风格:类名的首字母都要大写
class AllTheColorsOfTheRainbow{// ...
其他所有内容—方法、字段、以及对象引用名称,只是用标识符的第一个字母采用小写,后面的首字母大写。如下:
class AllTheColorsOfTheRainbow {
int anIntegerRepresentingColors;
void changeTheHueOfTheColor(int newHue) {
// ...
}
// ...
}
网友评论