程序中被注释掉的代码就像一个僵尸,空有一个躯体,但已经失去了生命。这种代码的存在有百害而无一利,越早删除越好。
删除被注释的代码的好处:
1、降低信噪比
本来阅读别人的代码就够费劲了,再加上注释就更不用说了。
2、造成歧义妨碍调试
3、影响关键词搜索
4、影响代码重构
如果打算要注释一段代码,先问问自己:
1、什么时候会取消注释?
2、是否能删掉它,需要时从版本控制里找回?
3、这种需要来回切换注释的功能可否通过配置实现?
4、重构时也需要重构这些注释掉的代码吗?
大多数人都会说,方法不能太长,但也不能定死,要具体问题具体分析。再追问一下,有人会说,不超过200行,100行,50行,30行都有。另有人说,面向对象风格的可以短些,面向过程风格的可以长些。也有人说,一个方法不超过一屏幕就行(姑且不论显示器大小,字体大小和分辨率问题)。
先摘录一段Martin Fowler《重构》P110-P111 中的一段话:
人们有时会问我,一个函数多长才合适?在我看来,长度不是问题,关键在于函数名称和函数本体之间的语义距离(semantic distance)。如果提炼动作(extracting)可以强化代码的清晰度,那就去做,就算函数名称比提炼出来的代码还长也无所谓。
说了直白点,函数名是干什么,函数体是怎么干。当2者不是那么能容易分辨出来时,就需要提炼出函数来,让代码更好懂。
既然大师都说了,长度不是问题了吗,那干吗还要追究函数长度规范呢?
其实大师讲的是对于懂得编程之道的人而言,不用关心长度,因为小函数是必然的结果。但在开发实践中,适当的函数长度限制值,可以给予我们警示,为什么这个方法写长了?哪里不对劲了?
对于这个问题我的回答是:Java函数不应超过15行。
为什么定这个数呢?
一方面,这个是基于多年开发实践的总结。15行其实已经是一个比较宽松的标准,开发人员稍加培训就可以实际贯彻,而符合这个标准的函数也能达到良好的可读性。
另一方面,这是基于对函数复杂度和代码行数之间关联关系的认识。
我采用一个简单的数学公式:
方法复杂度 >= 代码行数^2 (该公式参考于 gerald m. weinberg 《质量·软件·管理(第1卷)——系统思维》)
以下为了简化,只以最低增长方式,平方数进行计算。
以一个函数的行数,从1行到20行为例,见下图:

当函数行数到达10行以上,函数复杂度就开始大幅度攀升。
当代码行数达到20行时(复杂度400),其复杂度已经是14行时(复杂度 196)的2倍。
因此我将代码规范定在15行。
下面我们运行此公式,来分析一下提炼小函数的好处。
例如,有1个100行的函数,分解为11(含自身)个10行的函数。
原复杂度= 100^2=10000。
分解后复杂度= 11×(10^2)= 1100。
分解后的复杂几乎是分解前的 1/9,几乎降低了1个数量级。这就解释了为什么长方法分解之后,可维护性大幅度提高。
也就无怪乎有同学表示维护1000行以上的函数,有种生不如死的感受。
在生产环境中tomcat内存设置不好很容易出现内存溢出。造成内存原因是不一样的,当然处理方式也不一样。 这里根据平时遇到的情况和相关资料进行一个总结。常见的一般会有下面三种情况:
1.OutOfMemoryError: Java heap space
2.OutOfMemoryError: PermGen space
3.OutOfMemoryError:unable to create new native thread.

