书的大名听过6年多了,买了很久只是翻翻而已。最近抽空通读了一遍,花了一个多月的时间。
虽然书翻译的很烂,勘误也有不少,但是总体来讲,还是一种相见恨晚的感觉,尤其最后的并发编程几乎每个实例都调试了一遍,让我觉得以前编码生涯还是欠缺太多。
开始没想写笔记,很多东西可能也没记录下,现在尽量的回忆,和整理一些后期的笔记。
1. java多态的概念后期绑定。以前居然没听过这个词,感觉多态这么多年算是白学了,与之相对应的是c++ 虚函数。 而我以前只会将java的传参和 c++的引用传递联系起来。
2. 反射要理解是动态编程。它可以反射调用私有的方法。虽然以前很早也听说过,不过现在知道别人也是从这本书中学来的吧。
3. p214 局部内部类不能有访问说明符!访问说明符指的是 private,prototced,public开始很久不能理解。
4. p219 "你也可以直接使用Array.asList()的输出"
@SafeVarargs
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
但是这个ArrayList 是Array的一个static 内部类。所以的确不支持那些操作。不过delete写的倒是有点问题? 应该是remove方法。
5.p361. ”另外,对于一个static的方法而言,无法访问泛型类的类型参数,所以static方法需要使用泛型的能力,就必须使其成为泛型方法。”
public class ABC<T> {
T t;
public ABC(T t) {
this.t = t;
}
public static void print0() {
// System.out.println(t.getClass()); error
// 静态方法无法使用非静态参数
}
// public static void print1(T t) { error
// System.out.println(t.getClass());
// 静态方法无法使用非静态参数
// }
// 泛型方法
public static <T> void print2(T t) {
System.out.println(t.getClass());
}
public static void main(String[] args) {
ABC.print2(1);
}
}
补充解释一下:static方法,不需要初始化对象。但是泛型的具体类型,是初始化对象的时候才确定的,所以2点矛盾导致需要泛型方法。
6. p376 “泛型不能用于显示地引用运行时类型的操作中,例如转型,instanceof操作,和new表达式。“(实测中转型是可以的,只是会有警告)
解释:貌似因为java泛型是基于擦除实现的,真正运行于虚拟机的时候并没有它的类型。
联想一下(通过泛型或者类型转换的代码,javap字节码是一致的,所以它只是编译的时候有用)
7. p375 ”泛型类型参数将擦除到它的第一个边界”
解释:这里的擦除和上一句应该不一样,上一句表示的是JVM中,没有类型信息。这里的擦除应该是向上转型。
8. p389 “?被限制为单一边界。”
解释:有空好好研究下~ “?”通配符应该不算单一边界吧。
9. p585 “static信息读取却出现了问题。”
这个很好理解,如果static也可以被恢复的话,那么其他对象中有指向为static的数据也会跟着变化。
举个例子,A对象有个static 数据是3. 有个B对象是static等于2的时候store,你recover的时候如果恢复成2,那么A对象也会受影响。
10. 不爱用枚举,因为数据库的字段都是有int值,不太知道怎么把枚举和int值互相转换。其实可以这样。
enum Explore { HERE, THERE }
public class Foo{
public static void main(String[] args) {
System.out.println(Explore.HERE.ordinal());
System.out.println(Explore.values()[1]);
}
}
如果错位,或者下标为负数怎么办,那就自己写个计算规则吧?
例如
Explore.HERE.ordinal()+1
Explore.values()[x-1]
如果数据库的类型是
1,2,3,5
枚举值依然可以填出ONE,TWO,THREE,FOUR,FIVE。只是有个永远不用而已。关系还是对应的。
11. p665 ”因此一旦main()退出,JVM就会立即关闭所有后台进程。所以finnaly语句不会执行。”
所以阅读hadoop源码的时候里面都有大量的HOOK。利用HOOK来释放资源。原来是基于这个的目的。
例如:
public static class CompositeServiceShutdownHook implements Runnable {
private CompositeService compositeService;
public CompositeServiceShutdownHook(CompositeService compositeService) {
this.compositeService = compositeService;
}
@Override
public void run() {
ServiceOperations.stopQuietly(compositeService);
}
}
12.p673 很奇怪输出结果和书中不一致,和这个提问一样http://bbs.csdn.net/topics/390118941 没有检索到原因
既然没有人来回答这个问题,我就来回答一下,因为newCachedThreadPool会当线程异常后立即再次创建线程。
如果你调用
ExecutorService exec = Executors.newCachedThreadPool(
new HandlerThreadFactory());
exec.execute(new ExceptionThread2());
exec.shutdown();//加上这句和书上的输出就一致了。
13. p687页
方法可以多态,属性没有多态一说。子类可以访问父类 public的属性。但是至始至终,那始终是父类的属性,而不是子类的。
checkCounter的测试。
14.
notifyAll
public final void notifyAll()
-
唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个
wait
方法,在对象的监视器上等待。直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。
说明你调用 notify或者notifyAll的时候其他线程并不能运行,除非当前线程结束,或者调用wait()方法。
15.p765 "为了能够在不经意间就可以防止线程耦合,必须...,或者是不连接对象..."
解释:因为加入队列后,不会立即执行,如果还没执行就被别人修改了,当然也造成了并发问题。
16.p765 ”每个对象都将维护对它自己的域的全部控制权(这比普通的类要更严苛一些,普通的类只是拥有防护它们的域的选择权)”
解释:域就是属性。读了很多遍不是很理解这句话,估计大意在于控制权和选择权, 普通的类,可以让你调用方法访问并修改它。 而活动对象意味着你根本不应该对他有任何的控制权。即是,外围对象对它的域,不能进行任何控制。