枚举和注解
用enum代替int常量
java枚举的本质是int值,枚举类型的常量事实上是公有的静态final域修饰的,所以每个常量都是不可被修改的,只有在类加载时实例化一次,另外枚举类型是自动序列化的,防止反序列化攻击,可以保证常量一定是单例的。
枚举类型中可以增加成员变量、方法、构造器、接口、抽象类。
public enum Computer {
APPLE,
DELL,
LENOVO;
private String name = "电脑";
public void playGame(){
System.out.println("玩游戏");
}
public String getName() {
return name;
}
}
如何调用枚举类型中的方法?
public class UnitTest {
public static void main(String[] args) {
System.out.println(Computer.APPLE.getName());//Computer.APPLE就是一个实例化对象
Computer.APPLE.playGame();
for (Computer c : Computer.values()) {//枚举类型提供values()方法来遍历每个常量
System.out.println(c.name());
}
}
}
用实例域代替序数
每一个枚举类型常量对应一个int值,通过ordinal()方法获得这个关联的int值。
public enum Ensemble {
ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN;
public int numberOfMusicians(){
return ordinal()+1;
}
}
使用有参构造将关联的int值存放到实例域中。
public enum Ensemble {
ONE(1),TWO(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7),EIGHT(8),NINE(9),TEN(10);
private int numberofmusicians;
Ensemble(int i) {
this.numberofmusicians = i;
}
public int numberOfMusicians(){
return numberofmusicians;
}
}
注意:一般情况下,我们应尽量避免使用ordinal()方法,除非我们是在编写一个数据结构的代码。
用EnumSet代替位域
位域:使用或运算将几个常量合并到一个集合中。
public void display(int i){.....}
display(1 | 2);
不推荐使用位域,请使用EnumSet代替之。
public class IntEnum {
public enum style{STYLE_0,STYLE_2,STYLE_4,STYLE_8}
public void display(Set<style> set){
System.out.println(set);
}
}
IntEnum intEnum = new IntEnum();
intEnum.display(EnumSet.of(style.STYLE_0,style.STYLE_2));
坚持使用Override注解
使用Override注解表示该方法是从继承父类而来,看下面这个例子是否有问题?
public class Bigram {
private char first;
private char second;
public Bigram(char first,char second){
this.first = first;
this.second = second;
}
public boolean equals(Bigram b){
return this.first == b.first && this.second == b.second;
}
public int hashCode(){
System.out.println(30 * first + second);
return 30 * first + second;
}
public static void main(String[] args) {
HashSet<Bigram> set = new HashSet<Bigram>();
for (int i = 0; i < 10; i++) {
for (char j = 'a'; j <= 'z'; j++) {
set.add(new Bigram(j, j));
}
}
System.out.println(set.size());
}
}
我们的预期是输出26,但是运行结果却是260!可能有人会问set不是不会增加重复对象嘛?那是因为equals(Bigram)并没有重写equals(Object)方法,因为参数类型不同其实是overload了equals方法,这就导致判断是否相等走的是Object的equals方法,每次向set中添加元素都是new一个新的对象,所以一共有260个元素而不是26个。
那么就需要加上Override注解告诉编辑器Bigram的equals重写了Object的equals方法
加上@Override还不行,参数类型需要和Object保持一致,并在内部判断类型是否一致:
public class Bigram {
private char first;
private char second;
public Bigram(char first,char second){
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object b){
if(!(b instanceof Bigram)){
return false;
}
Bigram ram = (Bigram)b;
return this.first == ram.first && this.second == ram.second;
}
@Override
public int hashCode(){
return 30 * first + second;
}
public static void main(String[] args) {
HashSet<Bigram> set = new HashSet<Bigram>();
for (int i = 0; i < 10; i++) {
for (char j = 'a'; j <= 'z'; j++) {
set.add(new Bigram(j, j));
}
}
System.out.println(set.size());
}
}