mirror of
https://gitee.com/gaohongy/Java-Book.git
synced 2026-07-16 10:03:49 +00:00
修正全书错别字、术语统一和逻辑错误
This commit is contained in:
+8
-8
@@ -11,7 +11,7 @@
|
||||
|
||||
好了,这就是类与对象的基本内涵。类是一个模板(抽象的描述),对象是模板的一个实例(具体的)。这一点有点类似C中结构体的定义与结构体变量的关系,定义是抽象描述,变量是实体。
|
||||
|
||||
我们再深入讨论一下对象。对象(Object)这个概念广泛存在于我们的生活当中,一般只一个独立的个体,具备一定的特性(properties),并有一定的能力(capability)。例如,一辆A100:
|
||||
我们再深入讨论一下对象。对象(Object)这个概念广泛存在于我们的生活当中,一般指一个独立的个体,具备一定的特性(properties),并有一定的能力(capability)。例如,一辆A100:
|
||||
|
||||

|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
考虑到已经学习过C语言,使用C语言中的结构体来帮助理解抽象描述与实例的关系。
|
||||
|
||||
这个例子是描述平面中的一个圆。这里我们需要两组参数来描述圆,第一个参数是坐标位置(X、Y);另外一个是圆本生的描述,例如大小(半径r),可能还有颜色等等,简单来说,我们目前只有半径。如果从C语言出发,需要建立一个结构体来描述圆,请同学们写出该结构体的代码。
|
||||
这个例子是描述平面中的一个圆。这里我们需要两组参数来描述圆,第一个参数是坐标位置(X、Y);另外一个是圆本身的描述,例如大小(半径r),可能还有颜色等等,简单来说,我们目前只有半径。如果从C语言出发,需要建立一个结构体来描述圆,请同学们写出该结构体的代码。
|
||||
|
||||
如果从C语言出发,需要建立一个结构体来描述圆,代码如下:
|
||||
|
||||
@@ -135,7 +135,7 @@ public class Circle_Test {
|
||||
}
|
||||
```
|
||||
|
||||
**注意`setCircle`函数中的`this.x = x`这样的写法。因为这个对象本生有变量x、y、z;这些变量叫做成员变量,其作用域是在整个类的定义范围内;但是`setCircle`的形式参数中的x、y、z与成员变量重名了,但是语义不同。为了区分这两个变量,使用this关键字,`this.x`代表对象的成员变量,而`x`代表传递进来的参数。**
|
||||
**注意`setCircle`函数中的`this.x = x`这样的写法。因为这个对象本身有变量x、y、z;这些变量叫做成员变量,其作用域是在整个类的定义范围内;但是`setCircle`的形式参数中的x、y、z与成员变量重名了,但是语义不同。为了区分这两个变量,使用this关键字,`this.x`代表对象的成员变量,而`x`代表传递进来的参数。**
|
||||
|
||||
### 1.5. 构造函数
|
||||
|
||||
@@ -251,7 +251,7 @@ SDK中的一些类:
|
||||
|
||||
## 4. 类的成员
|
||||
|
||||
在本章节以前,我们也看到过类,也有相应的变量和函数,但是大多是静态的。本章开始,如同Circle类一样,定义的变量、函数都没有static的修饰,叫做实体变量和实体函数(区别于动态)。实体类型的变量和函数只能在引用对象的变量上面进行调用,而不能在类上进行调用。
|
||||
在本章节以前,我们也看到过类,也有相应的变量和函数,但是大多是静态的。本章开始,如同Circle类一样,定义的变量、函数都没有static的修饰,叫做实体变量和实体函数(区别于静态)。实体类型的变量和函数只能在引用对象的变量上面进行调用,而不能在类上进行调用。
|
||||
|
||||
定义在类中的变量、常量、函数都叫做类的成员,根据这些成员的不同性质,总结一下:
|
||||
|
||||
@@ -326,7 +326,7 @@ public class Test {
|
||||
```
|
||||
|
||||
1. 静态变量`numberOfObjects`的初始值是0,因此在主函数的第二行,使用`CircleWithStaticMembers.getNumberOfObjects()`取得这个静态变量的值的时候是0。这里证明了静态变量不依附对象存在,可以在类上面直接调用。
|
||||
2. `CircleWithStaticMembers`的两个构造函数(重载的构造函数)都对`numberOfObjects`进行了加1操作,语义是当创建一个`CircleWithStaticMembers’`对象的时候,让静态变量`numberOfObjects`加1,这样就得到了创建`CircleWithStaticMembers`对象的总数量。
|
||||
2. `CircleWithStaticMembers`的两个构造函数(重载的构造函数)都对`numberOfObjects进行了加1操作,语义是当创建一个`CircleWithStaticMembers’`对象的时候,让静态变量`numberOfObjects`加1,这样就得到了创建`CircleWithStaticMembers`对象的总数量。
|
||||
3. 注意后面的代码,得到`CircleWithStaticMembers`类实例化对象的个数可以使用静态变量`numberOfObjects`,也可以使用静态函数`getNumberOfObjects()。`且这两个静态成员即可以在类上面调用,也可以在对象的引用变量上调用。
|
||||
|
||||
**静态成员可以在类上访问,也可以在该类的引用变量上访问;这两种方式都是合法的,且没有任何的区别。**
|
||||
@@ -408,7 +408,7 @@ public class CircleWithPrivateDataFields {
|
||||
}
|
||||
```
|
||||
|
||||
这样清楚了,`radius` 这个变量被设置成私有,`getRadius()` 是共有函数,用于读取半径;`setRadius()` 是共有函数,用于设置半径。这两个函数就是 getter 和 setter 函数。特别注意,在 `setRadius` 函数中对传入参数进行了判断。这个函数好像是看门人,保证半径永远不为复数。
|
||||
这样清楚了,`radius` 这个变量被设置成私有,`getRadius()` 是共有函数,用于读取半径;`setRadius()` 是共有函数,用于设置半径。这两个函数就是 getter 和 setter 函数。特别注意,在 `setRadius` 函数中对传入参数进行了判断。这个函数好像是看门人,保证半径永远不为负数。
|
||||
|
||||
因为getter和setter函数用得太多了,eclipse 和大多Java的IDE为这个函数提供了快速构建方式。你只需要选择菜单`Source`-`Generate Getters and Setters ...`就会出现下面的窗口。
|
||||
|
||||
@@ -493,7 +493,7 @@ public class TestPassObject {
|
||||
|
||||
这个例子证明,如果是引用变量,在函数内部可以改变传入对象的成员变量值;其实这里使用的是setter函数改变半径的,因为半径是私有的;如果半径是public的,使用直接赋值也可以改变。
|
||||
|
||||
如果我么在`printAreas`函数执行完成后,打印n这个变量(作为参数times传入`printAreas`函数),会发现这个值还是5;因为基本类型的变量使用的是值传递。
|
||||
如果我们在`printAreas`函数执行完成后,打印n这个变量(作为参数times传入`printAreas`函数),会发现这个值还是5;因为基本类型的变量使用的是值传递。
|
||||
|
||||
## 7. 对象数组
|
||||
|
||||
@@ -590,7 +590,7 @@ public class TotalArea {
|
||||
|
||||
If the contents of an object cannot be changed once the object is created, the object is called an immutable(不变的) object and its class is called an immutable class. If you delete the set method in the Circle class in Listing 8.10, the class would be immutable because radius is private and cannot be changed without a set method.
|
||||
|
||||
这个概念需要了解,我们目前使用到的Immutable类是Spring,下一章中所有的 warp 类型也是 Immutable。
|
||||
这个概念需要了解,我们目前使用到的Immutable类是String,下一章中所有的 wrapper 类型也是 Immutable。
|
||||
|
||||
## 9. 变量作用域
|
||||
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@
|
||||
|
||||
## 2. 封装类型 Wrapper class
|
||||
|
||||
回忆一下前面我们学到的基本类型(primitive 类型),这些类型包括所有的以小写字母大头的Java预定义类型。
|
||||
回忆一下前面我们学到的基本类型(primitive 类型),这些类型包括所有的以小写字母开头的Java预定义类型。
|
||||
|
||||
1. byte
|
||||
2. short
|
||||
@@ -87,7 +87,7 @@ Character类的`Character.isDigit(char)`,`Character.isLetter(char)`这些函
|
||||
Byte b = 10; // 这是合法的
|
||||
Short s = 100;
|
||||
Integer i = 200;
|
||||
Long l = 999999L; // 字面量量缺省是int类型,需要标记成L(长整型)
|
||||
Long l = 999999L; // 字面量缺省是int类型,需要标记成L(长整型)
|
||||
Float f = 3.14F; // 字面量是double类型,需要标记成F(浮点类型)
|
||||
Double d = 33.33;
|
||||
```
|
||||
|
||||
+13
-13
@@ -8,7 +8,7 @@
|
||||
|
||||
在C语言中,降低代码冗余(增加代码复用性),一般使用函数来实现;但是函数是一个高纬度的抽象,和我们日常生活联系并不紧密。那么我们考虑日常生活中的例子。
|
||||
|
||||
通常我们描述一猫,只用说明猫是:界:动物界;门:脊椎动亚门;纲:哺乳纲;目:食肉目;科:猫科;属:猫属;种:猫种。
|
||||
通常我们描述一猫,只用说明猫是:界:动物界;门:脊椎动物亚门;纲:哺乳纲;目:食肉目;科:猫科;属:猫属;种:猫种。
|
||||

|
||||
|
||||
上述的图表示物种分类的一部分。这样描述一个物种的分类有很多好处:
|
||||
@@ -17,13 +17,13 @@
|
||||
2. 后代具备祖先的所有特性;
|
||||
3. 明确不同种之间的关系。
|
||||
|
||||
如果大家都清楚上述的规则,当我们讨论猫种的时候,就默认猫种具备祖先的所有特性,而不必再说明猫种是脊椎动物,胎生等这些它祖先所具备的特性。这种特性在Java种的类种也存在,这就是继承。
|
||||
如果大家都清楚上述的规则,当我们讨论猫种的时候,就默认猫种具备祖先的所有特性,而不必再说明猫种是脊椎动物,胎生等这些它祖先所具备的特性。这种特性在Java中的类中也存在,这就是继承。
|
||||
|
||||
### 1.2. Java中的继承(411)
|
||||
|
||||
例如要在平面上描述两个类,圆和矩形,那么这两个类好像有一些基本的特性是一致的。例如,填充颜色color,是否填充 filled,对象创建时间 dateCreated等。另外,需要对上述属性设置或者读取的方法:getColor(),setColor(),isFilled(),setFilled()等。
|
||||
|
||||
如果每个类都需要描述所有的这些特性好像有点浪费,如何做到降低代码冗余?我们使用到继承,如下图表述,GeometrocObject是父类,包括所有子类共有的特性(数据和方法);Circle和Rectangle继承于GeometrocObject。这样在编写Circle和Rectangle的时候就只需要对其特性进行描述就可以了;这两个类的共性在其父类中以及体现出来了,子类完全继承父类的所有特性(数据和方法)。
|
||||
如果每个类都需要描述所有的这些特性好像有点浪费,如何做到降低代码冗余?我们使用到继承,如下图表述,GeometricObject是父类,包括所有子类共有的特性(数据和方法);Circle和Rectangle继承于GeometrocObject。这样在编写Circle和Rectangle的时候就只需要对其特性进行描述就可以了;这两个类的共性在其父类中以及体现出来了,子类完全继承父类的所有特性(数据和方法)。
|
||||
|
||||

|
||||
|
||||
@@ -148,7 +148,7 @@ public class CircleFromSimpleGeometricObject extends SimpleGeometricObject {
|
||||
}
|
||||
```
|
||||
|
||||
1. 子类Circle使用`extend SimpleGeometricObject`表明继承于`SimpleGeometricObject`那么子类拥有父类的所有特性(数据和方法);
|
||||
1. 子类Circle使用`extends SimpleGeometricObject`表明继承于`SimpleGeometricObject`那么子类拥有父类的所有特性(数据和方法);
|
||||
2. 但是请注意,虽然子类拥有父类的所有特性,不意味子类就可以无限制的访问这些特性,例如`color`,`filled`,`dateCreated` 这些是父类的私有变量,在子类中并不能访问,而要通过对应的getter和setter函数访问(这些函数是公开的);
|
||||
3. `CircleFromSimpleGeometricObject`增加了自己的特性`radius`并设置成私有,以及对应的getter和setter函数;
|
||||
4. 子类中增加了自己的行为:`getArea()`、`getPerimeter`和`printCircle()`;
|
||||
@@ -275,7 +275,7 @@ class Man extends Person {
|
||||
}
|
||||
```
|
||||
|
||||
上诉例子中定义的 Man 类将出现编译错误,因为 Person 缺少不带参数的构造函数,Person 又没有显式的调用Person带参数的构造函数。修改 Man 类如下就可以了:
|
||||
上述例子中定义的 Man 类将出现编译错误,因为 Person 缺少不带参数的构造函数,Person 又没有显式的调用Person带参数的构造函数。修改 Man 类如下就可以了:
|
||||
|
||||
```java
|
||||
class Man extends Person {
|
||||
@@ -328,7 +328,7 @@ class Person {
|
||||
}
|
||||
```
|
||||
|
||||
main函数开起来比较奇怪,为什么在Faculty内中,又使用new 方法构造自己所在的类?其实大家不用太关心main函数在那里。首先因为java虚拟机要访问到这个静态函数作为程序的入口;其次,对于 main 函数,只要被构建的类对于main函数来说是可以访问就行了。上述所有类型都定义在一个文件间当中,这样如同是一个包;因此main函数可以访问该文件中的所有类;进而,也可以访问 Faculty 类,构建 Faculty 类的对象当然也是可以的。其实把main函数放在这个文件的任何类中都是可以的,只不过我们习惯放在 Faculty 这个类中(这个文档的文件名也是和这个类一致的)。
|
||||
main函数看起来比较奇怪,为什么在Faculty内中,又使用new 方法构造自己所在的类?其实大家不用太关心main函数在那里。首先因为Java虚拟机要访问到这个静态函数作为程序的入口;其次,对于 main 函数,只要被构建的类对于main函数来说是可以访问就行了。上述所有类型都定义在一个文件当中,这样如同是一个包;因此main函数可以访问该文件中的所有类;进而,也可以访问 Faculty 类,构建 Faculty 类的对象当然也是可以的。其实把main函数放在这个文件的任何类中都是可以的,只不过我们习惯放在 Faculty 这个类中(这个文档的文件名也是和这个类一致的)。
|
||||
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ public class Test {
|
||||
}
|
||||
```
|
||||
|
||||
Apple中没有toString()函数,但是其父类型后,因此Apple也得到了这样的能力。其实是间接调用父类型的toString()函数。
|
||||
Apple中没有toString()函数,但是继承其父类型后,因此Apple也得到了这样的能力。其实是间接调用父类型的toString()函数。
|
||||
|
||||
### 3.2. 覆盖父类型的函数
|
||||
|
||||
@@ -461,7 +461,7 @@ This is an apple.
|
||||
This is fruit.
|
||||
```
|
||||
|
||||
1、2行输出是`System.out.println(apple.toString());` 的结果。可以看到第1行是Apple类中`toString()`函数使用`super.toString()`调用了Fruit类中`toString`的结果。第3行使用Apple的函数`printFruitToString()`,本质也是使用了`super.toString()`。
|
||||
第1、2行输出是`System.out.println(apple.toString());` 的结果。可以看到第1行是Apple类中`toString()`函数使用`super.toString()`调用了Fruit类中`toString`的结果。第3行使用Apple的函数`printFruitToString()`,本质也是使用了`super.toString()`。
|
||||
|
||||
**注意:super关键字只能在直接子类中使用,表示其直接父类。**
|
||||
|
||||
@@ -671,7 +671,7 @@ java.lang.Object@7e774085
|
||||
上面文字使用下面的例子来解释:Apple这个例子中,我们再次扩展Apple,为一个GiantApple类:
|
||||
|
||||
```java
|
||||
sclass GiantApple extends Apple {
|
||||
class GiantApple extends Apple {
|
||||
|
||||
}
|
||||
|
||||
@@ -745,7 +745,7 @@ Orange orange = fruit; // 非法
|
||||
1. 真实对象是Fruit;
|
||||
2. 引用变量类型是 Orange;
|
||||
3. Orange是Fruit的子类型,其能力大于(准确的说是不小于)Fruit;
|
||||
4. 用较大的能力声明去定义一个较小能力的对象,而对其进行调用,可能造成能力不匹配的问题。例如,Orange 有一个`printInfo()`的方法,而Fruit没有,当用 `orange.pringInfo()`进行调用的时候,因为真实对象不具备这个能力,所以导致出错。
|
||||
4. 用较大的能力声明去定义一个较小能力的对象,而对其进行调用,可能造成能力不匹配的问题。例如,Orange 有一个`printInfo()`的方法,而Fruit没有,当用 `orange.printInfo()`进行调用的时候,因为真实对象不具备这个能力,所以导致出错。
|
||||
|
||||
因此:父类型赋值给子类型是非法的!其隐含的语义是 Fruit 是 Orange,这显然是不正确的。
|
||||
|
||||
@@ -908,15 +908,15 @@ public class TestArrayList {
|
||||
}
|
||||
```
|
||||
|
||||
掌握书上这个例子应该是足够了。注意ArrayList的声明方式,这是泛型申明。关于泛型,我们只需要知道如何使用就可以了,不用关心太多。
|
||||
掌握书上这个例子应该是足够了。注意ArrayList的声明方式,这是泛型声明。关于泛型,我们只需要知道如何使用就可以了,不用关心太多。
|
||||
|
||||
```java
|
||||
ArrayList<String> cityList = new ArrayList();
|
||||
```
|
||||
|
||||
尖括号中的就是泛型,表达的语义是ArrayList中转载的数据是什么类型。当然,如果是`ArrayList<Object>`那么可以装任何的引用类型。
|
||||
尖括号中的就是泛型,表达的语义是ArrayList中存放的数据是什么类型。当然,如果是`ArrayList<Object>`那么可以装任何的引用类型。
|
||||
|
||||
**注意:泛型中尖括号中的类型必须是引用类型,不能是原始类型。**
|
||||
**注意:泛型中尖括号内的类型必须是引用类型,不能是原始类型。**
|
||||
|
||||
需要了解ArrayList和Array间的相互转换:
|
||||
|
||||
|
||||
+6
-6
@@ -122,7 +122,7 @@ public class Circle extends GeometricObject {
|
||||
```java
|
||||
public class Rectangle extends GeometricObject {
|
||||
private double width;
|
||||
private Double height;
|
||||
private double height;
|
||||
|
||||
public Rectangle() {
|
||||
}
|
||||
@@ -164,7 +164,7 @@ public class Rectangle extends GeometricObject {
|
||||
}
|
||||
```
|
||||
|
||||
上述两个类都实现(impliment)了(覆盖了)`getArea()` 和 `getPerimeter()`两个函数(这两个函数都有函数体),且这两个类都没有使用 abstract 进行修饰,那么这两个类是可以被实例化的。
|
||||
上述两个类都实现(implement)了(覆盖了)`getArea()` 和 `getPerimeter()`两个函数(这两个函数都有函数体),且这两个类都没有使用 abstract 进行修饰,那么这两个类是可以被实例化的。
|
||||
|
||||
看看主函数如何使用多态调用的:
|
||||
|
||||
@@ -209,7 +209,7 @@ public class TestGeometricObject {
|
||||
|
||||
1. 实例化我没有任何实际的意义;
|
||||
2. 我只是描述我后代必须具备的能力;
|
||||
3. 后代的某些能力我知道是什么(函数原型),但是我不知道如何实现(算法),因为他们变化太多了;这些能力我就只描述成抽象的方法(只有函数申明,没有函数体)。
|
||||
3. 后代的某些能力我知道是什么(函数原型),但是我不知道如何实现(算法),因为他们变化太多了;这些能力我就只描述成抽象的方法(只有函数声明,没有函数体)。
|
||||
4. 有些能力我知道如何实现,这些能力就是非抽象的方法。
|
||||
|
||||
**抽象类不能实例化,但是作为参数,用作多态实现通用编程非常有用!**
|
||||
@@ -393,7 +393,7 @@ public interface Edible {
|
||||
|
||||
> An interface is treated like a special class in Java. Each interface is compiled into a separate bytecode file, just like a regular class. Like an abstract class, you cannot create an instance from an interface using the new operator, but in most cases you can use an interface more or less the same way you use an abstract class. For example, you can use an interface as a data type for a variable, as the result of casting, and so on.
|
||||
>
|
||||
> 接口如同一个特殊的类(class),每个接口被编译成一个对立的字节代码(bytecode)...
|
||||
> 接口如同一个特殊的类(class),每个接口被编译成一个独立的字节代码(bytecode)...
|
||||
>
|
||||
> 接口不能被实例化(使用new关键字),但是可以作为引用变量来引用实现了该接口的类的对象;这种情况下,接口的使用如同抽象类。
|
||||
|
||||
@@ -408,7 +408,7 @@ public interface Edible {
|
||||
1. 定义一个接口Edible(可食用的),其中包含一个抽象函数,返回如何烹饪的字符串描述;显然作为可食用这种能力(特性),在大自然中并不是某个类属所拥有的,而是跨越类属的一般特性;某些植物可以食用,某些动物可以食用;但不是所有的动物或者植物都可以食用。
|
||||
2. 作为动物(这里应该是脯乳动物),可以发声是脯乳动物的的共性,但是发出什么样的声音确是每个种类都不一样。因此定义了一个抽象相类Animal,有个抽象方法:sound。
|
||||
|
||||
上图中,虚线箭头表示接口实现,实线表示类继承(扩展)关系。上图中可以看到,水果(Fruit)都是可以食用的,因此水果这个抽象类(斜体表示)实现了可食用的接口;Chicken和Tiger都可以发声,因此由Animal这个抽象类扩展而来,且实现了发生的这个抽象方法;动物中只有Chicken可以食用,因此Chicken还实现了可食用的接口。
|
||||
上图中,虚线箭头表示接口实现,实线表示类继承(扩展)关系。上图中可以看到,水果(Fruit)都是可以食用的,因此水果这个抽象类(斜体表示)实现了可食用的接口;Chicken和Tiger都可以发声,因此由Animal这个抽象类扩展而来,且实现了发声的这个抽象方法;动物中只有Chicken可以食用,因此Chicken还实现了可食用的接口。
|
||||
|
||||
在代码中,先看看抽象类Animal:
|
||||
|
||||
@@ -469,7 +469,7 @@ class Tiger extends Animal {
|
||||
}
|
||||
```
|
||||
|
||||
Chicken很特殊,既可以发声,又能食用,因此由Anamal扩展而来,且实现Edible的接口:
|
||||
Chicken很特殊,既可以发声,又能食用,因此由Animal扩展而来,且实现Edible的接口:
|
||||
|
||||
```java
|
||||
class Chicken extends Animal implements Edible {
|
||||
|
||||
Reference in New Issue
Block a user