建议1 不要在常量和变量中出现易混淆的字母
首先,包名要全部小写,类名要首字母全部大写(CamelCase),变量名字要采用驼峰命名法命名等等,但是在变量声明中要注意不要引入容易混淆的字母,尝试阅读如下代码,思考一下打印出的变量i等于多少:
public static void main(String[] args) {
long i = 1l;
System.out.println("i的两倍是:" + (i + i));
}
这么简单的例子肯定不会出错,运行结果22,拷贝运行一下,结果是2.
赋值给变量i的值就是数字1,后面是加了一个长整型变量标示字母"l"而已,当你试图通过阅读代码来理解作者的思想时,此情此景就可能会出现,所以为了让您的程序更容易理解,字母"l"(还有大写字母O)尽量不要和数字混用,以免阅读者理解与程序意图产生偏差,如果混用,字母"l"务必大写,字母"O"则增加注释.
注意: 字母"l"作为长整型标示时务必大写
建议2 莫让常量蜕变为变量
有人说常量是不可能蜕变为变量的,用了final和static怎么可能会变,看看一下代码:
public static void main(String[] args) {
long i = 1l;
System.out.println("常量会变的:" + Const.RAND_CONST);
}
/*接口常量*/
interface Const{
public static final int RAND_CONST = new Random().nextInt();
}
RAND_CONST是常量么,值会变么,绝对会变,这种常量的定义方式是非常不可取的,常量在编译期就必须确定其值,不应该在运行期改变他的值
注意: 务必让常量的值在运行期保持不变
建议3 三元操作符的类型务必一致
三元操作符是if-else的简化写法,在项目中使用它的地方很多,也很好用,但是好用又简单的东西并不是刻意随便用,看看下面一段代码:
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”.
问题就是出在100和100.0这两个数上,在变量s中,三元操作符中的第一个操作数和第二个操作数都是int类型,类型想同,返回的也就是int类型的90,在转换成Striing,而变量s1却不是,第一个操作数90(int类型),第二个操作数是100.0(浮点数),两个操作数类型不一致,但是三元操作符还必须要返回一个类型的数据,也不可能为真时返回int类型,为假时返回float类型,这时他就会进行类型转换,int类型就会转换为浮点数的90.0,返回的也就是浮点型的90.0,所以与整形的90不相等,下面是三元操作符类型转换规则:
1). 若两个操作数不可转换,则不做转换,返回Object类型.
2).若两个操作数是明确类型的表达式(例如变量),则按照正常的二进制数字来转 换,int类型转换为long类型,long类型转换为float类型等.
3).若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么若是数字S在T的范围内,则会转换为T类型,若S超出了T类型的范围,则T转换为S类型(可以参考"建议22",暂未更新).
4)若两个操作数都是直接量数字,则返回值类型为范围较大者.
知道原因了,也就有了相应的解决办法:保证三元操作符中的两个操作数类型一致,即可减少可能错误的发生
建议4 避免带有变长参数的方法重载
在项目或系统的开发中,需要提高代码的复用性和灵活度,这样就会导致我们经常传递一些不确定的参数数量到方法中,在Java5之前常用的设计方法就是把形参声明为一个Collection或者其子类型(List)又或者是数组类型,这种方式的缺点就是需要对null值进行判断以及长度为0的Collection或数组进行判断,而Java5以后引入边长参数就是为了更好地提高方法的复用性,但是变长参数的使用也有一定的规则,变长参数必须是参数列表的最后一个参数,一个参数列表也不能定义多个变长参数.看看一下代码:
public static void main(String[] args) {
BasicStandardApplication basicStandardApplication = new BasicStandardApplication();
basicStandardApplication.calPrice(49900,75);
}
/*简单的折扣计算*/
public void calPrice(int price, int disCount){
float knockdownPrice = price * disCount / 100.0F;
System.out.println("简单折扣后的价格是:" + formateCurrency(knockdownPrice));
}
/*复杂多折扣计算*/
public void calPrice(int price, int... disCounts){
float knockdownPrice = price;
for (int disCount: disCounts) {
knockdownPrice = knockdownPrice * disCount / 100;
System.out.println("多折扣计算后的价格:" + formateCurrency(knockdownPrice));
}
}
private String formateCurrency(float knockdownPrice) {
return NumberFormat.getCurrencyInstance().format(knockdownPrice/100);
}
这是一个计算商品折扣的简单例子,带有两个参数的calPrice方法进行了重载,其中带有变长参数的calPrice则是计算多折扣的计算方式,也就是类似于生活中的折上折.
仔细看看这两个重载的方法,有一点小特殊,带有变长参数的方法范畴覆盖了单个calPrice(int price, int disCount)方法,那么对于calPrice(49900,75)这种类型的调用,到底该调用那个方法呢,如果传递的参数是这个calPrice(49900,75,95)毫无疑问,会调用calPrice(int price, int… disCounts),只有这一个是符合参数类型的,但是现在75即可以编译为int类型的75,也可以编译成数组类型的{75}
运行一下结果:
简单折扣后的价格是:¥374.25
看来调用的是第一个方法,编译器首先会会确认方法是否符合方法签名条件,但是为什么会选择第一个不是第二个,因为int类型是是原生数据类型,而数组确实一个对象类型,java编译器偷懒,会从简单的开始"猜想",只要符合条件就会编译通过,所以就出现了现在这个问题.
所以为了我们的代码能被看懂,还是慎重使用变长参数的方法重载吧
后续继续更新