《JAVA核心技术卷I》阅读笔记[记录重点,梳理脉络]

《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()
 	  {
 	  	...
 	  }
 	  ...
 }

此外还有

  1. 公有域(静态常亮)、
  2. 类注释标记:@author name, @version、
  3. 所有文档标记:@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可用操作

  1. 全新的界面设计 ,将会带来全新的写作体验;序号和加粗
  2. 强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.
博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左
上一篇:数据库的用法


下一篇:MyBatis的复杂查询与动态标签