Thinking in java 读书笔记1

Thinking in Java 4th Edition

Chap 1 对象入门

Chap 2 一切都是对象

1. Java中对象的操作都是传址。需要注意的是String类型,String类型的操作都会产生新的对象。

public class Test01 {

public String str = "Hello";

public char[] c = { 'a', 'b', 'c' };

public void change(String s, char[] c) {

s = "Ok";

c[0] = 'A';

System.out.println(s == this.str);//false,String赋值操作会产生新的对象

System.out.println(c == this.c);//true,还是原来的地址

}

public void change(String s)

{

this.str = "Ok";

}

public static void main(String[] args) {

Test01 t1 = new Test01();

t1.change(t1.str, t1.c);

System.out.println(t1.str+","+String.valueOf(t1.c));//Hello,Abc

t1.change(t1.str);

System.out.println(t1.str);//Ok

}

}

2. 对象通过new创建。保存对象的位置:

a) 寄存器:最快,地址由编译器分配,没有直接控制权。

b) 栈:位于RAM,访问速度仅次于寄存器,先入后出,存放对象“句柄”,不存放new创建的对象。

c) 堆:位于RAM,存放java对象,不用关注存放对象的生存时间和对象的大小。

d) 静态存储:static关键字定义对象存储的位置,程序运行期间,静态存储中的数据可以随时调动,Java对象不会存储于静态存储区。位于RAM

e) 常数存储:直接置于程序代码内部,不可修改,位于ROM

f) RAM存储:各种流对象。

3. 基本类型(9种):

a) boolean: 1bit

b) byte: 8bit

c) char: 16bit

d) short:16bit

e) int: 32bit

f) long: 64bit

g) float: 64bit

h) double: 64bit

i) void

4. 变量的作用域:不同于C/C++,如下代码在Java中不允许:

int area = 10;

{

int area = 20;

}

5. 类实例化的不同对象含有相同的方法,各自维护不用的数据成员存储空间。类的基本类型数据成员会有默认值,局部变量没有默认值。

6. 类文档标记:

a) @see:查看其它类

b) @version:版本信息

c) @author:作者

方法标记:

a) @param:参数

b) @return:返回值说明

c) @exception:异常信息

d) @deprecated:不推荐使用

 

Chap 3 控制程序流程

1. 关系运算符==对于基本类型比较的是值,对于对象数据类型,比较的是对象的地址。类方法equals默认使用==比较对象引用地址,可以重写equals以达到想要的内容比较。

public class Test02 {

private int id;

@Override

public boolean equals(Object obj) {

if (null == obj) {

return false;

}

if (this == obj) {

return true;

}

if (obj.getClass() != this.getClass()) {

return false;

}

return this.id == ((Test02) obj).id;

}

public static void main(String[] args) {

Test02 t1 = new Test02();

Test02 t2 = new Test02();

System.out.println(t1.equals(t2));// true

}

}

2. 逻辑运算符||&&的短路特性会使后面的表达式、函数不执行。如:false==true&&1/0,能够编译通过,后面的1/0不会执行。

3. 移位运算符:<<左移(相当于*2),有符号右移>>(相当于/2,值正:高位补0;值负:高位补1),无符号右移>>>(无论正负,高位补0)。charbyteshort右移时会自动转换成int,因此有符号右移>>可能不正确,无符号右移动没有这种问题。

4. Java没有sizeof,因为java是平台无关的。

5. int小的类型(char/byte/short)在算数或者按位运算是会转型为int。小数的字面常量是double类型,因此float f = 1.3;语句是不正确的。

6. gotojava的关键字,但是没有使用。java支持标签,通过break labelcontinue label进行标签跳转。

 

Chap 4 初始化和清除

1. 构造函数在对象创建时自动调用,构造函数的名字必须和类名相同。

2. 返回值不能用于判断方法重载,因为方法的调用有时并不关心返回值。

3. this关键字用于获取当前对象的句柄。构造方法中通过this调用其他构造函数只能在最开始的代码调用,并且只能调用一次。

4. static方法不能调用非static方法,非static方法可以调用static方法(没有什么意义)。

5. finalize方法垃圾收集器回收对象时调用的方法,执行finalize并不一定会触发垃圾回收,垃圾回收只跟内存有关。finalize的用途是调用其他语言(如C++)申请内存时,垃圾回收机制并不能有效的回收内存,此时需要调用finalize覆盖默认的方法来实现对这部分内存的释放和回收。

6. System.gc()告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的;System.runFinalization()强制调用已经失去引用的对象的finalize方法;

PS:runFinalizersOnExit因为线程安全问题不再使用,此外还有:

a) Thread.stop:这个方法会解除被加锁的对象的锁,因而可能造成这些对象处于不一致的状态,而且这个方法造成的ThreadDeath异常不像其他的检查期异常一样被捕获。可以使用interrupt方法代替。事实上,如果一个方法不能被interrupt,那stop方法也不会起作用。