对于前两种情况,在应用本身没有内存泄露的情况下可以用设置tomcat jvm参数来解决。(-Xms, -Xmx, -XX:PermSize, -XX:MaxPermSize),最后一种可能需要调整操作系统和tomcat jvm参数同时调整才能达到目的。
第一种:是堆溢出。
在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。没有内存泄露的情况下,调整-Xms,-Xmx参数可以解决。
-Xms:初始堆大小
-Xmx:最大堆大小
但堆的大小受下面三方面影响:
1.相关操作系统的数据模型(32-bt还是64-bit)限制;(32位系统下,一般限制在1.5G~2G;我在2003 server 系统下(物理内存:4G和6G,jdk:1.6)测试 1612M,64为操作系统对内存无限制。)
2.系统的可用虚拟内存限制;
3.系统的可用物理内存限制。
堆的大小可以使用 java -Xmx***M version 命令来测试。支持的话会出现jdk的版本号,不支持会报错。
-Xms, -Xmx一般配置成一样比较好比如set JAVA_OPTS= -Xms1024m -Xmx1024m 阅读全文…
1 bit 二进制数据
1 byte = 8 bit
1 字母 = 1 byte = 8 bit
1 汉字 = 2 byte = 16 bit
1. bit:位
一个二进制数据0或1,是1bit;
2. byte:字节
1 byte = 8 bit
3. 一个英文字符占一个字节;
1 字母 = 1 byte = 8 bit
4. 一个汉字占2个字节;
1 汉字 = 2 byte = 16 bit
5. 标点符号
A>. 汉字输入状态下,默认为全角输入方式;
B>. 英文输入状态下,默认为半角输入方式;
C>. 全角输入方式下,标点符号占2字节;
D>. 半角输入方式下,标点符号占1字节;
故:汉字输入状态下的字符,占2个字节 (但不排除,自己更改了默认设置);
英文输入状态下的字符,占1个字节 (但不排除,自己更改了默认设置);
老美在发明电脑时,肯定以自己的英文字母-即他们自认为的字符为最小的存储计量单位,于是也就有了不规范的1字符=1byte, 岂不知还有我们伟大的汉字计量单位,NND,一个汉字也是一个字符,我们的1汉字字符就等于2byte,后来,他们可能意识到这个尴尬的问题,于是又标榜为:一个字母为一个标准字符,去球吧,谁整天没事说个字符还“标准字符”,所以啊,个人认为:字符,不能用于标准的计量单位。
Google Code允许用户以Http协议Update代码,但Commit时必须以Https协议。
所以在SVN目录下利用Relocate功能将SVN协议从Http改为Https后就可以了。

setHeader(name,value) :如果Header中没有定义则添加,如果已定义则用新的value替换原用value值。
addHeader(name,value) :如果Header中没有定义则添加,如果已定义则原有value不改变。
由于Servlet默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全问题。然而,很多人编写Servlet程序时并没有注意到多线程安全的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题。
Servlet的多线程机制
Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行,如图1所示。

这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web应用时如果不注意线程安全的问题,会使所写的Servlet程序有难以发现的错误。
Servlet的线程安全问题
Servlet的线程安全问题主要是由于实例变量使用不当而引起的,这里以一个现实的例子来说 阅读全文…
在开始前给大家提3点建议!
不要使用System.out.println作为调试工具
把所有涉及到的组件日志级别激活并使用
使用日志分析器来读取日志
1.条件断点

如果你不知道如何添加断点,只需点击左边面板(行号前面)断点即被创建。在调试界面中,“断点”视图会把所有被创建的断点列出来。我们可以给它加一个布尔条件,也就是说,该断点会被激活并且如果布尔条件为真,就会执行该断点,否则将会跳过往下执行。
2.异常断点

在断点视图中,有一个J!标记按钮!我们可以使用该按钮来添加一个Java异常断点。例如,我们想让程序在遇到空指针异常(NullPointerException)时,仍然能继续调试,那么我们可以使用该按钮来添加一个异常断点!
3.监视点

