- 浏览: 111979 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (85)
- java (11)
- html picture toggler (0)
- web vector (1)
- tomcat (2)
- tomcat jconsole (1)
- comet (1)
- tomcat jconsole heapdump (0)
- code (1)
- java netty (1)
- 抓包 (1)
- netty (1)
- java jconsole heapdump (0)
- linux iptables (1)
- nginx (3)
- vim (2)
- 压力测试 (1)
- jsonsole (0)
- mysql (7)
- jconsole (2)
- seajs (1)
- linux (4)
- heapdump (1)
- 逻辑分析 (1)
- jvm 内存溢出 并发 压力 netty (1)
- linux 运维 (2)
- bug (1)
- netbeans (1)
- maven (1)
- 露营 (0)
- spring cloud (2)
- openresty (1)
- redis (1)
- git (1)
- mybatis (1)
- nginx curl (1)
- openssl https ca (1)
最新评论
-
重写幸福:
...
mysql 压力测试工具 -
faylai:
明显不是jquery 的写法
精简的TabComponent, 几十行的东西没必要搞个几十K -
lqixv:
jquery tools 的 tab 标签好看又好用。建议去试 ...
精简的TabComponent, 几十行的东西没必要搞个几十K -
伊苏:
bingo
精简的TabComponent, 几十行的东西没必要搞个几十K -
bitray:
baiyuxiong 写道楼主这是ylmfos?雨林木风系统+ ...
精简的TabComponent, 几十行的东西没必要搞个几十K
代码规范
这个词困扰了我多年
要统一代码规范, 我目前还没见过成功的例子,
各个公司, 各种语言, 甚至每个人都有自己的风格, 没有形成网格的也有习惯, 用别人的总是不那么顺手
常见的代码规范:
类的命名首字母大写, 然后驼峰命名
函数取名, 第一个词小写, 动词开头之类的
这2点还算厚道
然后
内部变量来了
以前学习C语言的喜欢 _a _i, lcName, lcCount, 之类
{}
C#的
if()
{
}
java的
if(){
}
运算符前后加个空格
i=1;
i = 1;
for(int i=0;i<len;i++)
for(int i=0; i<len; i++)
bool变量 一定要isExist, 之类的
大部代码规范文档都是这么要求的, 当然也是有它的道理和作用, 但执行起来很困难, 几乎全靠程序员自觉, 但这个人性, 你懂的, 要靠term leader吗? term leader也没那个功夫天天看, 行行看, 抽查的意义不大
而且这让很多编码人员很烦躁, 潜意识里被束缚着
所以, 多年来我一直没有去理会过代码规范这事
最近, 突然间有点觉悟, 是在写注释, 文档, 看代码时的一种突然间的顿悟
我不需要也不想读这么多代码,
80%的情况下, 我希望读少量注释或代码就能知道个大概就行
20%的情况下, 我希望针对小段代码深度分析
甚至有时候, 我希望针对一个方法, 直接进行替换而不是修改
为什么这么多年来都发现呢,
国内的编码环境, 追求快速编码, 快速实现功能
无视需求分析, 无视系统设计, 更别说写注释, 文档了
由程序员什么都没搞清就开始敲代码, 做设计, 那个不叫需求分析和系统设计
好了, 具体的代码规范: 不应该着眼于代码的命名, 变量的首字母之类的细枝末节
而是应该体现在思路上, 算法, 数构结构上, 让代码容易读起来
或者说几行重点代码就能知道个大概了
让人在读代码的时候, 很清淅的知道你在干什么, 或者是你想干什么
典型的场景1: 自己读自己以前的代码的时候, 由于是自己写的, 代码是看懂了, 但却不知道为什么要这么写, 一改, 结果bug出来了
典型的场景2: 自己读自己以前的代码, 搞不清楚类级别的变量是干什么用的, 前后跨几屏的翻代码, 穿插几个函数终于弄清该变量是干什么的了, 然后大骂, 虽然那是你自己亲手造成的
典型的场景3: 自己写的一个类, 要跑单元测试了, 要么就是数据库错误, 要么就是提示缺少组件, 要么就是null异常, 前后翻几个类几个包, 把mysql跑起来, 把tomcat跑起来, 然后才能把这段代码跑起来, 其实我只是想测刚才修改了报表里的一个字段是否正确而已...
以下是我个人整理的代码规范
一 注释
1.类的注释
每个类都要有注释说明, 包括: 这个类的标题, 这个类是干什么用的, 结合使用场景的说, 这个类的使用有什么特殊情况, 这个类的调用说明
2.函数的注释
所有公共函数都强制需要注释, 这个方法是干什么用的, 结合使用场景的说, 这个类的使用有什么特殊情况, 调用方法说明, 每个参数, 能给个例子就给个例子, 如param path, 别人调用时传个"d:/abc/"出错了半天, 才发现原来是要这么传"d:/abc", 你还在那振振有词的说, 你的入参不合法
3.域级变量的注释
所有域级变量都强制需要注释, 这个变量是干什么用的, 结合使用场景的说, 这个变量的使用有什么特殊情况
4.数据结构的注释
重要的数据结构前添加注释, 样例
//转算为M M=1024byte*1024Kb
double d1=result[1]/((double)1024*1024);
//转算为G G=1024byte*1024Kb*1024Mb
double d2=(double)result[1]/(1024*1024*1024);
针对d1, d2, 与其在命名写 sizeOfMb, sizeOfGb, 还不如直接标个注释更清晰
5.注释越多越好
曾经在合资企业呆过一阵子, 用英文写过注释, 自己看起来还可以,
但问题是: 你能保证你的英文不写错, 却不能保证别人的英文不读错, 这里还有语言背景问题, 所以, 作为中国人, 还是别装B了, 有条件的话, 老老实实母语吧, 这样才能有最详细最有质量的备注,
二 类的设计
1. 类的定义
这个类是干什么的, 要在设计是就定义好, 要杜绝客串其他功能, 经常有"临时"需要添加的方法, 几个临时下来, 这个类的就偏离它的定义了, 事后你老人家一不小心想不起来, 那坑的就是自己, 你老人家拍拍屁股一走, 坑的就是接手的人, 对于"临时"函数, 要在类的注释里详细说明这个临时的缘由, 以及事后找时间重构(有条件的话)
2. 函数的定义
慎重使用公共方法, 每个公共函数都要有清淅的理由, 可public又可private的, 一律private, public是公开给外人使用的, 没事就别给别人找麻烦了, 再说了, 那个别人, 多半是你自己
3. 上下文
类和函数的上下文清淅, 要做到这点, 会付出一点代价: 性能浪费在上下文转化
但在95%的情况, 可以方便的整块替换函数比追求函数的运算效率更有意义
三 资源的生命周期
1. 资源的规划
规划好资源是内部生成还是依赖外面, 如connection, inputstream之类的, 内部资源要自己释放, 参见下面的 "2. 内部资源的释放" 和 "3. 外面资源的使用"
2. 内部资源的释放
在自己类里面生成的资源, 要自己释放, 系统后期大部分null, permSpace out of memory就是这么产生的, 虽说java有回收机制, 但你也不能完全靠它, 用完后写个obj=null相当于买一份保险, 例子: 对于foutinputstream fout之类的, 用完后一定要写个fout.close();而fout=null;则是建议写
3. 外面资源的使用
来自外面的资源, 用完就还, 别多手
典型案例:
可以看见, 代码规范其实保是系统设计(类设计)的衍生物, 有一个良好的系统设计(类设计), 才能用良好的代码规范
综合例子1
FileCounter这个类是我去年写的, 我只依稀记得这个类是计算文件数量和容量的, 如今我要使用这个类了, 看着这个类的导航,
我面临以下问题
1.有动态函数和静态函数, 我要怎么使用呢, 这涉及到是否new FileCounter的问题, 这需要我去读代码
2.checkFileSize和checkFileSize1是怎么回事
3.checkFile, checkFileCount, checkFileSize, 看起来第一个函数包括了第2,3个函数的作用, 但我不敢肯定, 这需要我看一下checkFile的代码
4.公共域current和long是干什么用的
------------------------------------------------------------
这是添加注释之后的代码
缩略版
面对这份代码, 我的问题就完全解决了, 而且不需要读代码, 除了注释里的代码
对比:
1.有动态函数和静态函数, 我要怎么使用呢, 这涉及到是否new FileCounter的问题, 这需要我去读代码
2.checkFileSize和checkFileSize1是怎么回事
3.checkFile, checkFileCount, checkFileSize, 看起来第一个函数包括了第2,3个函数的作用, 第2个看起来是计算文件数量, 第3个看起来是计算文件容量, 但我不敢肯定, 这需要我看一下checkFile的代码
4.公共域current和total是干什么用的
5.checkFile的输出? 为什么返回是void
重构注释后
1.从类的说明看到, 直接用动态方法, 还额外知道了, 有进度功能, 实现接口即可实现进度监控, 差点又跑去写一段进度监控代码, 原来一年前我已经想到计算时间太长的卡顿问题
2.checkFIleSize1, 是由于添加了进度事件, 从静态函数改动态函数的原因
3.由于第1点的关系, 我已经知道了直接调用checkFile即可, 而且上面注释已经告诉我, fileCount是计算文件夹目录而不是计算文件数量, fileFileSize是计算文件数量和容易, 而不是只是容量, 这里不需要再深入了, 只有出现bug时, 我才需要深入
4.current, total从注释中看出来是checkFileSize递归算法用的
5.不需要看代码就知道, checkFile的输出是控制台, 这个类是方便开发人员自己使用的
额外的
看着checkFileCount上面的"计算目录数量, 为统计子图数量的进度提供总数", 我不用看代码就回忆起来了, 进度的显示是按目录的进度, 而不是真实的文件数量的进度
综合例子2
在insertDataIntoDb里没有关闭数据库连接
这个函数执行完后, 数据库连接会一直处于sleep状态, 造成严重的不可预知后果
要么数据库连接sleep到达上限, 由数据库回收连接
要么java虚拟机gc时清掉这个线程, 把数据库连接释放
如果遇到多几个这种代码, 数据库连接没能及时回归, 系统在状态下, 别的地方创建数据库失败就等着你, 特别是并发的情况, 这种错误通过静态单元测试是测不出来的
这是一个很可怕的bug
当然我们写代码时不可能时时刻刻想着大并发大压力的情况, 但资源的及时回收却是很容易做到的
改进
这样错误的, 如果sql语句错误, 就会在
ResultSet rs=stmt.executeQuery(sql);
这一行直接跳到exception catch
con.close()这行代码就会被忽略掉
同样造成资源没有及时回收的严重bug
正确的写法应该是写在
try catch 的 finally 里面
这个词困扰了我多年
要统一代码规范, 我目前还没见过成功的例子,
各个公司, 各种语言, 甚至每个人都有自己的风格, 没有形成网格的也有习惯, 用别人的总是不那么顺手
常见的代码规范:
类的命名首字母大写, 然后驼峰命名
函数取名, 第一个词小写, 动词开头之类的
这2点还算厚道
然后
内部变量来了
以前学习C语言的喜欢 _a _i, lcName, lcCount, 之类
{}
C#的
if()
{
}
java的
if(){
}
运算符前后加个空格
i=1;
i = 1;
for(int i=0;i<len;i++)
for(int i=0; i<len; i++)
bool变量 一定要isExist, 之类的
大部代码规范文档都是这么要求的, 当然也是有它的道理和作用, 但执行起来很困难, 几乎全靠程序员自觉, 但这个人性, 你懂的, 要靠term leader吗? term leader也没那个功夫天天看, 行行看, 抽查的意义不大
而且这让很多编码人员很烦躁, 潜意识里被束缚着
所以, 多年来我一直没有去理会过代码规范这事
最近, 突然间有点觉悟, 是在写注释, 文档, 看代码时的一种突然间的顿悟
我不需要也不想读这么多代码,
80%的情况下, 我希望读少量注释或代码就能知道个大概就行
20%的情况下, 我希望针对小段代码深度分析
甚至有时候, 我希望针对一个方法, 直接进行替换而不是修改
为什么这么多年来都发现呢,
国内的编码环境, 追求快速编码, 快速实现功能
无视需求分析, 无视系统设计, 更别说写注释, 文档了
由程序员什么都没搞清就开始敲代码, 做设计, 那个不叫需求分析和系统设计
好了, 具体的代码规范: 不应该着眼于代码的命名, 变量的首字母之类的细枝末节
而是应该体现在思路上, 算法, 数构结构上, 让代码容易读起来
或者说几行重点代码就能知道个大概了
让人在读代码的时候, 很清淅的知道你在干什么, 或者是你想干什么
典型的场景1: 自己读自己以前的代码的时候, 由于是自己写的, 代码是看懂了, 但却不知道为什么要这么写, 一改, 结果bug出来了
典型的场景2: 自己读自己以前的代码, 搞不清楚类级别的变量是干什么用的, 前后跨几屏的翻代码, 穿插几个函数终于弄清该变量是干什么的了, 然后大骂, 虽然那是你自己亲手造成的
典型的场景3: 自己写的一个类, 要跑单元测试了, 要么就是数据库错误, 要么就是提示缺少组件, 要么就是null异常, 前后翻几个类几个包, 把mysql跑起来, 把tomcat跑起来, 然后才能把这段代码跑起来, 其实我只是想测刚才修改了报表里的一个字段是否正确而已...
以下是我个人整理的代码规范
一 注释
1.类的注释
每个类都要有注释说明, 包括: 这个类的标题, 这个类是干什么用的, 结合使用场景的说, 这个类的使用有什么特殊情况, 这个类的调用说明
2.函数的注释
所有公共函数都强制需要注释, 这个方法是干什么用的, 结合使用场景的说, 这个类的使用有什么特殊情况, 调用方法说明, 每个参数, 能给个例子就给个例子, 如param path, 别人调用时传个"d:/abc/"出错了半天, 才发现原来是要这么传"d:/abc", 你还在那振振有词的说, 你的入参不合法
3.域级变量的注释
所有域级变量都强制需要注释, 这个变量是干什么用的, 结合使用场景的说, 这个变量的使用有什么特殊情况
4.数据结构的注释
重要的数据结构前添加注释, 样例
//转算为M M=1024byte*1024Kb
double d1=result[1]/((double)1024*1024);
//转算为G G=1024byte*1024Kb*1024Mb
double d2=(double)result[1]/(1024*1024*1024);
针对d1, d2, 与其在命名写 sizeOfMb, sizeOfGb, 还不如直接标个注释更清晰
5.注释越多越好
曾经在合资企业呆过一阵子, 用英文写过注释, 自己看起来还可以,
但问题是: 你能保证你的英文不写错, 却不能保证别人的英文不读错, 这里还有语言背景问题, 所以, 作为中国人, 还是别装B了, 有条件的话, 老老实实母语吧, 这样才能有最详细最有质量的备注,
二 类的设计
1. 类的定义
这个类是干什么的, 要在设计是就定义好, 要杜绝客串其他功能, 经常有"临时"需要添加的方法, 几个临时下来, 这个类的就偏离它的定义了, 事后你老人家一不小心想不起来, 那坑的就是自己, 你老人家拍拍屁股一走, 坑的就是接手的人, 对于"临时"函数, 要在类的注释里详细说明这个临时的缘由, 以及事后找时间重构(有条件的话)
2. 函数的定义
慎重使用公共方法, 每个公共函数都要有清淅的理由, 可public又可private的, 一律private, public是公开给外人使用的, 没事就别给别人找麻烦了, 再说了, 那个别人, 多半是你自己
3. 上下文
类和函数的上下文清淅, 要做到这点, 会付出一点代价: 性能浪费在上下文转化
但在95%的情况, 可以方便的整块替换函数比追求函数的运算效率更有意义
三 资源的生命周期
1. 资源的规划
规划好资源是内部生成还是依赖外面, 如connection, inputstream之类的, 内部资源要自己释放, 参见下面的 "2. 内部资源的释放" 和 "3. 外面资源的使用"
2. 内部资源的释放
在自己类里面生成的资源, 要自己释放, 系统后期大部分null, permSpace out of memory就是这么产生的, 虽说java有回收机制, 但你也不能完全靠它, 用完后写个obj=null相当于买一份保险, 例子: 对于foutinputstream fout之类的, 用完后一定要写个fout.close();而fout=null;则是建议写
3. 外面资源的使用
来自外面的资源, 用完就还, 别多手
典型案例:
public int setItem(conneciton, con, String sql, String[] param){ int flag=0; try{ ... }catch(exception ex){ ... }finally{ //这里手一抖, 把con关掉了, 调用者就悲剧了 con.close(); con=null; } return flag; }
可以看见, 代码规范其实保是系统设计(类设计)的衍生物, 有一个良好的系统设计(类设计), 才能用良好的代码规范
综合例子1
package zkhelper; import java.io.File; import java.util.LinkedList; import java.util.List; public class FileCounter { long current; long total; List<IprocessAction> listener=new LinkedList<IprocessAction>(); public void checkFile(String name, File file) throws Exception{ try { //long[] result=checkFileCnt(new File("d:/hyt/test60w")); System.out.println("正在计算文件夹..."); long count_dir=checkFileCount(file); total=count_dir; current=0; System.out.println("开始计算文件数量和容量..."); long[] result=checkFileSize1(file); //转算为M M=1024byte*1024Kb double d1=result[1]/((double)1024*1024); //转算为G G=1024byte*1024Kb*1024Mb double d2=(double)result[1]/(1024*1024*1024); System.out.println(name); System.out.println(String.format("容量: %.3f M", d1)); System.out.println(String.format("容量: %.3f G", d2)); System.out.println("文件数量:"+result[0]); System.out.println(String.format("容量: %.3fG, 数量: %d", d2, result[0])); } catch (Exception e) { e.printStackTrace(); } } public static long checkFileCount(File file) throws Exception { if(null==file) throw new Exception(String.format("指定目录为null")); if(!file.isDirectory()) throw new Exception(String.format("指定目录(%s)无效", file.getPath())); long count=0; File[] ff=file.listFiles(); for(File f : ff){ String name=f.getName().toLowerCase(); if(f.isDirectory()){ System.out.println(name); count++; long n=checkFileCount(f); count+=n; } } // System.out.println("file: "+file.getName()); // System.out.println(String.format("total file cnt: %d", cnt)); // System.out.println(String.format("total size: %d", amount)); return count; } public static long[] checkFileSize(File file) throws Exception { if(null==file) throw new Exception(String.format("指定目录为null")); if(!file.isDirectory()) throw new Exception(String.format("指定目录(%s)无效", file.getPath())); File[] ff=file.listFiles(); long count=0; long size=0; for(File f : ff){ String name=f.getName().toLowerCase(); if(f.isDirectory()){ long[] tmp=checkFileSize(f); count+=tmp[0]; size+=tmp[1]; }else if(f.isFile()){ boolean flag=false; if(name.lastIndexOf(".jpg")>=0 || name.lastIndexOf(".gif")>=0 || name.lastIndexOf(".tif")>=0) flag=true; if(!flag) continue; count++; long d=f.length(); size+=d; } } // System.out.println("file: "+file.getName()); // System.out.println(String.format("total file cnt: %d", cnt)); // System.out.println(String.format("total size: %d", amount)); long[] result={count, size}; return result; } public long[] checkFileSize1(File file) throws Exception { if(null==file) throw new Exception(String.format("指定目录为null")); if(!file.isDirectory()) throw new Exception(String.format("指定目录(%s)无效", file.getPath())); File[] ff=file.listFiles(); long count=0; long size=0; for(File f : ff){ String name=f.getName().toLowerCase(); if(f.isDirectory()){ current++; String[] param={String.valueOf(current), String.valueOf(total), name}; notify(param); long[] tmp=checkFileSize1(f); count+=tmp[0]; size+=tmp[1]; }else if(f.isFile()){ boolean flag=false; if(name.lastIndexOf(".jpg")>=0 || name.lastIndexOf(".gif")>=0 || name.lastIndexOf(".tif")>=0) flag=true; if(!flag) continue; count++; long d=f.length(); size+=d; } } // System.out.println("file: "+file.getName()); // System.out.println(String.format("total file cnt: %d", cnt)); // System.out.println(String.format("total size: %d", amount)); long[] result={count, size}; return result; } public void notify(String[] param){ for(IprocessAction e : listener){ e.actionPerom(param); } } public void addEvent(IprocessAction e){ listener.add(e); } public void removeEvent(IprocessAction e){ listener.remove(e); } /** * @param args the command line arguments */ public static void main(String[] args) throws Exception { String name="网球图片"; File file=new File("E:\\picture\\[20120102]莲花二村"); FileCounter fc=new FileCounter(); fc.addEvent(new IprocessAction() { @Override public void actionPerom(String[] param) { double n=100*new Double(param[0])/new Integer(param[1]); System.out.println(String.format("current: %s, total: %s, process: %.0f%%, name: %s", param[0], param[1], n, param[2])); } }); fc.checkFile(name, file); } interface IprocessAction { /** * 进度事件 * @param param {current, total, desc} */ public void actionPerom(String[] param); } }
FileCounter这个类是我去年写的, 我只依稀记得这个类是计算文件数量和容量的, 如今我要使用这个类了, 看着这个类的导航,
我面临以下问题
1.有动态函数和静态函数, 我要怎么使用呢, 这涉及到是否new FileCounter的问题, 这需要我去读代码
2.checkFileSize和checkFileSize1是怎么回事
3.checkFile, checkFileCount, checkFileSize, 看起来第一个函数包括了第2,3个函数的作用, 但我不敢肯定, 这需要我看一下checkFile的代码
4.公共域current和long是干什么用的
------------------------------------------------------------
这是添加注释之后的代码
package zkhelper; import java.io.File; import java.util.LinkedList; import java.util.List; /** * 检查子图数量和容量的工具类<br /> * <br /> * 调用方法:<br /> * 1.FileCounter fc=new FileCounter()<br /> * 2.fc.addEvent(IprocessAction); 注册进度事件<br /> * 3.checkFile(name, file); 开始运算<br /> * 科目, 子图容量, 子图数量会显示在控制台<br /> * @author lizw */ public class FileCounter { long current; //在checkFileSize用于递归算法, 记录当前是第几个目录 long total; //在checkFileSize用于递归算法, 记录一共有几个目录 List<IprocessAction> listener=new LinkedList<IprocessAction>(); /** * 在控制台打印科目子图容量和数量 * @param name 科目别名 * @param file 科目子图路径, 如//192.168.1.200/d$/2014yczk/YCZK/jykm/jy_dl/jpg/Current/Image * @throws Exception */ public void checkFile(String name, File file) throws Exception{ try { //long[] result=checkFileCnt(new File("d:/hyt/test60w")); System.out.println("正在计算文件夹..."); long count_dir=checkFileCount(file); total=count_dir; current=0; System.out.println("开始计算文件数量和容量..."); long[] result=checkFileSize(file); //转算为M M=1024byte*1024Kb double d1=result[1]/((double)1024*1024); //转算为G G=1024byte*1024Kb*1024Mb double d2=(double)result[1]/(1024*1024*1024); System.out.println(name); System.out.println(String.format("容量: %.3f M", d1)); System.out.println(String.format("容量: %.3f G", d2)); System.out.println("文件数量:"+result[0]); System.out.println(String.format("容量: %.3fG, 数量: %d", d2, result[0])); } catch (Exception e) { e.printStackTrace(); } } /** * 计算目录数量, 为统计子图数量的进度提供总数 * @param file * @return * @throws Exception */ public long checkFileCount(File file) throws Exception { if(null==file) throw new Exception(String.format("指定目录为null")); if(!file.isDirectory()) throw new Exception(String.format("指定目录(%s)无效", file.getPath())); long count=0; File[] ff=file.listFiles(); for(File f : ff){ String name=f.getName().toLowerCase(); if(f.isDirectory()){ System.out.println(name); count++; long n=checkFileCount(f); count+=n; } } // System.out.println("file: "+file.getName()); // System.out.println(String.format("total file cnt: %d", cnt)); // System.out.println(String.format("total size: %d", amount)); return count; } /** * 由于添加了进度事件, 此方法静态转成动态函数 * 计算图像的数和大小<br /> * 图像大小返回的是byte单位, 默认只统计(jpg, gif, tif)<br /> * 使用了递归算法 * @param file 科目子图路径, 如//192.168.1.200/d$/2014yczk/YCZK/jykm/jy_dl/jpg/Current/Image * @return {count, size} * @throws Exception */ public long[] checkFileSize(File file) throws Exception { if(null==file) throw new Exception(String.format("指定目录为null")); if(!file.isDirectory()) throw new Exception(String.format("指定目录(%s)无效", file.getPath())); File[] ff=file.listFiles(); long count=0; long size=0; for(File f : ff){ String name=f.getName().toLowerCase(); if(f.isDirectory()){ current++; long[] tmp=checkFileSize(f); count+=tmp[0]; size+=tmp[1]; String[] param={String.valueOf(current), String.valueOf(total), name, String.valueOf(count), String.valueOf(size)}; notify(param); }else if(f.isFile()){ boolean flag=false; if(name.lastIndexOf(".jpg")>=0 || name.lastIndexOf(".gif")>=0 || name.lastIndexOf(".tif")>=0) flag=true; if(!flag) continue; count++; long d=f.length(); size+=d; } } // System.out.println("file: "+file.getName()); // System.out.println(String.format("total file cnt: %d", cnt)); // System.out.println(String.format("total size: %d", amount)); long[] result={count, size}; return result; } /** * 完成一个目录文件数量和容量计算后触发 * @param param {current, total, name, count, size} */ public void notify(String[] param){ for(IprocessAction e : listener){ e.actionPerom(param); } } public void addEvent(IprocessAction e){ listener.add(e); } public void removeEvent(IprocessAction e){ listener.remove(e); } /** * @param args the command line arguments */ public static void main(String[] args) throws Exception { String name="网球图片"; File file=new File("E:\\图标素材"); // File file=new File("d:/hyt/test60w"); FileCounter fc=new FileCounter(); fc.addEvent(new IprocessAction() { @Override public void actionPerom(String[] param) { double n=100*new Double(param[0])/new Integer(param[1]); System.out.println(String.format("current: %s, total: %s, process: %.0f%%, name: %s", param[0], param[1], n, param[2])); } }); fc.checkFile(name, file); } interface IprocessAction { /** * 进度事件 * @param param {current, total, name, count, size} */ public void actionPerom(String[] param); } }
缩略版
/** * 检查子图数量和容量的工具类<br /> * <br /> * 调用方法:<br /> * 1.FileCounter fc=new FileCounter()<br /> * 2.fc.addEvent(IprocessAction); 注册进度事件<br /> * 3.checkFile(name, file); 开始运算<br /> * 科目, 子图容量, 子图数量会显示在控制台<br /> * @author lizw */ public class FileCounter1 { /** * 在控制台打印科目子图容量和数量 * @param name 科目别名 * @param file 科目子图路径, 如//192.168.1.200/d$/2014yczk/YCZK/jykm/jy_dl/jpg/Current/Image * @throws Exception */ public void checkFile(String name, File file) /** * 计算目录数量, 为统计子图数量的进度提供总数 * @param file * @return * @throws Exception */ public static long checkFileCount(File file) /** * 由于添加了进度事件, 此方法静态转成动态函数 * 计算图像的数和大小<br /> * 图像大小返回的是byte单位, 默认只统计(jpg, gif, tif)<br /> * 使用了递归算法 * @param file 科目子图路径, 如//192.168.1.200/d$/2014yczk/YCZK/jykm/jy_dl/jpg/Current/Image * @return {count, size} * @throws Exception */ public ong[] checkFileSize(File file) }
面对这份代码, 我的问题就完全解决了, 而且不需要读代码, 除了注释里的代码
对比:
1.有动态函数和静态函数, 我要怎么使用呢, 这涉及到是否new FileCounter的问题, 这需要我去读代码
2.checkFileSize和checkFileSize1是怎么回事
3.checkFile, checkFileCount, checkFileSize, 看起来第一个函数包括了第2,3个函数的作用, 第2个看起来是计算文件数量, 第3个看起来是计算文件容量, 但我不敢肯定, 这需要我看一下checkFile的代码
4.公共域current和total是干什么用的
5.checkFile的输出? 为什么返回是void
重构注释后
1.从类的说明看到, 直接用动态方法, 还额外知道了, 有进度功能, 实现接口即可实现进度监控, 差点又跑去写一段进度监控代码, 原来一年前我已经想到计算时间太长的卡顿问题
2.checkFIleSize1, 是由于添加了进度事件, 从静态函数改动态函数的原因
3.由于第1点的关系, 我已经知道了直接调用checkFile即可, 而且上面注释已经告诉我, fileCount是计算文件夹目录而不是计算文件数量, fileFileSize是计算文件数量和容易, 而不是只是容量, 这里不需要再深入了, 只有出现bug时, 我才需要深入
4.current, total从注释中看出来是checkFileSize递归算法用的
5.不需要看代码就知道, checkFile的输出是控制台, 这个类是方便开发人员自己使用的
额外的
看着checkFileCount上面的"计算目录数量, 为统计子图数量的进度提供总数", 我不用看代码就回忆起来了, 进度的显示是按目录的进度, 而不是真实的文件数量的进度
综合例子2
public class Demo1 { public void insertDataIntoDb(){ try { Class c=Class.forName("com.mysql.jdbc.Driver"); c.newInstance(); String jdbc="jdbc:mysql://localhost/demo?user=root"; Connection con=DriverManager.getConnection(jdbc); Statement stmt=con.createStatement(); String sql="select * from employee;"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()){ String[] text={rs.getString(2), rs.getString(3), rs.getString(4)}; System.out.println(Arrays.toString(text)); } } catch (Exception e) { e.printStackTrace(); } } }
在insertDataIntoDb里没有关闭数据库连接
这个函数执行完后, 数据库连接会一直处于sleep状态, 造成严重的不可预知后果
要么数据库连接sleep到达上限, 由数据库回收连接
要么java虚拟机gc时清掉这个线程, 把数据库连接释放
如果遇到多几个这种代码, 数据库连接没能及时回归, 系统在状态下, 别的地方创建数据库失败就等着你, 特别是并发的情况, 这种错误通过静态单元测试是测不出来的
这是一个很可怕的bug
当然我们写代码时不可能时时刻刻想着大并发大压力的情况, 但资源的及时回收却是很容易做到的
改进
public class Demo1 { public void insertDataIntoDb(){ try { Class c=Class.forName("com.mysql.jdbc.Driver"); c.newInstance(); String jdbc="jdbc:mysql://localhost/demo?user=root"; Connection con=DriverManager.getConnection(jdbc); Statement stmt=con.createStatement(); String sql="select * from employee;"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()){ String[] text={rs.getString(2), rs.getString(3), rs.getString(4)}; System.out.println(Arrays.toString(text)); } con.close(); //在这里及时资源回收 } catch (Exception e) { e.printStackTrace(); } } }
这样错误的, 如果sql语句错误, 就会在
ResultSet rs=stmt.executeQuery(sql);
这一行直接跳到exception catch
con.close()这行代码就会被忽略掉
同样造成资源没有及时回收的严重bug
正确的写法应该是写在
try catch 的 finally 里面
public class Demo1 { public void insertDataIntoDb(){ Connection con=null; try { Class c=Class.forName("com.mysql.jdbc.Driver"); c.newInstance(); String jdbc="jdbc:mysql://localhost/demo?user=root"; con=DriverManager.getConnection(jdbc); Statement stmt=con.createStatement(); String sql="select1 * from employee;"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()){ String[] text={rs.getString(2), rs.getString(3), rs.getString(4)}; System.out.println(Arrays.toString(text)); } } catch (Exception e) { e.printStackTrace(); } finally { try { con.close(); //在这里及时资源回收 } catch (SQLException ex) { Logger.getLogger(Demo1.class.getName()).log(Level.SEVERE, null, ex); } } } }
发表评论
-
java手动运行命令
2018-05-29 18:27 539java windows下启动命令 启动classs jav ... -
java 服务器调试
2017-04-13 21:24 785Unsupported major.minor version ... -
java maven 个人汇总
2017-03-25 16:52 775在netbeans里, 使用自动构建时跳过测试 cd D:\ ... -
java 1.8 linux x64
2015-12-27 22:57 744Installation of the 64-bit JDK ... -
netty 通过端口调用关闭
2015-12-26 17:48 2170package websocketdemo.timeser ... -
java 内存溢出陷阱
2015-12-25 21:59 423tomcat - reload tomcat可以不重启对一个工 ... -
java 使用内存查看方法
2015-12-24 23:03 677一.常用java内存查看命令 jmap -dump:form ... -
java jconsole 远程监控
2015-06-29 20:39 890jconsole 远程监控 一. win ... -
java jar getResource() null exception
2013-09-23 20:59 9861. Adding resource folder t ... -
note about property & charset
2011-07-13 21:59 929usually, I use property to rw d ...
相关推荐
在软件开发过程中,代码规范的重要性不言而喻。它不仅有助于提高代码的可读性和可维护性,还能确保团队成员之间的代码风格一致,减少沟通成本。Java作为一种广泛使用的编程语言,同样强调代码规范。本篇文章将详细...
在MATLAB编程中,代码规范是提升代码可读性、可维护性和团队协作效率的关键因素。这份名为"Matlab之代码规范"的压缩包资源,包含了一份详细的MATLAB代码规范指南,以及相关的编程实例,旨在帮助程序员遵循最佳实践,...
在软件开发过程中,代码规范和模板的使用是至关重要的,它们能够提高代码的可读性、可维护性和团队协作效率。华为作为全球领先的ICT解决方案提供商,对于代码质量有着极高的要求,因此制定了一套详尽的代码规范。这...
阿里巴巴代码规范,又被称为阿里巴巴Java开发手册泰山版,是一份由阿里巴巴技术团队编写的、旨在规范Java开发者编程行为和提高代码质量的文档。该手册不仅关注编码细节,还涉及软件开发的多个方面,如异常处理、日志...
iOS 软件代码规范 iOS 软件代码规范是一份详细的编程规范,旨在指导 iOS 软件开发过程,提高代码质量和可维护性。这份规范涵盖了编程指引原则、布局、注释、命名规则、变量、常量、宏与类型、表达式与语句、函数、...
Java代码规范文档中涉及的知识点涵盖了Java编程实践中的命名风格和代码组织方式,旨在为Java开发人员提供一份行业内部开发的准则,确保代码的可读性、一致性和维护性。以下是从提供的文档内容中提炼出的相关知识点:...
百度前端代码规范是一份旨在统一前端开发标准的文档,由百度前端团队或社区成员共同维护和分享。该规范涵盖的内容非常全面,包括但不限于Javascript编码规范、HTML编码规范、CSS编码规范、Less编码规范、E-JSON数据...
Java和前端代码规范是软件开发中的重要组成部分,尤其是在大型企业如阿里巴巴这样的公司中,它们对于保持代码质量和团队协作至关重要。本压缩包包含了阿里巴巴制定的Java和前端开发的详细规范,帮助开发者遵循一致的...
单片机程序编写是电子工程和嵌入式系统开发中的重要环节,良好的代码规范对于项目的可维护性、可读性和团队协作至关重要。本工具旨在帮助开发者遵循一定的编码标准,提高代码质量,降低后期维护难度。以下是一些关于...
### 代码规范详解 #### 一、引言 在软件开发过程中,良好的代码规范对于确保项目的可维护性、可读性和一致性至关重要。本篇将基于《代码规范代码规范.txt》的内容,详细介绍其中提及的各项规范要点及其重要性。 #...
### 浅析框架与代码规范 #### 代码规范的重要性及实践方法 在现代软件开发过程中,代码规范扮演着至关重要的角色。它不仅有助于提高代码的可读性和可维护性,还能促进团队之间的协作效率,减少潜在的错误和缺陷。...
《华为代码规范-C C++开发》是一份详细指导C++和C语言开发人员遵循的编程准则,旨在提高代码质量、可读性和维护性。这份规范不仅适用于华为内部的开发项目,也对广大的C++和C开发者具有重要的参考价值。其中涵盖了从...
首先,标题为《代码规范.pdf》,这表明该文档是一份关于编程代码规范的文件,它很可能详述了在编写代码时应遵循的规则和标准。代码规范是为了统一开发人员的编码风格,提高代码的可读性、可维护性,从而确保项目的...
《阿里巴巴Java代码规范》是Java开发者们遵循的一套专业编程指南,旨在提高代码质量、可读性和维护性。这份规范由阿里巴巴集团内部的专家团队制定,经过多年的实践和完善,已经成为业界广泛参考的标准之一。以下是对...
前端代码规范
本篇文章将详细阐述C++代码规范,旨在提升团队协作效率,确保代码质量。 1. **命名规范**:C++中的变量、函数、类等标识符应遵循清晰、简洁的命名规则。推荐使用驼峰式命名(CamelCase)或下划线连接命名(snake_...
《阿里代码规范13213.pdf》是一个重要的资源,主要针对Java开发人员,旨在提供一套标准和指导原则,以确保代码的质量、可读性和可维护性。在Java开发过程中,遵循良好的编码规范至关重要,因为它有助于团队协作,...
Java代码规范是编程实践中至关重要的一个方面,它旨在确保代码的质量、可读性和维护性。以下是一些核心的Java代码规范要点: 1. **命名规范**: - 类名使用大驼峰命名法,所有单词首字母大写,例如`ClassName`。 ...
在前端开发领域,代码规范是确保团队协作效率、提高代码可读性和维护性的关键。"前端代码规范"这个压缩包文件很可能包含了一系列关于如何编写整洁、一致且易于理解的前端代码的指南。以下是对这些规范的一些核心内容...
这是借鉴、引用的是京东前端代码规范。