mirror of
https://gitee.com/gaohongy/Java-Book.git
synced 2026-07-16 09:43:50 +00:00
修正全书错别字、术语统一和逻辑错误
This commit is contained in:
+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间的相互转换:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user