曾经有人说,作为Java程序员如果没有卷过这本书,就算不上是真正的Java程序员,那么我就也来卷卷它吧。下面是我的读书摘录笔记。
《Java 核心技术卷1 基础知识》第一章 Java程序设计概述 笔记_码农UP2U的博客-优快云博客
《Java 核心技术卷1 基础知识》第二章 Java 程序设计环境 笔记_码农UP2U的博客-优快云博客
《Java 核心技术卷1 基础知识》第三章 Java 的基本程序设计结构 笔记_码农UP2U的博客-优快云博客
目录
4.1 面向对象程序设计概述
面向对象程序设计(object-oriented programming, OOP)
面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。
传统的结构化程序设计通过设计一系列的过程(即算法)来求解问题。一旦确定了这些过程,就要开始考虑存储数据的适当方式。这就是 Pascal 语言的设计者 Niklaus Wirth 将其著作命名为《算法 + 数据结构 = 程序》的原因。
在 Wirth 的这个书名中,算法是第一位的,数据结构是第二位的,这就明确地表述了程序员的工作方式。首先要确定如何操作数据,然后再决定如何组织数据的结构,以便于操作数据。而 OOP 却调换了这个次序,将数据放在第一位,然后再考虑操作数据的算法。
4.1.1 类
类(class)是构造对象的模板或蓝图
由类构造(construct)对象的过程称为创建类的实例(instance)
用 Java 编写的所有代码都位于某个类里面
封装(encapsulation)是处理对象的一个重要概念。从形式上看,封装就是将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式。对象中的数据称为实例字段(instance field),操作数据的过程称为方法(method)。作为一个类的实例,特定对象都有一组特定的实例字段值。这些值的集合就是这个对象的当前状态(state)。只要在对象上调用一个方法,它的状态就有可能发生改变。
封装的关键在于,绝对不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。
可以通过扩展其他类来构建新类。
所有其他类都扩展自这个 Object 类
在扩展一个已有的类时,这个扩展后的新类具有被扩展类的全部属性和方法。你只需要在新类中提供适用于这个新类的新方法和数据字段就可以了。通过扩展一个类来建立另外一个类的过程称为继承(inheritance)
4.1.2 对象
对象的三个主要特性:
- 对象的行为(behavior)
- 对象的状态(state)
- 对象的标识(identity)
4.1.3 识别类
首先从识别类开始,然后再为各个类添加方法
识别类的一个经验是在分析问题的过程中寻找名词,而方法对应着动词
对于每一个动词,都要识别出负责完成相应动作的对象
4.1.4 类之间的关系
在类之间,最常见的关系有
- 依赖(uses-a)
- 聚合(has-a)
- 继承(is-a)
依赖(dependence),即“uses-a”关系,是一种 最明显的、最常见的关系。
如果一个类的方法使用或操纵另一个类的对象,我们就说一个类依赖于另一个类。
应该尽可能地将相互依赖的类减至最少。关键是,如果类 A 不知道 B 的存在,它就不会关心 B 的任何改变。用软件工程的术语来说,就是尽可能减少类之间的耦合。
聚合(aggregation),即“has-a”关系。包容关系意味着类 A 的对象包含类 B 的对象。
继承(inheritance),即“is-a”关系,表示一个更特殊的类与一个更一般的类之间的关系。如果类 A 扩展类 B,类 A 不但包含从类 B 继承的方法,还会有一些额外的功能。
UML Unified Modeling Language 统一建模语言
4.2 使用预定义类
Math 类只封装了功能,它不需要也不必隐藏数据。由于没有数据,因此也不必考虑创建对象和初始化它们的实例字段,因为根本没有实例字段。
4.2.1 对象与对象变量
要想使用对象,首先必须构造对象,并指定其初始状态。
使用构造器(constructor)构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。
内置的(built-in)类型
适应性如何
设置任务就交给了类库的设计者。如果类设计得不完善,其他的程序员可以很容易地编写自己的类,以便增强或替代(replace)系统提供的类
要想构造一个 Date 对象,需要在构造器前面加上 new 操作符
new Date();
这个表达式构造了一个新对象。这个对象被初始化为当前的日期和时间。
可以对刚刚创建的对象应用一个方法。对新构造的 Date 对象应用 toString 方法
Stirng s = new Date().toString;
希望构造器可以多次使用,因此,需要将对象存在在一个变量中:
Date birthday = new Date();
对象变量 birthday ,它引用了新构造的对象
对象与对象变量之间存在着一个重要的区别
Date deadline;
定义了一个对象变量 deadline,它可以引用 Date 类型的对象。变量 deadline 不是一个对象,而且实际上它也没有引用任何对象。此时还不能在这个变量上使用任何 Date 方法。下面的语句
s = deadline.toString();
将产生编译错误。
必须首先初始化变量 deadline,这有两个选择,可以初始化这个变量,让它引用一个新构造的对象:
deadline = new Date();
也可以设置这个变量,让它引用一个已有的对象。
deadline = birthday;
现在,这两个变量都引用同一个对象。
要认识到重要的一点:对象变量并没有实际包含一个对象,它只是引用一个对象。
在 Java 中,任何对象变量的值都是对存储在另外一个地方的某个对象的引用。
Date deadline = new Date();
有两部分。表达式 new Date() 构造了一个 Date 类型的对象,它的值是对新创建对象的一个引用。这个引用存储在变量 deadline 中。
可以显式地将对象变量设置为 null,指示这个对象变量目前没有引用任何对象。
所有的 Java 对象都存储在堆中。当一个对象包含另一个对象变量时,它只是包含着另一个堆对象的指针。
在 Java 中,必须使用 clone 方法获得对象的完整副本。
4.2.2 Java 类库中的 LocalDate 类
Date 类的实例有一个状态,即特定的时间点
时间是用距离一个固定时间点的毫秒数表示的,这个时间点就是所谓的纪元(epoch),它是 UTC 时间 1970 年 1 月 1 日 00:00:00 。UTC 就是 Coordinated Universal Time (国际协调时间),与大家熟悉的 GMT (即 Greenwich Mean Time 格林尼治时间)一样,是一种实用的科学标准时间
类库设计者决定将保存时间与给时间点命名分开。所以标准 Java 类库分别包含类两个类:一个是用来表示时间点的 Date 类;另一个是用大家熟悉的日历表示法表示日期的 LocalDate 类。
不要使用构造器来构造 LocalDate 类的对象。实际上,应当使用静态工厂方法(factory method),它会代表你调用构造器。
LocalDate.now()
会构造一个新对象,表示构造这个对象时的日期
可以提供年、月、日来构造对应一个特定日期的对象:
LocalDate.of(1999,12,31)
通常我们都希望将构造的对象保存在一个对象变量中:
LocalDate newYearsEve = LocalDate.of(1999, 12, 31);
一旦有来一个 LocalDate 对象,可以用方法 getYear、getMonthValue 和 getDayOfMonth 得到年、月、日。
Date 类也有得到日、月、年的方法,分别是 getDay、getMonth 以及 getYear,不过这些方法已经废弃。
JDK 提供了 jdeprscan 工具来检查你的代码中是否使用了 Java API 已经废弃的特性
4.2.3 更改器方法与访问器方法
plusDays 方法会生成一个新的 LocalDate 对象
更改器方法(mutator method)
访问器方法(accessor method)
date = date.minusDays(today - 1);
DayOfWeek weekday = date.getDayOfWeek();
int value = weekday.getValue();
这里遵循国际管理,即周末是一周的末尾,星期一就返回 1,星期二返回 2,依此类推。星期日则返回 7。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class CalendarTest
{
public static void main(String[] args) {
LocalDate date = LocalDate.now();
int month = date.getMonthValue();
int today = date.getDayOfMonth();
date = date.minusDays(today - 1);
DayOfWeek dayOfWeek = date.getDayOfWeek();
int value = dayOfWeek.getValue();
System.out.println("Mon Tue Wed Thu Fri Sat Sun");
for (int i = 0; i < value; i ++) {
System.out.print(" ");
}
while (date.getMonthValue() == month) {
System.out.printf("%3d", date.getDayOfMonth());
if (date.getDayOfMonth() == today) {
System.out.print("*");
} else {
System.out.print(" ");
}
date = date.plusDays(1);
if (date.getDayOfWeek().getValue() == 1) {
System.out.println("");
}
}
}
}
4.3 用户自定义类
主力类(workhorse class)
4.3.1 Employee类
最简单的类定义形式为:
class ClassName
{
field1;
field2;
...
constructor1;
constructor2;
...
method1;
method2;
...
}
程序清单 4-2 EmployeeTest/EmployeeTest.java
import java.time.LocalDate;
public class EmployeeTest
{
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);