151-suggestions-for-improving-java

不要在常量和变量中出现易混淆的字母

包名全小写,类名首字母全大写,常量全部大写并用下划线分隔,变量采用驼峰命名法(Camel Case) 命名等,这些都是最基本的Java 编码规范,是每个Javaer 都应熟知的规则,但是在变量的声明中要注意不要引入容易混淆的字母。

尝试阅读如下代码,思考一下打印出的i等于多少:

1
2
3
4
5
6
public class Client {
public static void main(String[] args) {
long i = 1l;
System.out.println("i的两倍是:" + (i+i));
}
}

肯定有人会说:这么简单的例子还能出错?运行结果肯定是22!

实践是检验真理的唯一标准,将其拷贝到Eclipse 中,然后Run 一下看看,或许你会很奇怪,结果是2,而不是22,难道是Eclipse 的显示有问题,少了个“2”?
因为赋给变量i 的数字就是“1”,只是后面加了长整型变量的标示字母“l” 而已。别说是我挖坑让你跳,如果有类似程序出现在项目中,当你试图通过阅读代码来理解作者的思想时,此情此景就有可能会出现。
所以,为了让您的程序更容易理解,字母“l”(还包括大写字母“O”)尽量不要和数字混用,以免使阅读者的理解与程序意图产生偏差。
如果字母和数字必须混合使用,字母“l”务必大写,字母“O”则增加注释。

字母“l”作为长整型标志时务必大写。


莫让常量蜕变成变量

常量蜕变成变量?你胡扯吧,加了final和static的常量怎么可能会变呢?不可能二次赋值的呀。真的不可能吗?

看我们神奇的魔术,代码如下:

1
2
3
4
5
6
7
8
9
10
public class Client {
public static void main(String[] args) {
System.out.println("常量会变哦:" + Const.RAND_CONST);
}
}
/*接口常量*/
interface Const{
//这还是常量吗?
public static final int RAND_CONST = new Random().nextInt();
}

RAND_CONST 是常量吗?它的值会变吗?绝对会变!这种常量的定义方式是极不可取的,常量就是常量,在编译期就必须确定其值,不应该在运行期更改,否则程序的可读性会非常差,甚至连作者自己都不能确定在运行期发生了何种神奇的事情。

因此不要想着使用常量会变的这个功能来实现序列号算法、随机种子生成等,除非这真的是项目中的唯一方案,否则就放弃吧,常量还是当常量使用。

务必让常量的值在运行期保持不变。


三元操作符的类型务必一致

三元操作符是if-else的简化写法,在项目中使用它的地方很多,也非常好用,但是好用又简单的东西并不表示就可以随便用,我们来看看下面这段代码:

1
2
3
4
5
6
7
8
public class Client {
public static void main(String[] args) {
int i = 80;
String s = String.valueOf(i < 100 ? 90 : 100);
String s1 = String.valueOf(i < 100 ? 90 : 100.0);
System.out.println("两者是否相等: "+s.equals(s1));
}
}

分析一下这段程序:

  • i是80,那它当然小于100,两者的返回值肯定都是90,再转成String类型,其值也绝对相等,毋庸置疑的。
  • 分析得有点道理,但是变量s中三元操作符的第二个操作数是100,而s1的第二个操作数是100.0,难道没有影响吗?
  • 不可能有影响吧,三元操作符的条件都为真了,只返回第一个值嘛,与第二个值有一毛钱的关系吗?貌似有道理。
  • 果真如此吗?我们通过结果来验证一下,运行结果是:“两者是否相等:false”,什么?不相等,Why?
  • 问题就出在了100和100.0这两个数字上,在变量s中,三元操作符中的第一个操作数(90)和第二个操作数(100)都是int 类型,类型相同,返回的结果也就是int 类型的90。而变量s1 的情况就有点不同了,第一个操作数是90(int 类型),第二个操作数却是100.0,而这是个浮点数,也就是说两个操作数的类型不一致。可三元操作符必须要返回一个数据,而且类型要确定,不可能条件为真时返回int 类型,条件为假时返回float 类型,编译器是不允许如此的。所以它就会进行类型转换了,int 型转换为浮点数90.0,也就是说三元操作符的返回值是浮点数90.0,那这当然与整型的90不相等了。
  • 这里可能有读者疑惑了:为什么是整型转为浮点,而不是浮点转为整型呢?

这就涉及三元操作符类型的转换规则:

  • 若两个操作数不可转换,则不做转换,返回值为Object类型。
  • 若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。
  • 若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
  • 若两个操作数都是直接量数字(Literal[字面量]),则返回值类型为范围较大者。

保证三元操作符中的两个操作数类型一致,即可减少可能错误的发生。


慎用Lombok

最近在使用了一下Gitpod 来写Github 上的代码,但是发现一运行,一大堆错误,查看错误后发现都是Lombok 的依赖错误,因为在IDEA 中的Spring Boot 项目都需要Lombok 的插件,但是在Gitpod 中是没有的,那么我就会想到,如果我有一天需要在一个我不熟悉的环境下去重新构建代码,那是不是就无法操作了。

所以,建议大家慎用Lombok ,它既然能为你带来方便,那么就能为你带来麻烦。

这个只是我的个人观点!!!


使用枚举类构建单例模式

地址


个人备注

此博客内容均为作者学习《编写高质量代码-改善Java程序的151个建议》所做笔记,侵删!
若转作其他用途,请注明来源!