effective java 第七天

57.只针对异常的情况才使用异常

不要在正常的控制中使用异常:

58.对可恢复的情况使用受检异常,对编程错误使用运行时异常

Java程序设计语言提供了三种异常:1.受检异常;2.运行时异常;3.错误;

59.避免不必要地使用受检的异常

60.优先使用标准异常

61.抛出与抽象相对应的异常

异常翻译:

异常链:

62.每个方法抛出的异常都要有文档

63.在细节消息中包含能捕获失败的信息

64.努力将失败保持原子性

失败的方法调用应该使对象保持在被调用之前的状态

对于不可变的对象,失败原子性是显然的;对于可变的对象,在调用方法的时候检测参数的有效性:

65.不要忽略异常

66.同步访问共享的可变数据

67.避免过度同步

68.executor和task优先于线程

Runnable和Callable的区别:Runnable的方法是run()而Callable的方法是call()。

ExecutorService有四种线程池:

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

https://www.cnblogs.com/Steven0805/p/6393443.html

https://www.cnblogs.com/Steven0805/p/6393443.html

69.并发工具优于wait()、notify()

自Java1.5之后,Java平台提供了更强大更高级的并发工具

70.线程安全性的文档化

71.慎用延迟初始化

72.不要依赖于线程调度器

73.避免使用线程组

74.谨慎地实现Serializable接口

1.如果你简单地实现了Serializable接口,那么如果不做特殊处理,里面的私有化类型也会被序列化,这就让隐蔽工作变得困难了。

2.增加了出现Bug和安全漏洞的可能性

通常情况下,对象是利用构造器来创建的,序列化机制是一种语言之外的对象创建机制(隐藏的构造器);由于反序列化机制中没有显示的构造器,所以你很容易忘记要确保,反序列化过程必须也要保证所有“由真正的构造器建立起来的约束关系”,而且不允许攻击者访问正在构造过程中的对象的内部信息。

为继承设计的类尽可能不去实现Serializable接口,用户的接口也尽可能不去继承Serializable接口。

内部类不应该实现S接口

75.考虑使用自定义的序列化形式

76.保护性地编写readObject方法

不严格地说,readObject是一个“用字节流作为唯一参数”的构造器。对象进行反序列化的时候,如果面对一个人工仿造的字节流,这时应该为类提供一个readObject方法,该方法会首先调用defaultReadObject方法,然后检查被反序列化后的对象的有效性,如果无效,会抛出异常。

readObject方法实际上相当于另一个公有的构造器,与其他构造器一样,它也需要进行参数的有效性检查与保护性拷贝

77.对于实例控制,枚举类型优先于readResolve

在jdk中ObjectInputStream的类中有readUnshared()方法,上面详细解释了原因。我简单描述一下,那就是如果被反序列化的对象的类存在readResolve这个方法,他会调用这个方法来返回一个“array”(我也不明白),然后浅拷贝一份,作为返回值,并且无视掉反序列化的值,即使那个字节码已经被解析。

78.考虑用序列化代理代替序列化实例

猜你喜欢

转载自blog.csdn.net/weixin_38967434/article/details/82851898