Thinking in Java 读书总结(二)

小吐槽

上周产线发布的时候,新包竟然出了产线故障。虽然紧急回滚避免了更大的影响,但是包内部的问题还是让我头疼了一整周。可以说上周真的是工作以来最艰难的一周,每天都弄到2,3点才回去,博客也没有更新。现在虽然还没有完全解决包内部的问题(需要和别的团队联调),但是至少目前有work around的方案让新的包可以正常工作且新的feature都可以正常上线了。不得不说这一周的紧张真的是锻炼了自己的抗压能力,也让自己明白需要在越紧张的时候越要保持冷静,把思路理清楚之后再一步一步来,这样才能更好地解决问题!

话不多说,开始更新新的Thinking in Java的总结!

第五章 初始化与清理

5.1 构造器初始化

构造器本身并不返回任何返回值。

5.2 重载

5.2.1

方法参数顺序不同也可以重载,但是尽量不要这样!!!这样可能会导致系统难以维护。如果一定要传相同参数的话,可以再多加一个参数以标识不同情况下的区别,而不要去通过参数顺序的不同来做。(我个人观点)

5.2.2 基本类型重载

  • byte会先尝试转换成short,没有short类型的参数的话才会转型成int及更大的基本类型,这也是基本类型向上转换的基本原则!特别注意的是比int小的,char会直接转型成int(如果接受int型)或更大的参数!
  • 如果方法只接受比较小的基本类型作为参数,那么必须执行窄化转换!这其实和类的向上向下转换类似!

5.2.3 返回值

不可以用返回值区分重载函数!比如有

void f(){}
int f(){return 1;}

两个函数f,那么现在直接在代码里调用f(),编译器也不知道调用哪个。很好理解。

5.3 无参构造器

无参构造器会创建一个默认对象,自己不写构造器那么编译器会自动创建一个无参构造器。但是如果自己写了构造器,不管有无参数,编译器不会再帮创建构造器。

5.4 this

对象调用函数时,会隐式的把当前操作对象的引用当作参数传给函数。用this关键字可以在函数内部获取当前对象的引用。

5.4.1 构造器相互调用

  • 在一个构造器A中可以用this调用另一个构造器B,但是如果还有一个构造器B,不能同时在A中调用B和C。
    • 但是可以层级调用,比如A中调用B,B中调用C。

5.4.2 static

static方法中不能调用非静态方法。---> 不是绝对,可以参考

static方法调用普通方法

但是这样的设计是没有必要的,因为完全可以通过一个非静态方法来做到。

5.5 GC

这部分内容很复杂,TIJ里介绍的也不是很详细,之后会详细学一学JVM内部运行的原理,然后分享一些博客的!

这里说一说引用计数的缺点,伪代码如下:

T t1 = new T();
T t2 = new T();
t1.t = t2;
t2.t = t1;
t1 = null;
t2 = null;

这种情况用引用计数就会出现bug!因为虽然t1和t2的引用都被置为null,但是它们的对象还是相互引用的,这种情况下他们仍然占着内存。

JVM gc机制是java程序员必须要知道的,这里不展开说,列几点,分代,GC方法,各种方法的优劣等。

5.6 成员初始化

类的成员变量即使不显示赋值也会有初始化。基础类型会有各自的默认值,对象会出初始化成null。

在Java中,可以在成员变量定义的地方初始化值,但C++中不行!

方法中局部变量不会有默认的初始化值!

5.7 构造器初始化

晚于成员初始化。这其实和JVM中类的加载和初始化有关系,如果要完全弄明白为什么初始化的关系需要理解JVM类加载的工作原理。

5.7.2 静态初始化

只有第一次类对象被创建或者第一次访问静态数据时才会被初始化。而且此后不会再初始化。很好理解,静态数据都是存在方法区里的。

初始化的顺序是先静态后非静态。后面结合继承和多态的时候就会有一点复杂,但是对一个单个的类来说是这样的。

而且非常重要的一点,TIJ在这里为了便于理解可能犯了一个错误,书中提到即使没有显示的使用static,构造器实际上是静态方法,当时我也觉得是这样,但是后面在看多态的时候去查了一下发现这个说法并不对,这个会在后面多态的部分分享。

5.7.3

非静态语句块会在构造器之前执行。

5.8 数组初始化

Java数组初始化将数组中引用指向堆中相应类的对象实例。

JVM数组方法的介绍 这篇博客由length入手介绍了jvm动态生成数组类的过程。

5.8.1 可变参数列表

可变参数和重载一起使用时可能会有问题。伪代码如:

void f(int... a){print 0}
void f(float... a){print 1}
void f(String... a){print 2}

这里如果不加任何参数调用f(),jvm就不知道该调用谁了。解决办法和前面一样,也是可以加一个不可变参数来控制!

第六章 访问权限控制

6.1.2 包名

反顺序的小写的Internet域名。

6.2 各类权限:

private:类自己内部可以使用。

protected:继承访问权限。

public:接口访问权限。可以在任何类中使用。

不写:包访问权限。

6.3 接口和实现

访问权限的控制被称为 具体实现的隐藏。把数据和方法放入类中,以及具体实现的隐藏,被共同成为 封装。其结果是一个带有特征和行为的数据类型。

6.4 类的访问权限

  • 每个编译单元只能由一个public类。包括public内部类也会有一个单独的文件。
  • public类类名必须完全与含有此编译单元的文件名一致。
  • 一个类文件可以无public类,但尽量不要这样做,会造成代码混淆。
posted @ 2018-08-03 00:33  SmallMushroom  阅读(200)  评论(0编辑  收藏  举报