《Effective Java》总结
导语
《Effective Java》是和《Thinking in java》齐名的java进阶书籍。作者参与了JDK标准库的编写工作,对于此书的学习,让我收获很多。好记性不如烂笔头,我决定好好总结一下。本书主要内容有11章,分别从各个方面阐述了作者对于java代码编写的体会。我看的是第二版,目前最新版已经是第三版了,但是还没有在国内翻译出版。这就是英语不好的局限之处~
创建和销毁对象
作者认为,使用构造方法构造对象是不优雅的。我们应该是用工厂方法来构建对象。一来可以用语义化的静态方法名来避免构造方法重载造成的迷惑性,二来可以在构造对象时进行如懒加载,校验等相关控制,因为构造方法调用后一定会返回一个新的分配了堆内存的对象引用。通常的方法名为:
valueOf
,of
,getInstance
,newInstance
,getType
,newType
等。作者认为,对象参数过多时,为了避免冗长的setter方法调用,应该使用Builder设计模式。同时builder对象可以作为参数传递给相关方法。此处可以配合Lombok。
作者认为构造单例的最好方式是枚举,同时应该注意对象序列化对单例造成的破坏。
作者认为只包含静态方法和静态域的类应该私有构造器,因而不可实例化,不能被继承(子类实例化时会调用父类构造器)。个人认为也可以使用abstarct关键字。
作者认为避免创建不必要的对象,如
String s =new String("hello")
,这里其实就重复定义了字符串,造成了内存浪费和GC压力。还有就是循环语句中的某些对象可以在语句外面创建,在整个循环中重用。避免自动装箱造成的频繁创建对象。在我们自己管理内存时,要注意消除过期对象的引用,让JVM及时回收内存。我们自己管理内存的典型场景为我们在全局范围内持有一个数组,我们自己管理自己的数组内存,进行数据的增删改。我们要及时的将不用的对象引用从数组中通过置为
null
去掉。让GC内存回收内存。避免使用finalize方法。在此方法历写业务的最大问题时,该方法的调用时间是不一定的。因为GC线程的优先级很低,所以该方法的调用时机是不可控的,且性能开销很大。只建议在某些特定情况下作为安全网方法,即最后一道捕捉漏网之鱼的方法。
应该重写equals方法。此处可以配合Lombok。
应该同时重写hasCode方法。此处可以配合Lombok。
应该要覆盖toString方法。便于调试。此处可以配合Lombok。
应该谨慎的使用clone方法。因为存在浅克隆问题。
对于值对象类,应该合理的实现
Comparable
方法。此处可以配合guava的Ordering。应该使类的成员可见性在可能的情况下最小。因为一旦类的成员暴露,那就成为创建者和调用者之间的约定。那么类的创建者就要对这些暴露的成员的稳定性负责,不能随意修改约定。
应该通过方法访问域而不是直接访问域。因为可以在方法中进行相关控制。
应该使对象的可变性最小。即,除非必要,所有的域都应该用
final
修饰,所有域都应该是私有的,所有类都不能被拓展。被拓展的类可能会被破坏封装性,即,拓展的过程中,需要去了解被拓展的类的内部实现,而不仅仅是被拓展的类暴露出来的API。复合优于继承。如上所述,继承破坏了封装性,同时复合更稳定,不会受到被复合的类的结构的改变的影响。通过复合和转发(适配器模式)可以方便的实现继承的效果。同时可以通过
asType
方法暴露一个被复合的类的视图模拟多态。继承是一种约定。要么提供丰富和负责任的文档告知方法的自用性,并测试被继承后的风险,要么就通过final禁止被继承。
接口优于抽象类。因为单继承的局限性,同时接口之间并不一定和类一样是分层关系。通过mixin接口(如
Comparable
接口),可以构建功能丰富的类,并且可以灵活的实现多态。为了便捷的实现接口,可以提供一个接口默认实现骨架类(Wapper)。接口只用于定义类型,便于实现多态。不应该用来定义常量,常量属于不同的实现类的内部实现,不应该放在接口中作为API约定。
通过在类中添加一个type字段来区分不同类型是不够OOP的,应该通过类的继承来实现层次。将相同的部分抽象成父类,type字段的每一个值都作为一个拓展子类。添加自己的字段和方法。
用函数对象表示策略,java8之前不支持函数式编程的迂回。
优先考虑静态内部类。静态内部类时访问权限的最小域。如果一个类只在本类中使用,就可以定义为私有的静态内部类。当然,它实现的接口可以有公开的访问权限。
不要使用原生类型(raw type)。对于泛型类,都应该使用参数化类型。
使用
SupressWarn()
压制编译器警告。前提是必须要了解警告的内容,同时将压制的区域最小化,避免出现诡异的问题。列表优于数组。两个原因,数组是协变的,容易产生类型转换异常。数组不支持泛型。
使用泛型。避免类型转换异常。
使用泛型方法。便捷的类型推导可以使代码更简洁。
使用有限制的类型通配符来提高API的灵活性。
Class类是参数化类型,有很多类型相关的方法。如:
cast
等。注意灵活使用。常量推荐使用枚举定义。
不要在业务中使用枚举的
ordinal
属性,应该自定义一个实例域。使用EnumSet来代替位域。
使用EnumMap代替序数索引。枚举作为map的key时。
枚举可以实现接口(因为枚举是一种特殊的类)。
注解优于命名模式。通过命名约定来指定范围,不如在类或类成员上添加注解标记。
使用Override注解来进行编译器检查。
某些只在类上的标记,可以考虑标记接口。如
Cloneable
,Serialble
。检查参数,快速失败。
必要时对参数进行拷贝。如果方法调用者将引用传递给方法后,在方法外对引用指向的对象进行了修改,可能会造成诡异的不可预期的错误。
谨慎设计方法签名。这部分内容太多,也很经典。建议时不时翻下这一节。方法名要合乎约定;不要过分追求方法便捷,除非某个功能太常用可以提供一个便捷方法,不然的话提供一个功能齐全的方法就好;避免过长的参数列表,如有必要,可以提供一个辅助类;注意方法正交性,即功能不要重复。参数优先使用接口,离散参数如布尔参数优先使用枚举。
慎用重载。可以定义一个参数相关的方法名。
慎用可变参数。不安全,代码不美观。建议是一个必要参数加一个可变参数。
返回空数组或空集合,而不是null。
为所有公开API编写文档。
局部变量作用于最小化。
尽可能的使用类库。
精确计算使用大数类型。
基本类型优于包装类型。
尽量避免使用字符串。
小心字符串连接的性能。
接口优于反射机制。反射效率低,无法进行编译期检查。
谨慎的进行优化。前期能跑就行,不要进行没有目的的优化。
不要用异常进行分支控制。
丰富异常信息。
不要忽略异常。
优先使用标准的异常。
并发编程中,尽量使用并发工具类。
序列化没啥用啊,不说了。
总结
我感觉这本书就是很厉害,尤其是带我理解了Super Type Token
这个关于反射和泛型的概念。当然了,那又是一篇博客了,找时间我会娓娓道来的。这本书里关于类和方法的内容很精辟,让我理解了一些关于OOP迷惑。其实值得我多刷好几遍,但是我就匆忙的两三天刷完了。。。心态浮躁。第四章第五章找个午休再翻翻吧。
第一次正式的开始用Markdown写博客,感觉自己很极客。就是博客园的Markdown主题有点太low了。以后我就用这个来写博客啦。。。
后面的博客计划是总结下字节码,反射和泛型。还想着刷一本Zookeeper的书写一写Zookeeper的相关实践。就是心情太浮躁,做事效率太低,拖拖拉拉让我很烦恼。
加油吧。
《Effective Java》总结的更多相关文章
- 《FLASH PROGRAMMING 那些事》总结
注明来自 http://www.ssdfans.com/?p=5589 以MLC为例: 对FGF(Floating Gate Flash)技术的,MLC programming一般分两步走:先prog ...
- Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors
Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...
- [原创] Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的算法解决办法
MDK开发环境从V4升级到V5后,支持包不再是集成到开发环境当中,而是封装在PACK中,需要自行安装,比较麻烦. 搭建MDK开发环境以及破解的方法,在前面的文章中有详细说明,这里不再赘述,有兴趣的可以 ...
- Turtelizer 2 provide JTAG Flash programming and debugging of ARM based boards via USB
http://www.ethernut.de/en/hardware/turtelizer/ Introducing Turtelizer 2 Overview Turtelizer 2 had be ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.3)- 串行NOR Flash下载算法(J-Link工具篇)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是J-Link工具下i.MXRT的串行NOR Flash下载算法设计. 在i.MXRT硬件那些事系列之<在串行NOR Flash X ...
- Programming Internal Flash Over the Serial Wire Debug <SWD> Interface -- EFM32
1 Debug Interface Overview 1.1 Serial Wire Debug Serial Wire Debug (SWD) is a two-wire protocol for ...
- Error:Flash Download Failed-"Cortex-M3"
Error:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/H ...
- STM32F4读写内部FLASH【使用库函数】
STM32F4Discovery开发帮使用的STM32F407VGT6芯片,内部FLASH有1M之多.平时写的代码,烧写完之后还有大量的剩余.有效利用这剩余的FLASH能存储不少数据.因此研究了一下S ...
- Flash Download Failed-"Cortex-M3"
rror:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HW ...
- Stm32_调试出现 Error:Flash Download Failed-"Cortex-M3"
rror:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HW ...
随机推荐
- scala之map,List,:: , +:, :+, :::, +++操作
scala之map,List操作 1.Map操作 2.List操作 2.1Demo1 2.2Demo2 3.:: , +:, :+, :::, +++ 1.Map操作 Map(映射)是一种可迭代的键值 ...
- 网络编程(socket简介)
socket简介 Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中 ...
- Hive on MR调优
当HiveQL跑不出来时,基本上是数据倾斜了,比如出现count(distinct),groupby,join等情况,理解 MR 底层原理,同时结合实际的业务,数据的类型,分布,质量状况等来实际的考虑 ...
- REST架构及其介绍
概述 REST是英文Representational State Transfer的缩写,中文翻译:表述性状态转移. 他是由Roy Thomas Fielding博士在他的论文 < ...
- 【疑】接入交换机lacp port-channel连接核心突然中断
现状: 职场网络架构为接入交换机2个端口通过lacp协议的active模式组成port-channel上联到核心. 具体配置如下 接入: 核心: 故障现象: zabbix监控到核心交换机对应该接入交换 ...
- CCF-有趣的数(数位DP)
有趣的数 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前 ...
- 真正云原生的智能运维体系,阿里云发布ECS自动化运维套件
云计算的发展,推动了自动化运维.DevOps.AIOps 等趋势的兴起,在业务快速变化的今天,企业希望通过一套自动化运维的专家系统提高运维效率,为业务提供支撑. 传统的方式下,打造一套成熟的 DevO ...
- 90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(2)- TLAB预热
经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢? 面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java 程序越执行越快呢? 一般人 ...
- 从NMEA0183到GNSS定位数据获取(一)原理篇
作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:Conscience_Remains 总述 GPS我们都知道,一种用来全球定位的系统,后来俄罗斯推出了格洛纳斯定位系统,中国推出了北斗定位,欧盟有 ...
- P1435 回文字串(DP)
题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 "Ab3bd"插 ...