《Java编程思想》读书笔记(一)

第二章 一切都是对象

用句柄操纵对象

尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)

所有对象都必须创建

  1. 字符串的特殊初始化方式:用加引号的文字初始化
  2. 数据的保存位置:
    • 寄存器(处理器内部):最快的保存区域,根据需要由编译器分配
    • 堆栈(RAM中,随机访问存储器):创建程序时,Java 编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”,有些 Java 数据要保存在堆栈里——特别是对象句柄,但Java 对象并不放到其中
    • 堆(RAM中):保存Java对象,比堆栈更灵活,但在堆里分配存储空间时会花掉更长的时间
    • 静态存储(RAM中):指“位于固定位置”,可用static 关键字指出一个对象的特定元素是静态的,但 Java 对象本身永远都不会置入静态存储空间
    • 常数存储:直接置于代码内部,有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)
    • 非RAM存储器:“流式对象”和“固定对象”(磁盘中)
  3. 主要类型:置于堆栈中,更高效的存取
  4. Java数组:安全性,保证被初始化,而且不可在它的范围之外访问
    对象数组:实际创建的是一个句柄数组。而且每个句柄都会自动初始化成一个特殊值,并带有自己的
    关键字:null(空)
    主类型数组:将数组的内存划分成零

绝对不要清除对象

  1. 作用域:同时决定了它的“可见性”以及“存在时间”
  2. Java 有一个特别的“垃圾收集器”,它会查找用new 创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由那些闲置对象占据的内存,以便能由新对象使用

新建数据类型:类

主成员的默认值:若某个主数据类型属于一个类成员,那么即使不明确(显式)进行初始化,也可以保证它们获得一个默认值,这种保证却并不适用于“局部”变量——那些变量并非一个类的字段

方法、自变量和返回值

  1. Java 的方法只能作为类的一部分创建
  2. “静态”方法可针对类调用,毋需一个对象
  3. 自变量列表:实际传递的是“句柄”(对于前面提及的“特殊”数据类型 boolean,char,byte,short,int,long,float 以及double来说是一个例外。但在传递对象时,通常都是指传递指向对象的句柄)

构建Java程序

  1. static关键字:一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起,因为引用的是同样的内存区域,对方法来说,static 一项重要的用途就是帮助我们在不必创建对象的前提下调用那个方法
  2. 一个特殊的类库会自动导入每个Java 文件:java.lang
  3. main函数中的args保存了在命令行调用的自变量

第三章 控制程序流程

使用Java运算符

  1. 几乎所有运算符都只能操作“主类型”(Primitives)。唯一的例外是“=”、“==”和“!=”,它们能操作所有对象(也是对象易令人混淆的一个地方)。除此以外,String 类支持“+”和“+=”
  2. 主类型的赋值:由于主类型容纳了实际的值,而且并非指向一个对象的句柄,所以在为其赋值的时候,可将来自一个地方的内容复制到另一个地方
    对象的赋值:复制句柄,而两个句柄指向堆中同一个对象
  3. 自动递增和递减:对于前递增和前递减(如++A 或–A),会先执行运算,再生成值。而对于后递增和后递减(如A++或A–),会先生成值,再执行运算
  4. “==”比较的是对象句柄,equals()比较的是两个对象的实际内容(Java类库中的类),但如果是自己创建的类,equals()的默认行为是比较句柄,如需比较内容,需要在该类中修改equals()
  5. 逻辑运算符中的“短路”:逻辑表达式的任意部分都有可能不进行求值
  6. 按位运算符会对两个自变量中对应的位执行布尔代数,并最终生成一个结果
  7. 移位运算符:“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入 0;若值为负,则在高位插入1。“无符号”右移位运算符(>>>)使用了“零扩展”:无论正负,都在高位插入0
  8. “造型”运算符(强制类型转换):boolean类型不能执行该运算

执行控制

  1. 只有 for 循环才具备在控制表达式里定义变量的能力。对于其他任何条件或循环语句,都不可采用这种方法
  2. 标签:对Java 来说,唯一用到标签的地方是在循环语句之前,它需要紧靠在循环语句的前方,设置标签的唯一理由是:我们希望在其中嵌套另一个循环。由于 break 和 continue 关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方
  3. switch语句要求使用一个选择因子,并且必须是 int 或char 那样的整数值

第四章 初始化和清除

方法重载

  1. 区分重载的方法:每个过载的方法都必须采取独一无二的自变量类型列表,不能根据返回值类型来区分过载的方法
  2. 如果在类中已经定义了一个构建器(无论是否有自变量),编译程序不会再帮我们自动生成一个默认构建起
  3. this关键字:在一个方法的内部希望获得当前对象的句柄。通常,当我们说this 的时候,都是指“这个对象”或者“当前对象”,而且它本身会产生当前对象的一个句柄
  4. 在构建器中调用构建器:不可以同时调用两个构建器;构建器必须是执行的第一条语句;在类的内部不允许除构建器之外的任何方法调用构建器static关键字:不可从static方法内部访问非static成员

清除:收尾和垃圾回收(?)

垃圾收收集器(GC)只知道释放由new关键字分配的内存,所以不知道如何释放对象的“特殊”内存。为了解决这个问题,Java提供了一个名为finalize()的方法。如果定义了finalize()方法,那么java在回收该类的一个对象时就会调用这个方法。在finalize()中要指定回收前要进行的操作。finalize正好在垃圾回收之前被调用,也就一样的具有了时间的不确定性

成员初始化

  1. “向前引用”,注意初始化顺序,且变量的初始化会在调用任何方法(包括构建器)之前执行,自动初始化(将变量初始化为默认值)在构建器执行初始化之前执行
  2. static对象初始化:在创建某个类的第一个对象时初始化,后期再创建该类的对象时不会重新初始化,且static对象初始化在非static对象初始化之前