b) Thread.suspend, Thread.resume:这俩方法有造成死锁的危险。使用suspend时,并不会释放锁;而如果我想先获取该锁,再进行resume,就会造成死锁。可以使用objectwaitnotify方法代替。wait方法会释放持有的锁。

c) Runtime.runFinalizersOnExit:这个方法本身就是不安全的。它可能导致终结器(finallizers)在活动对象上被调用,而其他线程正在并发操作这些对象。而且,这个调用不是“线程安全”的,因为它设置了一个VM全局标志。

7. 所有成员变量的初始化优先于构造函数进行赋值,静态代码块、静态变量优先于所有成员变量初始化,且静态代码块、静态变量只初始化一次。非静态代码块执行顺序优先级和成员变量一致,按照代码书写的顺序执行。

class MyInteger {

MyInteger(int i) {

System.out.println("MyInteger constructed.");

}

}

public class Test02 {

MyInteger i = new MyInteger(1);

{

int a = 100;

System.out.println("non-static block initialized.");

}

Test02() {

System.out.println("Test02 constructed.");

}

MyInteger j = new MyInteger(2);

static {

System.out.println("Static block initialized.");

}

public static void main(String[] args) {

System.out.println(new Test02().i);

}

}

输出:

Static block initialized.

MyInteger constructed.

non-static block initialized.

MyInteger constructed.

Test02 constructed.

com.conanswp.chap04.MyInteger@15db9742

 

8. Java支持数组类型的直接赋值,其效果是对象引用的赋值。

public class Test03 {

public static void main(String[] args) {

int[] a1 = { 1, 2, 3, 4, 5 };

int[] a2;

a2 = a1;

for (int i = 0; i < a2.length; i++)

a2[i]++;

for (int i = 0; i < a1.length; i++)

prt("a1[" + i + "] = " + a1[i]);

}

static void prt(String s) {

System.out.println(s);

}

}

输出:

a1[0] = 2

a1[1] = 3

a1[2] = 4

a1[3] = 5

a1[4] = 6

9. 基本类型数组会根据数据类型有默认值,非基本类型数组初始化为null

public class Test04 {

public static void main(String[] args) {

int[] primary_array = new int[5];

for (int i : primary_array)

System.out.println(i);// 输出0

Integer[] object_array = new Integer[5];

for (Integer o : object_array)

System.out.println(o);// 输出null

Integer[] object_array1 = new Integer[] { new Integer(1), new Integer(2) };

for (Integer o : object_array1)

System.out.println(o);// 输出1/2

}

}

 

Chap 5 隐藏实施过程

1. 包:库单元。一个java源码文件称之为一个编译单元,一个编译单元只能有一个public类且编译单元文件的名字必须与public类的名字完全相同,包括大小写。Package包必须作为编译单元的第一个非注释语句出现。

2. 访问指示符号:默认不写是包内友好的访问权限。Public公共访问,protected继承访问,private私有访问。

 

Chap 6 类再生

1. 类中非primative对象的初始化可以在对象定义、构造器和紧挨对象使用前进行初始化。

2. 衍生类的构建起会自动插入对基础类构建起的调用,因此衍生类构建时会首先调用基础类的构造方法。还可以通过在衍生类构造函数第一样通过super调用基础类的构造方法。

3. final关键字:

|-修饰变量->常数,编译期间不会变化。

|-空白finaljava1.1允许,必须在定义字段时使用表达式或者在构造函数中对final变量进行初始化。

|-final自变量:方法中的参数可以通过final修饰,只能读取,不能改变。

|-final方法:防止继承改变,并能够提高执行效率(传统方法调用:自变量入堆栈->跳到方法并执行->跳回来->清除堆栈自变量->返回值处理。Final方法调用:用实际代码的副本进行替换。要求代码不能太长。)。类内所有private方法都自动成为final方法。

|-final类:final class XXX不允许继承,内部变量的值可以改变,除非其值是final修饰的。

4. 继承初始化:先执行基础类+衍生类的static属性和静态代码块,然后是基础类的成员变量初始化+构造函数,最后是衍生类的成员变量初始化+构造函数。

package com.conanswp.chap06;

class Base {

private int a = 10;

private static int b = 20;

Base() {

System.out.println("Base Constructed.");

say();

}

private int c = 30;

private static int d = 40;

public void say() {

System.out.println("Hi from Base, a=" + a + ", b="+b+".");

}

}

class Derive extends Base {

private int a = 50;

private static int b = 60;

Derive() {

System.out.println("Derive constructed.");

}

public void say()

{

System.out.println("Hi from Derive, a="+a+", b="+b+".");

}

private int e = 70;

private static int f = 80;

}

public class Test {

public static void main(String[] args) {

new Derive().say();

}

}

输出:

Base Constructed.

Hi from Derive, a=0, b=60.

Derive constructed.

Hi from Derive, a=50, b=60.



猜你喜欢

转载自blog.csdn.net/conanswp/article/details/78651124