java代码优化(五)——枚举和注解

枚举和注解

用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());
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值