Title: Core Java — Volume I Fundamentals
Edition: Eleventh Edition
Author: Cay S. Horstmann
读书笔记:对原书的归纳、总结、补充和疑问。
文章目录
- Chapter 4 Objects and Classes
- 4.1 Introduction to Object-Oriented Programming
- 4.2 Using Predefined Classes
- 4.3 Defining Your Own Classes
- 4.3.1 An `Employee` Class
- 4.3.2 Use of Multiple Soucr Files
- 4.3.3 Dissecting the Employee Class
- 4.3.4 First Steps with Cosntructors
- 4.3.5 Declaring Local Vairables with `var`
- 4.3.6 Working with `null` Reference
- 4.3.7 Implicit and Explicit Parameters
- 4.3.8 Benefits of Encapsulation
- 4.3.9 Class-Based Access Privileges
- 4.3.10 Private Methods
- 4.3.11 Final Instance Fields
- 4.4 Static Fields and Methods
- 4.5 Method Parameters
- 4.6 Object Construction
- 4.7 Packages
- 4.8 JAR Files
- 4.9 Documentation Comments
- 4.10 Class Design Hints
Chapter 4 Objects and Classes
4.1 Introduction to Object-Oriented Programming
没有OOP,人们本来是如何工作的?
以往的编程,注重于算法和数据储存方式,可以说: Algorithm + Data Structure = Programmes
有了 OOP,人们首先思考 Data 然后才是 Algorithm。
4.1.1 Classes
Encapsulation 的意义:
我们之所以想要发明这些繁琐的概念,在于我们想把每一个object 弄成一个 Black Box。程序员们和 objects 通过他的methods 交流,那么只要这些method不改,里面的data到底是如何储存的,以及里面的methods到底是如何实现的,别人没有必要去care。
4.1.2 Objects
Objects 最重要的三个特征:behaviour, state and identity.
4.1.3 Identifying Classes
Look for nouns for Classes.
Look for verbs for Methods.
4.1.4 Relationships between Classes
Objects 之间的三种关系:
- Dependence
好的系统设计当中,我们应该尽量减少相互依赖的 classes。这样可以减少系统的耦合。 - Aggregation
- Inheitance
4.2 Using Predefined Classes
4.2.1 Objects and Object Variables
Date 这种常见的数据类型,为什么不是 built-in type 而是一个 class 呢?
原因是在于 Java designers 考虑到了全球各地区对于 Date的要求不同,而且设计成 Date 方便更改替换。
Object vs Object variables: Object variables 仅仅是 objects 的 reference。
4.2.2 The LocalDate
Class of the Java Library
这个 Class 被创建的基本原因就在于在不同的文化当中对时间、日期的命名方式是不一样的。
好的OOP 设计会把不同的概念放在不同的 Class 当中。
所以 LocalDate
是更好的,用来处理日期的类。使用的时候我们不用 constructor 而是用 static factory。
Date
本身也有一些处理日期的methods 但是都已经过时了 deprecated
。
4.2.3 Mutator and Accessor Methods
Mutator:methods that will change the internal states of an object
Accessor:只读 对象 的状态而不修改。
我们只需要知道一个 Class 的 接口interface 就可以利用其完成复杂的任务,而不用了解其实现细节。
4.3 Defining Your Own Classes
4.3.1 An Employee
Class
You can only have one public class but any number of non-public classes in a source file
什么意思?在这里作者给我们展现的代码是一个public class 中间内含了一个 没有标注的 class。
我记得没有标注意味着 package access 不是吗?
4.3.2 Use of Multiple Soucr Files
Javac 会自动compile 你用的到 class,而且是按照新的为标准。
4.3.3 Dissecting the Employee Class
public methods
: any method in any class could access it.
private fields
: no any other class other than itself could access it.
由于目前还不太清楚 public、private是不是对 fields、methods 有着不同的意义,所以在这里先写清楚。
其实如果 private
几乎没有被用在 fields 里面,那么为什么不默认呢?我的意思是,为什么可以允许 fields 被声明成 public
呢?
4.3.4 First Steps with Cosntructors
Constructors features:
- same name as the calss
- can have more than one constructor
- can take zero, one, or more parameters
- has no return value
- must be calld with
new
4.3.5 Declaring Local Vairables with var
var
can only be used in local variables, as for parameters and fields, you must always decare their type.
从前面的发展历程来看,var
是Java 10之后才有的特点,那么Java 的设计师们是为什么要借鉴这一特点呢?
(除了避免重复声明以外)
4.3.6 Working with null
Reference
这一章倒是有几个要点需要注意:
- Primitive types can never be
null
- 那么如果我们的 constructor 或者是 methods 需要 take 某个 object as parameter,那么保证其不是 null 呢?
- 手动设置一个
null
value 为另一个合适的值; - Java 9:
Objects.requrieNonNullElse(n , "otherValues");
- Tough love:
Objects.requrieNonNull(n, "warning message");
- 手动设置一个
又看见了我以前不懂的几个细节,为什么是 Objects 而不是 Object ?
4.3.7 Implicit and Explicit Parameters
Explicit Parameters: listed in the method declaration.
Implicit Paramterts: this
which refers the object itself.
4.3.8 Benefits of Encapsulation
这一章我觉得很重要。
因为从一开始学习 Java 的时候就被告知:private fields, public setters/getters,既然要提供修改的方式,为什么不直接 public fields 呢?这章就是着重讲了 Encapsulation 的好处。
-
修改内部的具体实现,除了 getter/setter 以外,其他都不受影响。
Changing the internal implementation without affecting any code other than the methods of the class. -
Mutators/Setter 可以帮忙检查数据是否有错。
Mutator methods can perform error checking, whereas code that simply assigns to a field may lead to errors.
Caution!
Avoid writing accessors to mutable objects.
不过 mutable objects是什么呢?我隐约记得 strings 是 immutable 的,python 里面的 array 也是mutable 的。在Java 里面有什么判断 mutable objects的方法吗?
后面提到答案了,戳 Final Instance Fields
4.3.9 Class-Based Access Privileges
Wow!
我们知道一个: a method can access the private fields of an object.
但是实际上: a method could access the private fields of all objects if its class.
例如:
Class Employy{
private int age;
public boolean equals(Employee other){
return age == other.age;
}
}
//其实也不难理解,age 其实全称不是 this.age 吗。 既然可以 this.age 当然可以 other.age。
4.3.10 Private Methods
Private methods vs. Public methods in the view of designers:
private methods 你可以随时扔掉,反正也没人能用,也没人看到…
4.3.11 Final Instance Fields
Wow 上面还在疑惑,这下答案就来了。
final
modifier 就是可以用来实现 immutable class 的好助手。因为 immutable class = none of the methods could change the fields. 不过正是因为这个特点所以你还得保证 constructor 完成的时候,你的final fields 必须已经初始化了。(不然你也不能改了呀!这不是final嘛…)
4.4 Static Fields and Methods
4.4.1 Static Fields
哈哈哈…
The term “static” is a meaningless holdover from C++
Static fields = class fields
4.4.2 Static constants
constants 貌似大多数都会被声明成 static。因为不然的话你又不改它,你弄这么多个object, each object has a copy of it 有啥用呢。
Note:
If you look at the
System
class, you will notice a methodsetOut
that setsSystem.ou
t to a different stream. You may wonder how that method can change the value of a final variable. However, thesetOut
method is a native method, not implemented in the Java programming language. Native methods can bypass the access control mechanisms of the Java language. This is a very unusual workaround that you should not emulate in your programs.
4.4.3 Static Methods
Static Methods do not operate on objects.
(Although speaking of syntax, you could do that)
什么时候应该用 static methods:
- when explicit parameters are sufficient.
- when a method only need to access static fields of the class.
4.4.4 Factory Methods
皮毛,皮毛····
这个稍微提到了一下 factory methods,为什么需要呢? 为什么不直接就用 constructor 吗?
- constructor 不能随便命名,这样你要是想生成一个特别的实例,光看名字是看不出来的。
- constructor 不能 return a sub-class (具体有什么好处我还看不出来。)
4.4.5 The main
Method
main
method 看起只有当 当前class 作为主要启动类的时候才会被执行。
作者说这一个特点其实可以用来做 unit testing,这原来就是 unit testing 的原理吗?
4.5 Method Parameters
几个要点:
- Java use call-by-value only.
- 就算是 object reference 被用作了 method parameter, Java 也会先copy reference。Object references are passed by value.
可能有人问了,object reference are passed by value,这和 pass by reference 有啥区别呢?区别在于in Java, you can’t chnage the object paremeter to refer to another object.
4.6 Object Construction
4.6.1 Overloading
4.6.2 Default Field Initialization
作者告诫:
fields 和 local variables 不一样。
Fields 的话即使没有initialize,虽然这是不好的习惯,但是还是可以的,会被设置为default。
但是 you must always explicity initialise local variables.
(why tho?)
4.6.3 The Constructor with No Arguments
Free no-argument constructor only when you have no constructors.
4.6.4 Explicit Field Initialization
4.6.5 Parameter Names
4.6.6 Calling Anther Constructor
this
key world 还有一个意思:
If the first statement of a constructor has this form: this(...)
Then it refers another constuctor of the same class.
4.6.7 Initialization Blocks
Wow! I didn’t know this.
每一个类可以有任意数量的 代码块,这些代码块在创建实例的时候首先执行,这一特点通常用来初始化。
static block:
有什么用?
To initialise a static field.
All static field initialiser and static initialisation blocks are executed in the order in which they occur in the class declaration.
4.6.8 Object Destruction and the finalize
method
Wow!
我知道 finalize 是用来删除不再使用的实例的,但是在Java automatic gabbage collection 的基础上,为什么还需要这个呢?
原因是:
object 就算是不用 memory,也可能用 着resources,比如一个文件,这种情况下,资源就必须回收。不过回收的方法已经改变了很多了,finalize
已经 deprecated.
4.7 Packages
4.7.1 Package Names
其实可以理解成文件夹啦,没什么特殊的。
4.7.2 Class Importation
Purely for the sake of convienience.
4.7.3 Static Imports
A form of the import
statement permits the importing of static methods and fields, not just classes.
4.7.4 Addition of a Class into a Package (?)
4.7.5 Package Access
Default access (就是不写 public
也不写 private
) 就是 package access.
原来 Java 自身的 source code 也会有质量问题。
最如今的做法是: use modules to encapsulate packages.
4.7.6 The Class Path
path to the class must = package name
Windows: class paths separated by :
UNIX: class paths separated by ;
Caution:
javac (java compiler), compile 的时候 always look for files in the current director no matter what.
java (JVM launcher), will not look for current directory if “.” directory is not on the class path.
class path, imports, compilation, package 等等乱七八糟的东西其实是这样的:
- Class file: source code 被 javac compile 之后生成的东西,JVM 运行的时候会直接运行这个。
- Souce file:还没有被 compile,含有 source code 的东西。
- compile 的时候发现 source code 用了某一个没见过的 class 怎么办?javac 得先确定这个 class 是放在哪个package里面的。比如
import java.util.*;
import com.horstmann.corejava.*;
...
...
Employee e = new Employee();
//Employy 在什么地方呢?在 java.util 还是 com.hostmann.java 里面呢?
- 这些package又是放在什么地方的呢?这取决于 class path。
- 如果你的 source code 用了某一个已经 compile 了的class,javac 还会检查那个compile后的class file 是不是最新版,不是的话还会继续重新 compile。
- 一个 source file 只能有一个 public class,但是可以有很多个其他的 non-public class,non-public class 有 default package access, 所以如果你的source code 用了同一个 package 的某个non-public class,compiler 会检查同一个 package 下的所有 source file。
4.7.7 Setting the Class Path
java -classpath
再次注意,你想要把 Class path 设置成 environment variable 是可以的。但是记住,在设置后的情况下,JVM 可能不一定跑哦,again it will not look for the current directory if ‘.’ is not on the class path.
4.8 JAR Files
JAR 的好处(为啥要搞这个玩意儿):
- 把所有 file 打包成一个给用户。
- 可以包含好多不同种类的文件,比如图片、声音。
- JAR 是压缩的格式。
4.8.1 Creating JAR Files
标准格式,各种 flag 请自行 google。
jar options file1, file2 ...
4.8.2 The Manifest
It describes special features of the archive.
4.8.3 Executable JAR Files
jar cvfe MyProgram.jar com.mycompany.mypkg.MainAppClass {files to add}
我试着把这一段翻译成人话:
请把 {files to add} 这一堆文件给我打包成一个新的 jar file,新的 jar file 叫做 MyProgram.jar。运行的时候的话就请运行 mycompany.mypkg.MainAppClass 吧。
e = entrypoint
也可以在 Manifest 里面声明。
4.8.4 Multi-Release JAR Files
What is the sole purpose of multi-release of JAR Files?
- To make your JAR Files work with multiple JDK releases
4.8.5 A Note about Command-Line Options
4.9 Documentation Comments
javadoc
为啥要搞这个玩意儿呢?
把 documentation 和 code 放在一起,方便generate documentation。
4.9.1 Comment Insertion
/**
documentation
*/
如果想要在 documentation 里面附带附件,附件要放在 doc-files 下面。
4.9.2 Class Comments
class comments must be put after import
statements directly before class definition.
4.9.3 Method Comments
4.9.4 Field Comments
你最好只用 documentation public static fields 啦。
4.9.5 General Comments
4.9.6 Package Comments
Two choices to write package comments:
- packge-info.java
- HTML file named package.html
4.9.7 Comments Extraction
4.10 Class Design Hints
wow 都是比较实际的建议。
- Always keep data private.
- Always initialise data.
- Don’t use too many basic types in a class.
- Not all fields need individual field accessors and mutators.
- Break up classes that have too many responsbilities.
- Make the names of your classes and methods relfect their responsibility.
- Prefer immutable classes.