《JAVA核心技术卷I》阅读笔记[记录重点,梳理脉络]
C3 基本程序设计结构
*编译器将.java编译成字节码.class
*Double.POSITIVE_INFINITY
修饰符
final 变量名大写
public static final double CM_PER = 2.5; // 定义在main外
3.5 运算符
Math.pow(a, b) 幂运算
Math.round() 返回long
位运算:&, | , ^(xor), ~ 很重要,应用多 << , >> 注意符号位
P41:类型转换
三元操作符 ?:
&& || 短路设计
枚举类型:enum Size {SMALL, LARGE};
3.6 字符串
s.substring(start, end);
String.join(",", …); // ,拼接所有s
s1.equals(s2); // ==判断的是位置,不是字符串内容
码点和代码单元,有的符号虽然是一个码点,但需要两个代码单元来表示,所以遍历特殊string尽量不要使用s.charAt(i),使用s.codePoints().toArray()转为数组遍历(codePoints方法将其作为流返回)
P50 API
字符串构建器 StringBuilder API: P55
3.7 IN&OUT
- 输入
import java.util.*;
Scanner in = new Scanner(System.in);
String s = in.nextLine();
// .next 读取单词(空格分隔) .nextInt
- 输出
System.out.printf(“a %d”, n);
String s = String.format(“a %d”, n); // 创建字符串但不打印
各种时间相关的东西 new Date() - 文件
Scanner in = new Scanner(Paths.get("f.txt"), "UTF-8"); // 读取
PrintWriter out = new PrintWriter("f.txt", "UTF-8"); // 创建
3.8 控制流程
switch
- 带标签的break
jump:
while () {
while () {
break jump;
}
}
带标签的continue
3.9 大数值 BigInteger
3.10 数组
匿名数组及其传递
main接收命令行参数 String[] args
Array[API]: P84 toString, copyOf, copyOfRange, sort, binarySearch, fill, equals
多维数组快速打印:System.out.println(Arrays.deepToString(a));
C4 对象与类
类的关系:uses-a, has-a, is-a
类方法:构造器,更改器,访问器
- LocalData类
LocalData.now(), LocalData.of(y, m, d), .getYear(), .getMonthValue(), .getDayOfMonth(), .plusDays(n) …
4.3 自定义类
.java源文件中只能有一个public类,且文件名类名一样(若有构造器,也一样)。可有多个非公有类,编译后产生所有.class类文件。
类的实例域尽量标为private,用this.引用
封装:实例域为可变对象的引用时,访问器不可直接返回,return (Data) hireDay.clone();
类方法可以访问所属类的任意对象的私有域
- 实例域 final在构造器执行后要被设置好,且不可更改,大多为基本或不可变类型域
- 静态/类域 (private) static:属于类,不属于对象,可直接通过类名调用(为避免歧义,尽量别通过对象调用,下同)
- 静态常量 (public) static final:如Math.PI,通过类名调用。(静态常量可设置为public是因为定义为final即不可更改)
- 静态方法:不能操作对象,即没有this参数,通过类名调用。可用于1:无需访问对象,参数直接显式提供;2:访问类的静态域
- 工厂方法 factory method:利用静态方法来构造对象生成不同风格对象
- main:也是静态方法,不对对象操作
4.5 方法参数
java是按值调用 call by value,即得到参数的拷贝,无法修改,但在对象引用时可以修改对象,对于基本数据类型,则完全不能修改。
4.6 多重对象构造机制
- 重载 overloading:同一方法传入不同参数时编译器选择具体执行的方法(不限于构造器)。完整描述方法需要签名:方法名和参数类型。
- 域初始化
- 无参数构造器:类无构造器,系统会提供无参构造器置域为默认值。如果提供了都是有参构造器,则不能无参调用。
- 显式域初始化:在类定义声明中直接将值赋给域;构造器初始化域;初始化块(直接{}住代码)
- 参数名:aName, this.name
- this调用构造器:在构造器开始使用this(args),可以调用另一个构造器。
- 静态域初始化:声明时初始化值;静态初始化块 static { }
- *finalize方法:垃圾回收器清除对象前调用,以释放内存外其他资源(内存可自动回收)
4.7 包
- 类导入:import java.time.* 一个类可以使用所属包中的所有类以及其他包中的共有类。
- 静态导入:import static Math.* 可以导入静态方法和静态域,无需类名直接调用,但易读性不高。
-
将类放到包里:要将类放到某个包里,要
1:将包名放到源文件开头 package com.horstmann.corejava。
2:文件放到匹配的目录中
否则.class、 .java放入到默认包中(在基目录下,与com平行)
编译和运行类:
javac com/horstmann/corejava/Employee.java // 编译器
java com.horstmann.corejava.Employee // 解释器加载
4.8 类路径*====todoP137
4.9 文档注释 javadoc
由源文件生成HTML文档
import ..
/**
* A {@code Card} object represents a card, bala...
*/
public class Card
{
...
/**
* 方法注释:描述
* @param ...
* @return ...
* @throws ...可能抛出的异常
*/
public double raiseSalary()
{
...
}
...
}
此外还有
- 公有域(静态常亮)、
- 类注释标记:@author name, @version、
- 所有文档标记:@since 引入特征的版本描述,@deprecated 方法取代建议,@see 超链接
包注释:在包目录中添加单独文件:package.html or package-info.java
4.10 类设计技巧
- 数据私有
- 数据初始化
- 尽量包装基本类型
- 优先使用不可变的类,即对象的状态无法改变,可避免多线程并发更改,线程间安全共享。
C5 继承 inheritance
5.1 超类和子类
public class Manager extends Employee
- 覆盖方法 override:重写超类的某些方法。子类访问超类的私有域需要借助公有方法:超类的访问器 super.getSalary()
- 子类构造器:子类不能访问超类私有域,所以需要调用超类构造器对该部分私有域初始化,在子类构造器中首先调用super(args);
-
多态 polymorphism:
一个变量指示多重实际类型,如变量被声明为超类,但也可以引用子类。可定义超类数组时引用子类对象,但不可通过超类数组变量调用子类方法
继承,is-a,置换法则:程序中出现超类对象的地方都可以用子类置换(只加不减) - 子类方法调用过程 P155
-
阻止继承:final类:(包含编译器优化)
在类定义中加入final即为final类,不可拓展子类,其方法也成为final方法(但不包含域)。
也可单独将方法声明为final,子类就不能覆盖该方法 -
强制类型转换(少用):在忽视对象的实际类型后,使用对象的全部功能
Manager boss = (Manager) staff[0];
将子类引用赋给超类变量可直接实现(多态),将超类引用赋给子类变量需要类型转换。
类型转换之前可查看是否可行 if (staff[0] instanceof Manager) -
抽象类:祖先类更加抽象Qtodo
抽象类中可通过abstract关键词在祖先类中定义一个占位 抽象方法,在子类中再具体实现,包含抽象方法的类也要被声明为抽象的(即使不含抽象方法,也可以被声明为抽象类)。
public abstract class Person {
public abstract String getDescription();
}
拓展抽象类时,如果方法不全是抽象方法,就要将子类定义为抽象类。
抽象类不能被实例化,即不能创建类的对象,但可以定义抽象类对象变量引用非抽象子类对象
var people = new Person[2];
// Person[] people = ...
people[0] = new Employee(args);
people[0].getDescription(); // Person类中未定义,但是引用的Employee类中定义了该方法
- 受保护访问 protected:用于子类访问超类中的某些方法或者域,如Object.clone,慎用。
-
控制可见性的访问修饰符:public, private(本类可见), protected(本包和所有子类), 默认(本包)
本包和本类:包中类可调用本包中其他类
5.2 Object 超类
只有基本类型(primitive types, 如int. String boolean)不是对象,Object变量可以引用所有类型对象。
-
equals 方法:Object中将判断两个对象是否具有相同引用,但应该改为判断对象状态的相等性。
在子类定义equals时,先调用超类equals,再判断子类的实例域。 - 相等测试和继承 todo
-
hashCode 方法:
Object中的hashCode方法使每个对象都有默认散列码:对象的存储地址。
如果重新定义equals,就要重新定义hashCode,且返回值要一致,为了方便将对象插入到散列表中
定义hashCode,需要返回整型,并组合实例域的散列码:
public int hashCode() {
return Objects.hash(name, salary, hireDay);
}
-
toString 方法:一般返回格式:类名[域值]
类名:getClass().getName()+[“a=”+a, …]
子类调用 super.toString()+[…]
5.3 泛型数组列表 ArrayList
采用类型参数(type parameter)的泛型类(generic class)。
ArrayList<Employee> staff = new ArrayList<>();
staff.ensureCapacity(100); // 若评估出可能大小,或
ArrayList<Employee> staff = new ArrayList<>(100); // 两种方式初始化后并不包含任何元素
staff.size(); // 实际大小
staff.add(new Employee(...)); // 添加元素
staff.add(n, e); // 特定位置添加元素
staff.trimToSize(); // 调整大小
staff.set(i, harry); // i 必须先有元素
Employee e = staff.remove(n); // 获取元素同时删除元素
Employee e = (Employee) staff.get(i); // 访问元素需要进行数据转换
Employee[] a = new Employee[staff.size()];
list.toArray(a); // 或者转为数组a访问
for (Employee e: staff) // 遍历访问元素
pass
和没有使用类型参数的遗留代码进行交互,如果数组列表变量接收返回的ArrayList型,进行类型转换依然会受到警告,当确保转换的类型可行后,可进行标注:@SuppressWarnings("unchecked") ArrayList<Employee> result = (ArrayList<Employee>) employeeDB.find(query);
5.4 对象包装器和自动装箱
基本类型转换为类:Integer, Long, Float…,Character, Void, Boolean
如ArrayList 类型参数不能为基本类型,可以采用包装器
特性:1.值不可变;2.final类,不可定义子类;3.比较值用equals
-
Adv:
1.赋值算数运算符中autoboxing;
2.可将一些方法放到包装器中,如字符串转int:int x = Integer.parseInt(s);
- Disadv:ArrayList< Integer> 效率远低于int[]
API:
int intValue()
String toString(int i)
int parseInt(String s)
Integer valueOf(String s) // 以上三个可指定进制
5.6 参数数量可变的方法
printf(String fmt, Object... args) // Object... 等同 Object[]
5.7 枚举类
public enum Size {SMALL, MEDIUM, LARGE};
以上语句定义了一个类,有三个实例。
比较枚举类型的值时直接使用 = =
可在枚举类型中添加构造器方法域 API:P188
5.8 反射(重要)
5.9 继承的设计技巧
使用多态
少用反射
合理设计继承关系和方法
不要使用受保护的域,少用protected
C6 接口、lambda和内部类
*tips: 本次复习只查看PDF上笔记部分(2021.9.23)
markdown可用操作
- 全新的界面设计 ,将会带来全新的写作体验;序号和加粗
- 强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |