mirror of
https://github.com/LingCoder/OnJava8.git
synced 2026-08-23 22:43:28 +08:00
调整排版,文字润色
This commit is contained in:
@@ -2,28 +2,28 @@
|
||||
|
||||
# 第三章 万物皆对象
|
||||
|
||||
>如果我们说不同的语言,我们会感觉到一个不同的世界!— Ludwig Wittgenstein (1889-1951)
|
||||
> 如果我们说不同的语言,我们会感觉到一个不同的世界!— Ludwig Wittgenstein (1889-1951)
|
||||
|
||||
尽管 Java 基于 C++ ,但 Java 是一种更纯粹的面向对象程序设计语言。Java 和 C++ 都是混合语言。在 Java 中,语言设计者认为混合并不像 C++ 那样重要。混合语言允许多种编程风格;这也是 C++ 支持与 C 语言的向后兼容性原因。因为 C++ 是 C 语言的超集,所以它也包含了许多 C 语言的不良特性,这可能使得 C++ 在某些方面过于复杂。
|
||||
相比 C++ ,Java 是一种更纯粹的面向对象编程语言。虽然它们都是混合语言,但在 Java 中,设计者们认为混合的作用并非像 C++ 那般重要。混合语言允许多种编程风格,这也是 C++ 支持向后兼容 C 的原因。正因为 C++ 是 C 语言的超集,所以它也同时包含了许多 C 语言的不良特性,这使得 C++ 在某种程度上过于复杂。
|
||||
|
||||
Java 语言预设你已经编写过面对对象的程序。在此之前,你必须将自己的思维置于面对对象的世界。在本章中你将了解 Java 语言的基本组成,学习 Java (几乎)万物皆对象的思想。
|
||||
Java 语言假设你已接触过面向对象编程。开始学习之前,我们需要将思维置于面向对象的世界。本章你将了解到 Java 语言的基本组成,学习 Java (几乎)万物皆对象的思想。
|
||||
|
||||
<!-- You Manipulate Objects with References -->
|
||||
## 对象操纵
|
||||
|
||||
名字的意义在于,当我们听到“玫瑰”这个词时,就会想到一种闻起来很甜蜜的的花。(引用自 莎士比亚,《罗密欧与朱丽叶》)。
|
||||
“名字代表什么?玫瑰即使不叫玫瑰,也依旧芬芳”。(引用自 莎士比亚,《罗密欧与朱丽叶》)。
|
||||
|
||||
所有的编程语言都会操纵内存中的元素。有时程序员必须要有意识地直接或间接地操纵它们。示例:在 C/C++ 语言中是通过指针来完成操作的。
|
||||
所有的编程语言都会操纵内存中的元素。有时程序员必须要有意识地直接或间接地操纵它们。在 C/C++ 中,对象的操纵是通过指针来完成的。
|
||||
|
||||
Java 使用万物皆对象的思想和特有的语法方式来简化问题。虽然万物皆可为对象,但你操纵的标识符实际上是只对象的“引用” [^1]。 示例:我们可以将这种“引用”想象成电视(对象)和遥控器(引用)之间的关系。只要拥有对象的“引用”,就可以操纵该“对象”。我们无需直接接触电视,只要掌握遥控器就可以在房中自由地控制电视(对象)的频道和音量。此外,没有电视机,遥控器也可以单独存在。引申来说,仅仅因为你有一个“引用”并不意味着你必然有一个关联的“对象”。
|
||||
Java 利用万物皆对象的思想和独特的语法方式来简化问题。虽万物皆可为对象,但我们所操纵的标识符实际上是只对象的“引用” [^1]。 举例:我们可以将这种“引用”想象成电视(对象)和遥控器(引用)之间的关系。只要拥有对象的“引用”,就可以操纵该“对象”。换成白话,我们无需直接接触电视,就可通过遥控器自由地控制电视(对象)的频道和音量。此外,没有电视机,遥控器也可以单独存在。引申来说,仅仅因为你有一个“引用”并不意味着你必然有一个关联的“对象”。
|
||||
|
||||
下面来创建一个 String 的引用,用于保存单词语句。代码示例:
|
||||
下面来创建一个 **String** 的引用,用于保存单词语句。代码示例:
|
||||
|
||||
```java
|
||||
String s;
|
||||
```
|
||||
|
||||
这里我们仅仅只是创建了一个 String 对象的引用,而非对象。直接拿来使用会出现错误:因为此时你并没有给变量 s 赋值--附加任何引用的对象。通常更安全的做法是:在声明变量引用的同时初始化对象信息。代码示例:
|
||||
这里我们仅仅只是创建了一个 **String** 对象的引用,而非对象。直接拿来使用会出现错误:因为此时你并没有给变量 `s` 赋值--附加任何引用的对象。通常更安全的做法是:在声明变量引用的同时初始化对象信息。代码示例:
|
||||
|
||||
```java
|
||||
String s = "asdf";
|
||||
@@ -76,7 +76,7 @@ Java 预设了每种基本类型的初始内存占用大小。 这些大小标
|
||||
| double | 64 bits |IEEE754 | IEEE754 | Double |
|
||||
| void | — | — | — | Void |
|
||||
|
||||
所有的数值类型都是有正/负符号的。布尔(boolean)类型的大小没有明确的规定,通常定义为采用文字 “true” 和 “false”。基本类型有自己对应的包装类型,如果你希望在堆内存里表示基本类型的数据,就需要用到它们的包装类。代码示例:
|
||||
所有的数值类型都是有正/负符号的。布尔(*boolean*)类型的大小没有明确的规定,通常定义为采用文字 “true” 和 “false”。基本类型有自己对应的包装类型,如果你希望在堆内存里表示基本类型的数据,就需要用到它们的包装类。代码示例:
|
||||
|
||||
```java
|
||||
char c = 'x';
|
||||
@@ -180,7 +180,7 @@ Java 的变量只有在其作用域内才可用。缩进使得 Java 代码更易
|
||||
}
|
||||
```
|
||||
|
||||
在上例中, Java 便编译器会在提示变量 x 已经被定义过了。因此,在 C 和 C++ 中可以于更大作用域中“隐藏”变量的能力在 Java 中是不被允许的。 因为 Java 的设计者认为这样的定义会混淆编程。
|
||||
在上例中, Java 便编译器会在提示变量 x 已经被定义过了。因此,在 C/C++ 中可以于更大作用域中“隐藏”变量的能力在 Java 中是不被允许的。 因为 Java 的设计者认为这样的定义会混淆编程。
|
||||
|
||||
<!-- Scope of Objects -->
|
||||
### 对象作用域
|
||||
@@ -214,7 +214,7 @@ Java 对象与基本类型具有不同的生命周期。当我们使用 `new`
|
||||
|
||||
在上例中,我们介绍了如何创建一个新的类型,尽管这个类里只有一行注释。但是我们一样可以通过 `new` 关键字来创建一个对象。如下:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
ATypeName a = new ATypeName();
|
||||
```
|
||||
|
||||
@@ -223,9 +223,9 @@ ATypeName a = new ATypeName();
|
||||
<!-- Fields -->
|
||||
### 属性
|
||||
|
||||
当我们创建好了一个类之后,我们可以往类里存放两种类型的元素。方法(**method**)和属性(**field**)。类的属性可以是基本类型。如果类的属性是对象的话,那么必须要初始化该引用将其关联到一个实际的对象上(通过之前介绍的创建对象的方法)。每个对象都会为其属性保留独立的存储空间。通常,属性不再对象之间做共享。下面是一个包含部分属性的类的代码示例:
|
||||
当我们创建好了一个类之后,我们可以往类里存放两种类型的元素。方法(*method*)和属性(*field*)。类的属性可以是基本类型。如果类的属性是对象的话,那么必须要初始化该引用将其关联到一个实际的对象上(通过之前介绍的创建对象的方法)。每个对象都会为其属性保留独立的存储空间。通常,属性不再对象之间做共享。下面是一个包含部分属性的类的代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
class DataOnly {
|
||||
int i;
|
||||
double d;
|
||||
@@ -235,13 +235,13 @@ class DataOnly {
|
||||
|
||||
除非持有数据,不然这个类不能做任何事。在此之前,我们可以通过下面的代码示例来创建它的对象:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
DataOnly data = new DataOnly();
|
||||
```
|
||||
|
||||
我们必须通过这个对象的引用来指定属性值。格式:对象名称.方法名称或成员名称。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
data.i = 47;
|
||||
data.d = 1.1;
|
||||
data.b = false;
|
||||
@@ -249,7 +249,7 @@ class DataOnly {
|
||||
|
||||
如果你想修改对象内部包含的另一个对象的数据,可以通过这样的格式修改。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
myPlane.leftTank.capacity = 100;
|
||||
```
|
||||
|
||||
@@ -286,7 +286,7 @@ class DataOnly {
|
||||
<!-- Methods, Arguments,and Return Values -->
|
||||
### 方法使用
|
||||
|
||||
在许多语言(如 C 和 C++)中,术语函数(**function**)用于描述命名子程序。在 Java 中,我们使用术语方法(**method**)来表示“做某事的方式”。
|
||||
在许多语言(如 C 和 C++)中,术语函数(*function*)用于描述命名子程序。在 Java 中,我们使用术语方法(*method*)来表示“做某事的方式”。
|
||||
|
||||
在 JAVA 中,方法决定着对象能接收哪些信息。方法的基础部分包含名称、参数、返回类型、方法体。格式如:
|
||||
|
||||
@@ -298,44 +298,44 @@ class DataOnly {
|
||||
|
||||
#### 返回类型
|
||||
|
||||
方法的返回类型表明了当你调用它时会返回的结果类型。参数列表则显示了可被传递到方法内部的参数类型及名称。方法的名称和参数列表被统称为**方法签名**(**signature of the method**)。签名作为方法的唯一性标识。
|
||||
方法的返回类型表明了当你调用它时会返回的结果类型。参数列表则显示了可被传递到方法内部的参数类型及名称。方法的名称和参数列表被统称为**方法签名**(*signature of the method*)。签名作为方法的唯一性标识。
|
||||
|
||||
Java 中的方法只能作为类的一部分创建。它只能被对象所调用 [^4],并且该对象必须有权限来执行调用。若对象调用错误的方法,则程序将在编译时报错。
|
||||
|
||||
我们可以通过在对象名的后面跟上 `.` 符号+方法名及其参数来调用一个方法。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
[对象引用].[方法名](参数1, 参数2, 参数3);
|
||||
```
|
||||
|
||||
若方法不带参数,例如一个对象 a 的方法 f 不带参数并返回 int 型结果,我们可以如下表示。代码示例:
|
||||
若方法不带参数,例如一个对象 `a` 的方法 `f` 不带参数并返回 **int** 型结果,我们可以如下表示。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
int x = a.f();
|
||||
```
|
||||
|
||||
上例中方法 f 的返回值必须兼容接收的变量 x 。这种调用方法的行为有时被称为向对象传递信息。面向对象编程可以被总结为:向对象传递信息。
|
||||
上例中方法 `f` 的返回值必须兼容接收的变量 `x` 。这种调用方法的行为有时被称为向对象传递信息。面向对象编程可以被总结为:向对象传递信息。
|
||||
|
||||
<!-- The Argument List -->
|
||||
#### 参数列表
|
||||
|
||||
方法参数列表指定传递给方法的信息。正如你可能猜到的,这些信息 —— 就像 Java 中的其他所有信息 —— 采用对象的形式。参数列表必须指定对象类型和每个对象的名称。同样,我们并没有直接处理对象,而是在传递对象引用 [^5] 。但是引用的类型必须是正确的。如果方法需要 String 参数,则必须传入 String,否则编译器将报错。
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
int storage(String s) {
|
||||
|
||||
return s.length() * 2;
|
||||
}
|
||||
```
|
||||
|
||||
此方法计算并返回某个字符串的长度。参数 s 的类型为 String 。将 字符串变量 s 传递给 storage() 后,我们可以将其视为任何其他对象一样 —— 我们可以想起传递信息。在这里,我们调用 length() 方法,它是一个 String 方法,返回字符串长度。字符串中每个字符的大小为16位或两个字节。您还可以看到 **return** 关键字,它执行两项操作。首先,它意味着“方法执行结束”。其次,如果方法有返回值,那么该值就位于 **return** 语句之后。这里,返回值是通过计算
|
||||
此方法计算并返回某个字符串的长度。参数 `s` 的类型为 **String** 。将 字符串变量 s 传递给 `storage()` 后,我们可以将其视为任何其他对象一样 —— 我们可以想起传递信息。在这里,我们调用 `length()` 方法,它是一个 String 方法,返回字符串长度。字符串中每个字符的大小为16位或两个字节。您还可以看到 **return** 关键字,它执行两项操作。首先,它意味着“方法执行结束”。其次,如果方法有返回值,那么该值就位于 **return** 语句之后。这里,返回值是通过计算
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
s.length() * 2
|
||||
```
|
||||
产生的。在方法中,我们可以返回任意的数据。如果我们不想方法返回什么数据,则可以通过给方法标识 `void` 来表明这是一个无需返回值的方法。 代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
boolean flag() {
|
||||
return true;
|
||||
}
|
||||
@@ -369,11 +369,11 @@ void nothing2() {
|
||||
|
||||
Java 采取了一种新的方法避免了以上这些问题:为一个库生成一个明确的名称,Java 创建者希望我们反向使用自己的网络域名,因为域名通常是唯一的。自从我的域名为 MindviewInc.com 开始,我就将我的 foibles 工具库命名为 com.mindviewinc.utility.foibles。根据你的域名的反向信息,`.`代表着一个子目录。
|
||||
|
||||
在 Java 1.0和 Java 1.1中,域扩展 com,edu,org,net 等按惯例大写,因此类库中会出现这样类似的名称:Com.mindviewinc.utility.foibles。然而,在 Java 2 的开发过程中,他们发现这会导致问题,所以现在整个包名都是小写的。此机制意味着所有文件都自动存在于自己的命名空间中,文件中的每个类都具有唯一标识符。这样,该语言可以防止名称冲突。
|
||||
在 Java 1.0 和 Java 1.1 中,域扩展 com,edu,org,net 等按惯例大写,因此类库中会出现这样类似的名称:Com.mindviewinc.utility.foibles。然而,在 Java 2 的开发过程中,他们发现这会导致问题,所以现在整个包名都是小写的。此机制意味着所有文件都自动存在于自己的命名空间中,文件中的每个类都具有唯一标识符。这样,该语言可以防止名称冲突。
|
||||
|
||||
使用反向 URL 是一种新的命名空间方法,在此之前尚未有其他语言这么做过。Java 中有许多这些“创造性”地解决问题的方法。正如你想象,如果我们未经测试就添加一个功能并用于生产,那么在将来发现该功能的问题再想纠正,通常为时已晚。(有些问题错误得足以从语言中删除。)
|
||||
|
||||
使用反向 URL 将命名空间与文件路径相关联不会导致BUG,但它却给源代码管理带来麻烦。例如在 com.mindviewinc.utility.foiles 这样的目录结构中,我们创建了com、mindviewinc 空目录。它们存在的唯一目的就是用来表示这个反向的 URL。
|
||||
使用反向 URL 将命名空间与文件路径相关联不会导致BUG,但它却给源代码管理带来麻烦。例如在 `com.mindviewinc.utility.foiles` 这样的目录结构中,我们创建了 `com`、`mindviewinc` 空目录。它们存在的唯一目的就是用来表示这个反向的 URL。
|
||||
|
||||
这种方式似乎为我们在编写 Java 程序中的某个问题打开了大门。空目录填充了深层次结构,它们不仅用于表示反向 URL,还用于捕获其他信息。这些长路径基本上用于存储有关目录中的内容的数据。如果你希望以最初设计的方式使用目录,这种方法可以从“令人沮丧”到“令人抓狂”,对于产生的 Java 代码,你基本上不得不使用专门为此设计的 IDE 来管理代码。例如 NetBeans,Eclipse 或 IntelliJ IDEA。实际上,这些 IDE 都为我们管理和创建深度空目录层次结构。
|
||||
|
||||
@@ -387,13 +387,13 @@ Java 采取了一种新的方法避免了以上这些问题:为一个库生成
|
||||
|
||||
要解决此问题,你必须通过使用 `import` 关键字来告诉 Java 编译器具体要使用的类。import 表示编译器引入一个包,它是一个类库。(在其他语言中,库可以包含函数和数据以及类,但请记住,Java 中的所有活动都在类中进行。)大多数时候,我们都在使用 JAVA 标准库中的组件。有了这些,你不用担心长的反向域名。你只用说,例如:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
```
|
||||
|
||||
上例可以告诉编译器使用位于标准库 util 下的 ArrayList 类。在 util 包含许多类,我们可以使用通配符 `*` 来导入其中部分类,无需显式导入。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
import java.util.*;
|
||||
```
|
||||
|
||||
@@ -411,32 +411,32 @@ import java.util.*;
|
||||
|
||||
**static** 关键字(从 C++ 采用)就符合我们的要求。当我们说某些东西是静态的时,它意味着该字段或方法不依赖于任何特定的对象实例 。 即使我们从未创建过该类的对象,也可以调用其静态方法或访问静态字段。相反,对于普通的非静态字段和方法,我们必须要先创建一个对象并使用该对象来访问该字段或方法,因为非静态字段和方法必须与替对象关联 [^6] 。
|
||||
|
||||
一些面向对象的语言使用类数据(**class data**)和类方法(**class method**)这样的术语来表述静态。静态的数据意味着该数据和方法仅存在于类中,而非类的任何实例对象中。有时 Java 文献也使用这些术语。我们可以通过在类的属性或方法前添加 `static` 修饰来表示这是一个静态属性或静态方法。 代码示例:
|
||||
一些面向对象的语言使用类数据(*class data*)和类方法(*class method*)这样的术语来表述静态。静态的数据意味着该数据和方法仅存在于类中,而非类的任何实例对象中。有时 Java 文献也使用这些术语。我们可以通过在类的属性或方法前添加 `static` 修饰来表示这是一个静态属性或静态方法。 代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
class StaticTest {
|
||||
static int i = 47;
|
||||
}
|
||||
```
|
||||
|
||||
现在,即使你创建了两个 StaticTest 对象,但是静态变量 i 仍只占一份存储空间。两个对象都会共享相同的变量 i。 代码示例:
|
||||
现在,即使你创建了两个 `StaticTest` 对象,但是静态变量 `i` 仍只占一份存储空间。两个对象都会共享相同的变量 `i`。 代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
StaticTest st1 = new StaticTest();
|
||||
StaticTest st2 = new StaticTest();
|
||||
```
|
||||
|
||||
st1.i 和 st2.i 的值都是47,因为它们属于同一段内存。引用静态变量有两种方法。在前面的示例中,我们可以通过一个对象来命名它;例如,st2.i。同时,你也可以通过它的类名直接调用它(这是非静态成员不能执行的操作):
|
||||
`st1.i` 和 `st2.i` 的值都是 47,因为它们属于同一段内存。引用静态变量有两种方法。在前面的示例中,我们可以通过一个对象来命名它;例如,`st2.i`。同时,你也可以通过它的类名直接调用它(这是非静态成员不能执行的操作):
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
StaticTest.i ++;
|
||||
```
|
||||
|
||||
`++` 运算符将会使变量结果 + 1。此时 st1.i 和 st2.i 的值就变成了48了。
|
||||
`++` 运算符将会使变量结果 + 1。此时 `st1.i` 和 `st2.i` 的值就变成了 48 了。
|
||||
|
||||
使用类名直接引用静态变量的首选方法,因为它强调了变量的静态属性。类似的逻辑也适用于静态方法。我们可以通过对象引用静态方法,就像使用任何方法一样,也可以使用特殊的附加语法 classname.method()来直接调用静态属性或方法 [^7]。 代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
class Incrementable {
|
||||
static void increment() {
|
||||
StaticTest.i++;
|
||||
@@ -444,17 +444,17 @@ class Incrementable {
|
||||
}
|
||||
```
|
||||
|
||||
上例中 Incrementable 类调用静态方法 increment()。后者再使用 `++` 运算符递增静态变量 int i。我们依然可以先实例化对象再调用该方法。 代码示例:
|
||||
上例中 `Incrementable` 类调用静态方法 `increment()`。后者再使用 `++` 运算符递增静态变量 **int** `i`。我们依然可以先实例化对象再调用该方法。 代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
Incrementable sf = new Incrementable();
|
||||
sf.increment();
|
||||
```
|
||||
|
||||
当然了,首选的方法是直接通过类来调用它。代码示例:
|
||||
|
||||
```JAVA
|
||||
Incrementable.increment();
|
||||
```java
|
||||
Incrementable.increment();
|
||||
```
|
||||
|
||||
相比非静态的对象,`static` 属性改变了创建数据的方式。同样,当 `static` 关键字修饰方法时,它允许我们无需创建对象就可以直接通过类的引用来调用该方法。正如我们所知,`static` 关键字的这些特性对于应用程序入口点的 main() 方法尤为重要。
|
||||
@@ -466,7 +466,7 @@ Incrementable.increment();
|
||||
|
||||
最后,我们来开始编写第一个完整的程序。我们使用 Java 标准库来展示一个字符串和日期。
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
|
||||
// objects/HelloDate.java
|
||||
import java.util.*;
|
||||
@@ -482,44 +482,41 @@ public class HelloDate {
|
||||
|
||||
在这本书中,代码块的第一行,我将使用注释行,其中包含文件的路径信息(使用本章的目录名对象),后跟文件名。我的工具可以根据这些信息自动提取和测试书籍的代码,你也可以通过参考第一行注释信息轻松地在 Github 库中找到相应的代码示例。
|
||||
|
||||
如果你想在代码中使用到一些额外的库,那么你需要在程序文件的开始处使用 **import** 关键字来导入它们。之所以说是额外的,因为有一些库已经默认自动包含到每个文件里了。例如:**java.lang** 包。
|
||||
如果你想在代码中使用到一些额外的库,那么你需要在程序文件的开始处使用 **import** 关键字来导入它们。之所以说是额外的,因为有一些库已经默认自动包含到每个文件里了。例如:`java.lang` 包。
|
||||
|
||||
现在打开你的浏览器在 [Oracle](https://www.oracle.com/) 上查看文档。如果你还没有在 [Oracle](https://www.oracle.com/) 网站上下载 JDK 文档,那就趁现在 [^8] 。查看包列表,你会看到 Java 附带的所有不同的类库。
|
||||
|
||||
选择 **java.lang**。这里显示的是该库中所有类的列表。由于 **java.lang** 隐式包含在每个 Java代码文件中,因此这些类是自动可用的。**java.lang** 中没有列出 **Date** 类,所以我们必须将其导入库才能使用它。如果你不清楚某个类名或者想查看所有的类,可以在 Java 文档中选择“Tree”。
|
||||
选择 `java.lang`。这里显示的是该库中所有类的列表。由于 `java.lang` 隐式包含在每个 Java代码文件中,因此这些类是自动可用的。`java.lang` 中没有列出 **Date** 类,所以我们必须将其导入库才能使用它。如果你不清楚某个类名或者想查看所有的类,可以在 Java 文档中选择“Tree”。
|
||||
|
||||
现在,我们可以找到 Java 附带的每个类。使用浏览器的“查找”功能查找 “Date”。搜索结果中将会列出 java.util.Date,显而易见,它在 util 库中,所以我们必须导入 java.util.* 才能使用 Date。
|
||||
|
||||
如果你在文档中选择 java.lang,然后选择 System,你会看到 System 类中有几个字段,如果你选择 `out`,你会发现它是一个静态的 PrintStream 对象。 所以,即使我们没有使用 new 创建, `out` 对象就已经存在并可以使用。 `out` 对象可以执行的操作取决于 PrintStream 。 其在文档中的描述中显示为超链接,如果单击该链接,我们将可以看到 PrintStream 所对应的方法列表。(更多详情,将在本书后面介绍。) 现在我们重点说的是 println() 这个方法。 它的作用是 “将信息输出到控制台,并以换行符结束。” 既然如此,我们可以这样编码来输出信息到控制台。 代码示例:
|
||||
|
||||
```JAVA
|
||||
如果你在文档中选择 `java.lang`,然后选择 **System**,你会看到 System 类中有几个字段,如果你选择 `out`,你会发现它是一个静态的 **PrintStream** 对象。 所以,即使我们没有使用 new 创建, `out` 对象就已经存在并可以使用。 `out` 对象可以执行的操作取决于 PrintStream 。 其在文档中的描述中显示为超链接,如果单击该链接,我们将可以看到 PrintStream 所对应的方法列表。(更多详情,将在本书后面介绍。) 现在我们重点说的是 println() 这个方法。 它的作用是 “将信息输出到控制台,并以换行符结束。” 既然如此,我们可以这样编码来输出信息到控制台。 代码示例:
|
||||
|
||||
```java
|
||||
System.out.println("A String of things");
|
||||
```
|
||||
|
||||
每个 java 源文件中允许有多个类。与此同时,源文件的名称必须要和其中一个类名相同,否则编译器将会报错。每个独立的程序应该包含一个 main 方法作为程序运行的入口。其方法签名和返回类型如下。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
关键字 `public` 表示方法可以被外界访问到。( 更多详情将在 **隐藏实现** 章节讲到)
|
||||
main() 方法的参数是一个 字符串(String) 数组。 参数 `args` 并没有在当前的程序中使用到,但是 Java 虚拟机强制要求必须要有。 这是因为它们被用于保存命令行中的参数。
|
||||
main() 方法的参数是一个 字符串(**String**) 数组。 参数 `args` 并没有在当前的程序中使用到,但是 Java 虚拟机强制要求必须要有。 这是因为它们被用于保存命令行中的参数。
|
||||
|
||||
下面我们来看一段有趣的代码:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
System.out.println(new Date());
|
||||
```
|
||||
|
||||
上面的示例中,我们创建了一个日期(Date)型对象并将其转化为字符串类型并输出到控制台中。 一旦这一行语句执行完毕,我们就不再需要该日期对象了。这时, JAVA 的垃圾回收器就可以将其占用的内存回收,我们无需去主动清除它们。
|
||||
上面的示例中,我们创建了一个日期(**Date**)型对象并将其转化为字符串类型并输出到控制台中。 一旦这一行语句执行完毕,我们就不再需要该日期对象了。这时, JAVA 的垃圾回收器就可以将其占用的内存回收,我们无需去主动清除它们。
|
||||
|
||||
查看 JDK 文档,我们可以看到, **System** 类下还有很多其他有用的方法。( Java 的牛逼之处还在于,它拥有一个庞大的标准库资源。) 代码示例:
|
||||
|
||||
```JAVA
|
||||
|
||||
```java
|
||||
// objects/ShowProperties.java
|
||||
public class ShowProperties {
|
||||
public static void main(String[] args) {
|
||||
@@ -574,7 +571,7 @@ javac HelloDate.java
|
||||
|
||||
此外,仅仅是执行的话,则可以键入:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
java HelloDate
|
||||
```
|
||||
我们将会获得信息反馈,日期输出。这是我们编译和运行本书中每个程序(包含main())的过程 [^9]。但是,本书的源代码在根目录中也有一个名为 **build.gradle** 的文件,其中包含用于自动构建,测试和运行本书文件的 **Gradle** 配置。当您第一次运行 `gradlew` 命令时,**Gradle** 将自动安装(前提已安装Java)。
|
||||
@@ -585,7 +582,7 @@ java HelloDate
|
||||
|
||||
Java 的代码约定规范(*Code Conventions for the Java Programming Language*)[^10] 要求类名的首字母大写。 如果类名是由多个单词构成的,则每个单词的首字母都应大写(不采用下划线来分隔)例如:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
class AllTheColorsOfTheRainbow {
|
||||
// ...
|
||||
```
|
||||
@@ -593,7 +590,7 @@ class AllTheColorsOfTheRainbow {
|
||||
|
||||
这种风格也被称之为“驼峰式”。对于几乎所有其他方法,字段(成员变量)和对象引用名称 - 除了标识符的首字母是小写之外其他规范与类的命名一致。代码示例:
|
||||
|
||||
```JAVA
|
||||
```java
|
||||
class AllTheColorsOfTheRainbow {
|
||||
int anIntegerRepresentingColors;
|
||||
void changeTheHueOfTheColor(int newHue) {
|
||||
|
||||
Reference in New Issue
Block a user