建议1:
不要在常量和变量中出现容易混淆的字母:如long i = 1L,表示long类型,后面的l最好大写
建议2:
不要让常量蜕变成变量,常量应该在编译期就确定。
如:publicstatic final int RAND_CONST = new Random().nextInt();
建议3:
三元操作符的类型务必一致
如:
public class Suggest3 {
public static void main(String[] args) {
int i = 80;
String s = String.valueOf(i < 100 ? 90 : 100);
// 100.0为float类型,返回值时,90会被自动提升为90.0,所以两个String不是同一个对象
String s1 = String.valueOf(i < 100 ? 90 : 100.0);
System.out.println(s == s1);
/*
* 上面提到三元运算符的一个类型转换问题
* 1,若两个操作数不可转换,则不转换,返回Object
* 2,若连个数都是明确的表达式,则int转long,long转float
* */
}
}
建议4:
使用变长方法时,避免带有变长参数的方法重载:
如:
public class Suggest4 {
public static void main(String[] args) {
// 执行的是简单折扣的方法,虽然多次折扣的方法也包括了改参数类型
// 最好不要用,容易引起混淆
calPrice(100, 75);
calPrice(100, 75, 80);
}
public static void calPrice(int price, int discount) {
float money = price * discount / 100.0F;
System.out.println("折扣后的价是:" + money);
}
// 方法重载 ,传入可变长参数
public static void calPrice(int price, int... discount) {
float money = price;
for (int d : discount) {
money = money * d / 100.0F;
}
System.out.println("多次折扣后的价是:" + money);
}
}
建议5:
警惕自增的陷阱:
看下面这段代码
public class Suggest5 {
public static void main(String[] args) {
int count = 0;
for (int i = 0; i < 10; i++) {
// count++是一个表达式,返回count自加前的值
count = count++;
}
System.out.println(count);
}
}
输出count的值是0
建议6:
避免instanceof非预期结果
//详细分析instanceof()
public class Suggest6 {
public static void main(String[] args) {
// 判断String对象是否是Object对象的实例
// true
boolean b1 = "cloud" instanceof Object;
// String对象是否是String的实例
// true
boolean b2 = new String() instanceof String;
// Object对象是否是String的实例
// false,Object是String的父类,编译可以通过
boolean b3 = new Object() instanceof String;
// 拆箱类型是否是装箱类型的实例,编译不通过,char类型是基本类型,instanceof只用于对象的判断
// boolean b4 = 'A' instanceof Character;
// 空对象是否是String的实例
// false,规则:如果左操作数是null,则直接返回false不再运算右边
boolean b5 = null instanceof String;
// 转换类型后的null是否是String类型的对象
// false,null没有类型,做类型转换后还是null
boolean b6 = (String) null instanceof String;
// Data对象是否是String对象的实例,编译不通过,Date类和String没有继承或实现关系
// boolean b7 = new Date() instanceof new String;
}
}
建议7:
使用偶判断,不用奇判断
如下面:
可看到-1也是偶数
底层运算公式是: dividend表示被除数-1,divisor表示除数2
dividend– dividend/divisor * divisor
所以最好用偶判断
建议8:
在接口中不要存在实现代码
如下:
//接口中可以声明常量,声明抽象方法,也可继承父接口
interface B {
// 声明一个S类型的常量,指向匿名对象
public static final S s = new S() {
public void doSomething() {
System.out.println("在接口中实现了");
}
};
}
interface S {
public void doSomething();
}
public class Suggest8 {
public static void main(String[] args){
B.s.doSomething();
}
}
使用String字符串的一些建议:
建议9:
推荐使用String直接量赋值,如:String str = “abcd”;
代码如下:
public class Suggest9 {
public static void main(String[] args) {
String str1 = "itheima";
String str2 = "itheima";
String str3 = new String("itheima");
String str4 = str3.intern();
// true,这里用到了一个字符串池的技术,主要为了避免产生大量String对象
// 在使用直接量赋值时,会先检查字符串池中有没有相等的值,有就不再创建对象,而是返回池中的对象引用
System.out.println(str1 == str2);
// false,new String不会检查字符串池,而是直接创建一个新对象,也不会把对象放入字符串池中
System.out.println(str1 == str3);
// true,intern()方法会检查池有没有值相同的对象,有就放回池中对象的引用,没有就将当前对象放入池中,并返回当前对象
System.out.println(str1 == str4);
}
}
String类是一个不可变(Immutable)对象
1,String类是final修饰的,不可继承,不可能产生一个String的子类
2,在String提供的方法中,如果有String返回值,就会新建一个String对象,不对原对象进行修改
所以不会产生线程安全问题
建议10:
使用String,StringBuffer,StringBuilder的场景
1,String
在字符串不经常变化的场景中可以使用String类,例如:常量的声明,少量的变量运算
2,StringBuffer(线程同步)
在频繁进行字符串的运算(如拼接,替换,删除),并且运行在多线程的环境中,如XML解析,HTTP参数解析和封装等
3,StringBuilder(线程不同步)
在频繁进行字符串的运算(如拼接,替换,删除),并且运行在单线程的环境中,如SQL语句的拼装,JSON封装等