这是一个非常好的功能,当选定的属性访问或修改程序时,程序会停止执行并允许进行调试。在Outline视图中选择一个类变量并从上下文菜单中选择切换监视点,属性监视点将会被创建,在断点(Breakpoints)视图中会把所有监视点用列表的形式显示出来。
4.评估/检查 阅读全文…
先看代码:
public static String bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[ i ] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
上面是将byte[]转化十六进制的字符串,注意这里b[ i ] & 0xFF将一个byte和 0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出:b[ i ] & 0xFF 运算后得出的仍然是个int,那么为何要和 0xFF 进行与运算呢?直接 Integer.toHexString(b[ i ]);,将 byte 强转为 int 不行吗?答案是不行的。
其原因在于:
1.byte的大小为 8bits 而 int 的大小为 32bits ;
2.java的二进制采用的是补码形式 ;
在这里先温习下计算机基础理论:
byte是一个字节保存的,有8个位,即8个0、1。
8位的第一个位是符号位,也就是说0000 0001代表的是数字1 ,1000 0001代表的就是-1 。
所以正数最大位0111 1111,也就是数字127;负数最大为1111 1111,也就是数字-128 。
上面说的是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码(补码就是原码按位取反再加1,下边的解释有些抽象。):
1、反码:
一个数如果是正,则它的反码与原码相同;
一个数如果是负,则符号位为1,其余各位是对原码取反;
2、补码:利用溢出,我们可以将减法变成加法
对于十进制数,从9得到5可用减法:
9-4=5 因为4+6=10,我们可以将6作为4的补数
改写为加法:
9+6=15(去掉高位1,也就是减10)得到5.
对于十六进制数,从c到5可用减法:
c-7=5 因为7+9=16 将9作为7的补数
改写为加法:
c+9=15(去掉高位1,也就是减16)得到5.
在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。
⑴一个数为正,则它的原码、反码、补码相同
⑵一个数为负,则符号位为1,其余各位是对原码取反,然后整个数加1
- 1的原码为 10000001
- 1的反码为 11111110
+ 1
- 1的补码为 11111111
0的原码为 00000000
0的反码为 11111111(正零和负零的反码相同)
+1
0的补码为 100000000(舍掉打头的1,正零和负零的补码相同)
Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位,例如补码11111111的十进制数为 -1 ,转换为int时变为 11111111111111111111111111111111,好多1啊,呵呵!即 0xffffffff,但是这个数是不对的,这种补位就会造成误差。
和0xff相与后,高24比特就会被清0了,结果就对了。
重要信息:
Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。
而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。
很多人已经有了几年的开发经验,但还是没有充分发挥自己的潜力,本文总结了十种程序员无法意识到自己潜力的原因,意在让更多程序员发掘出自己的潜力,从而成为强大的developer。
1. 太害怕学不会新的工具、语言和框架
一般的程序员会墨守他们最喜欢的工具,而不希望学习新的,因为他们认为,离开了那些语言和工具,多年的经验就会付诸东流。而强大的程序员会拥抱那些挑战和机会,积极地学习新的工作方式。
2. 直到特性“完成”的时候才会提交。(但永远都不会完成!)
他在MarkedUp公司中把这种行为叫做“囤积提交(commit hoarding)”。有些程序员没有足够的信心来承受团队中其他成员的批评和审查,因此会把自己的工作藏起来,直到“完成”状态才提交。
这种开发者会损害团队中其他人员的生产力,因为团队看不到他每天的成果,而且他也不会在正常开发的过程中寻求帮助,这样就会造成很多“最后一分钟”的缺陷,从而让交付延迟。而强大的程序员会知道,代码并不是他们自己,因此会把代码经常自信地呈现在其他团队成员的眼前,获得批评和建议。
3. 只是“知其然”会很危险
在微软最近在C# 5.0中引入的async和await关键字为例,这两个关键字会让创建和管理异步调用变得很容易,但是也会造成上下文切换、对共享资源进行多线程访问的成本,仅仅对此有基本了解的程序员会盲目地使用这些特性,把所有I/O调用都封装成C#中的Task对象,这会创建出危险的、不可预测的而且非常难以测试的代码。
好的开发者不仅“知其然”,而且会了解为什么这么做以及应该在什么样的条件下使用。
4. 分析瘫痪(Analysis paralysis)
分析瘫痪是指在程序开发初期进行系统分析,常因为太过执着于控制所有可能的变化和意外,而造成大量时间的浪费,裹足不前。这是一种很经典的问题,会影响很多一般的程序员。它通常是由过度分析造成的,但是Aaron认为其根本原因在于不敢做出坏的决定。一般的程序员会担心犯错,只想一次成功。
而强大的程序员不会害怕,他们会编写很烂的代码,对其进行单元测试,如果认为无法达到目的,就会在45分钟之内把它抛弃。强大的程序员会积极地限制用来研究的时间,因为他们知道那是个陷阱——看起来是有效的,但经常都无效。
5. 没有对工具和开发过程投入
阅读全文…