java字符串和枚举比较_JAVA基础(四)枚举(enum)和常量定义,工厂类使用对比...

baba5bf87bfdc43a04df901679d4531b.png

Java极客  |  作者  /  铿然一叶

这是Java极客的第 64 篇原创文章

相关阅读:

1. 枚举的用途

枚举可以用来定义常量,也可以当作工厂类使用,其相比常量定义,定义可以更集中;相比工厂类,表达is A(某一种类型)的语义更强。

2. 常量定义例子

2.1. 常量定义

class Constants{

// 常量定义方式一般通过相同前缀来分类,只要保证定义在同一个代码段就没问题,如果分散到多个代码段,找起来就挺费劲

public static final int SERV_TYPE_CAR = 1;

public static final int SERV_TYPE_TV = 2;

public static final int SERV_TYPE_MOBILE = 3;

// 通过枚举定义的方式更加集中,不可能会分散到多个代码段

public enum SERV_TYPE{

CAR, TV, MOBILE

}

}

复制代码

2.2. 使用方式

// 使用常量

public static void dox(int servType){

switch (servType) {

case Constants.SERV_TYPE_CAR:

// do something

break;

case Constants.SERV_TYPE_MOBILE:

// do something

break;

case Constants.SERV_TYPE_TV:

// do something

break;

default:

break;

}

}

// 使用枚举

public static void doy(Constants.SERV_TYPE servType){

switch (servType) {

case CAR:

// do something

break;

case TV:

// do something

break;

case MOBILE:

// do something

break;

default: // 使用枚举作为参数时,这个分支实际可以去掉,不需要考虑非法值的异常处理

break;

}

}

复制代码

可见,在使用上虽然区别不大,但枚举的好处是在定义时更加集中,好维护,同时还限定了入参的取值范围,使得更不容易发生参数输入错误的情况,不需要考虑输入不合法值时的异常处理。

3. 工厂类用法例子

枚举充当工厂类的用法在很多开源项目中都可以看到,其作用和工厂类一样。先看下例子的类结构:

fd8c98a3af42ee7adf6d4b51d7c29bba.png

类职责CacheType缓存类型,枚举类,通过它来获取对应的缓存类实例

BasicCache缓存类接口,对外暴露

ConcurrentMapCacheConcurrentMap实现的缓存,可以不对外暴露

LinkedHashMapCacheLinkedHashMap实现的缓存,可以不对外暴露

3.1. 代码

3.1.1. 缓存接口

public interface BasicCache{

V get(K key);

void put(K key, V value);

}

复制代码

3.1.2. 缓存实现类

// 注:没有public修饰,只在包内访问,屏蔽了可见性,对外只暴露BasicCache

final class LinkedHashMapCache implements BasicCache{

private final Map map;

public LinkedHashMapCache(int maximumSize, boolean accessOrder){

map = new BoundedLinkedHashMap<>(maximumSize, accessOrder);

}

@Override

public V get(K key){

synchronized (map) {

return map.get(key);

}

}

@Override

public void put(K key, V value){

synchronized (map) {

map.put(key, value);

}

}

static final class BoundedLinkedHashMap extends LinkedHashMap{

private static final long serialVersionUID = 1L;

private final int maximumSize;

public BoundedLinkedHashMap(int maximumSize, boolean accessOrder){

super(maximumSize, 0.75f, accessOrder);

this.maximumSize = maximumSize;

}

@Override protected boolean removeEldestEntry(Map.Entry eldest){

return size() > maximumSize;

}

}

}

final class ConcurrentMapCache implements BasicCache{

private final ConcurrentMap map;

public ConcurrentMapCache(ConcurrentMap map){

this.map = requireNonNull(map);

}

@Override

public V get(K key){

return map.get(key);

}

@Override

public void put(K key, V value){

map.put(key, value);

}

}

复制代码

3.1.3. 缓存类型

public enum CacheType{

ConcurrentHashMap {

@Override public BasicCache create(int maximumSize){

return new ConcurrentMapCache<>(new ConcurrentHashMap<>(maximumSize));

}

},

LinkedHashMap {

@Override public BasicCache create(int maximumSize){

return new LinkedHashMapCache<>(maximumSize, true);

}

};

public abstract BasicCache create(int maximumSize);

}

复制代码

3.1.4. 枚举类使用

// 使用枚举,可充当工厂类作用

BasicCache enumConcurrentHash = CacheType.ConcurrentHashMap.create(2);

BasicCache enumLinkedHash = CacheType.LinkedHashMap.create(2);

复制代码

可以看到,此时枚举类充当了工厂类的作用。

3.1.5. 对比直接实例化

如果ConcurrentMapCache和LinkedHashMapCache定义为public的,那么可以直接实例化,如下:

BasicCache concurrentMapCache = new ConcurrentMapCache<>(new ConcurrentHashMap<>(2));

BasicCache linkedHashMapCache = new LinkedHashMapCache<>(2, true);

复制代码

既然可以直接实例化,为什么还需要通过枚举来创建实例? 其主要目的和工厂类一样:屏蔽创建类实例的逻辑,外部直接使用接口就好。

3.1.6. 对比工厂类用法

// 工厂类

public final class CacheFactory{

public static BasicCache createConcurrentMapCache(int maximumSize){

return new ConcurrentMapCache<>(new ConcurrentHashMap<>(maximumSize));

}

public static BasicCache createLinkedHashMapCache(int maximumSize){

return new LinkedHashMapCache<>(maximumSize, true);

}

}

// 使用

BasicCache concurrentHashCache = CacheFactory.createConcurrentMapCache(2);

BasicCache linkedHashCache = CacheFactory.createLinkedHashMapCache(2);

复制代码

从以上例子来看,枚举和工厂类用法并没有多大区别,那为什么还要用枚举?此时枚举有什么价值? 回答这个问题,这还是要回到枚举的最基本用途上来-限制入参的取值范围,当需要限制时就一定要用枚举。

4. 总结

在作为常量定义使用时,如果每个取值有不同的分支逻辑,适合使用枚举定义;或者想限制取值的范围(尽管此时没有不同的分支逻辑),例如话费充值只能充值50和100,也适合使用枚举。

在作为创建工厂使用时,枚举和工厂类没啥差别,只是业务语义稍有不同,枚举的is A语义更强,可以先表达is A然后再创建具体类实例,而工厂类是一步到位创建具体类实例,此时还是要看是否需要用到通过枚举类来限制入参取值的目的,如果有这个目的,那么就使用枚举。

end.

112592004eac12b63835b41741df76e3.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值