Java编程规范

基本语句

  1. switch语句要有default分支,除非switch的条件变量是枚举类型
  2. if-else if类型的条件判断,最后应包含一个else分支
  3. 不能用浮点数作为循环变量

类的使用

覆写时要加上@override注解

原因:

  • 如果覆写时因为疏忽,导致子类方法的参数同父类不一致,编译时会报错,使问题在编译期就被发现。
  • 如果父类修改了方法的定义造成子类不再覆写父类方法,也能使问题在编译期尽早被发现。

未使用@override注解可能难以发现的错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Vehicle {
void run() {
System.out.println("Vehicle is running");
}
}

// 子类编写方法覆写父类方法
void rum() { // 方法名不正确
System.out.println("the Car is running");
}

void run(String name) { // 方法参数不正确
System.out.println(name + "drives the Car is running");
}

将对象存入HashSet,或作为key存入HashMap后,必须确保该对象的hashcode值不变

Java代码也可能发生内存泄漏

对于Hash集合(HashMap,HashSet等)而言,对象的hashcode至关重要,在hash集合内查找该对象完全依赖此值。如果一个对象存入Hash集合后,修改了参与计算hashcode有关的字段,那么修改后的hashcode的值就与最初存储进来的hashcode的值不同了,结果就是无法在集合内找到该对象,进而不能删除该对象,最终导致内存泄漏。

会发生内存泄漏的例子:

1
2
3
4
5
6
7
8
9
10
11
HashSet<Email> emailSet = new HashSet<>();
Email email = new Email("fly.com", "Jim");
emailSet.add(email);

email.setAddress("run.com"); // 导致hashcode发生变化
System.out.println(emailSet.contains(email)); // false
emailSet.remove(email); // 无法移除,发生内存泄漏
for (Email setEmail : emailSet) {
System.out.println(setEmail.getAddress());
System.out.println(setEmail.getName());
}

向下类型转换前用instance of 进行判断

目的:避免类型转换的安全性问题

例程:

1
2
3
4
5
6
if (animal instanceof Tiger) {
Tiger tiger = (Tiger) animal;
tiger.eat();
} else {
System.out.println("动物对象不能转换成老虎对象!");
}

使用集合的toArray()方法将集合转为数组

  • Object[]不可以转化为String[],需要进行每个元素的单独转换

这样太麻烦了,推荐更简便的方法(带参数的toArray方法)

1
String array3 = nameList3.toArray(new String[nameList3.size()]);

异常处理

异常条件下,保证释放已持有的锁

ReentrantLock

可重入的互斥锁,是一种递归无阻塞的同步机制。它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大、灵活的锁机制,可以减少死锁发生的概率

  • ReentrantLock类能够实现线程之间的同步互斥

  • ReentrantLock类具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务

1
2
3
4
5
6
7
8
9
10
11
12
private Lock lock = new ReentrantLock();

public void service(Object inputData) {
try {
Thread.sleep(100);
// 可能发生异常
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 异常状态也要释放锁
}
}

防止通过异常泄漏敏感信息

例如:文件不存在的异常可以泄漏文件系统的结构

解决方法:限制可访问的文件目录

1
2
3
4
if (!file.getPath().startsWith("c:\\homepath")) {
System.out.println("Invalid path.");
return;
}

在finally块中不要使finally块非正常结束

return, break, continue会使finally块非正常结束

后果:即使在try块或catch中抛出了异常,也会因为finally非正常结束而导致无法输出