发发神经
在研究Solr源码发现它用到了Apache的commons io包,回想以前在各种场合见过这位“侠客”留下的痕迹,犹如挥之不去的魅影,决心花一天时间好好拜访一下commons io!!正当我撸起了袖子,信心满满,蓄势待发,果然单FileUtils就给了我一个闭门羹……
在研究源码时,类图、时序图能起到很好的辅助作用,而且借助Eclipse调试、链接功能,可以省下很多力气。但是面对粒度更细的方法层,我并没找到很好的解决方案。有时候单一个类中的方法,就有各种跳转调用,我们也被牵着鼻子在Eclipse中跳来跳去。以FileUtils类为例,它是一个工具方法集合共93个方法。里面含有大量的同名或者至少长得可以让你眼花的兄弟方法。下面举一些例子。
copyDirectory | 4 |
copyFile | 3 |
iterateFiles | 2 |
listFiles | 2 |
write | 6 |
writeLines | 7 |
writeStringToFile | 6 |
但其实,一归纳就会发现,很多重载方法归根结底就是一个方法,只不过为了调用的方便,或是省去某个参数代以默认值,或是加了一层包装。有时候需要忽略重载细节,抓住问题的本质,当你再一次看到某个重载方法时,你头脑就会反应“嗯,它其实最后调用的是这个方法”。所以我按照自己的想法,给出了一个阅读源码方法层的解决方案。
方法的度
①指1度方法,②指二度方法。度越小,这个方法越“本质”。而⓪度方法通常表示非装饰的内部方法。
+ listFiles(File, IOFileFilter, IOFileFilter) ①
+ listFiles(File, String[], boolean) ②
- innerListFiles(...) ⓪
+ listFilesAndDirs(File, String[], boolean) ①
- innerListFiles(...) ⓪
- validateListFilesParameters(File, IOFileFilter) ⓪
一般而言,方法的参数个数越多,度会越小,其他重载方法是某些参数缺省值的快捷方法;方法的参数个数相同,同位置参数类型越简单,度会越大,比如含String encode参数的方法会调用含Charset encode的重载方法。
还有一个“一般”规律:参数每减少一个,不是直接调用低一度的方法,而是直接调用①度方法。对我们的启示是:高度方法尽量不要多层嵌套调用重载方法,而是直接调用①度方法;①度方法的设计很重要。
幽灵方法
加下划线__的表示是幽灵方法。
玩过赛车游戏的人可能知道,有些赛车游戏会加入自己以前的赛车轨迹,成为幽灵选手。而一些功能相同的方法总是会有两个,比如返回值为File类型和String,返回值为数组类型和Collection类型,返回值为Collection类型和Iterate类型。
+ listFiles(File, IOFileFilter, IOFileFilter) ①
+ listFiles(File, String[], boolean) ②
- innerListFiles(...) ⓪
+ listFilesAndDirs(File, String[], boolean) ①
- innerListFiles(...) ⓪
- validateListFilesParameters(File, IOFileFilter) ⓪
+ iterateFiles(File, String[], boolean) ③
+ iterateFilesAndDirs(File, String[], boolean) ②
方法约简
+ copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate)
①
+ copyDirectory(File srcDir, File destDir, boolean preserveFileDate) ②
+ copyDirectory(File srcDir, File destDir, FileFilter filter) ②
+ copyDirectory(File srcDir, File destDir) ③
- doCopyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate, List<String> exclusionList) ⓪
+ write(File file, CharSequence data, Charset encoding, boolean append)
①
+ write(File file, CharSequence data, boolean append) ②
+ write(File file, CharSequence data, Charset encoding) ②
+ write(File file, CharSequence data) ②
+ write(File file, CharSequence data, String encoding, boolean append) ②
+ write(File file, CharSequence data, String encoding) ③
+ writeStringToFile(File file, String data, Charset encoding, boolean append) ⓪
+ writeLines(File file, String encoding, Collection<?> lines, String lineEnding, boolean append)
①
+ writeLines(File file, String encoding, Collection<?> lines, boolean append) ②
+ writeLines(File file, String encoding, Collection<?> lines, String lineEnding) ②
+ writeLines(File file, Collection<?> lines, String lineEnding, boolean append) ②
+ writeLines(File file, Collection<?> lines, String lineEnding) ②
+ writeLines(File file, String encoding, Collection<?> lines) ②
+ writeLines(File file, Collection<?> lines, boolean append) ②
+ writeLines(File file, Collection<?> lines) ②
+IOUtils.writeLines(Collection<?> lines, String lineEnding,OutputStream output, String encoding) ⓪
+ writeStringToFile(File file, String data, Charset encoding, boolean append)
①
+ writeStringToFile(File file, String data, Charset encoding) ②
+ writeStringToFile(File file, String data, boolean append) ②
+ writeStringToFile(File file, String data) ②
+ writeStringToFile(File file, String data, String encoding, boolean append) ②
+ writeStringToFile(File file, String data, String encoding) ③
+IOUtils.write(String data, OutputStream output, Charset encoding) ⓪
约简后
+ copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate)
+ write(File file, CharSequence data, Charset encoding, boolean append)
+ writeLines(File file, String encoding, Collection<?> lines, String lineEnding, boolean append)
+ writeStringToFile(File file, String data, Charset encoding, boolean append)
单这4个方法,可以约简掉20个方法。
结论
结论一
重载方法中:参数越长,度越低;参数长度相同,类型越复杂,度越低。
我们只需要看那些度为①的方法。
结论二
高度方法尽量不要多层嵌套调用低度重载方法,而是直接调用①度方法;①度方法的设计很重要。