[JAVA]如何定义好一个静态final域

背景描述:
最近在做一些JAVA方面的开发,时常需要定义一些常量,比如String类,Map类等等。

public static final String ADDRESS = "CSDN";

上述的定义很常见,但是对于如何定义一个常量的map,看了公司一些同事的做法如下:

public class Constants{
public static final Map<String,String> ADDRESS_MAP=new HashMap<>();
static{
    ADDRESS_MAP.put("1","CSDN");
    ADDRESS_MAP.put("2","CNBLOGS");
}
}

其实这种做法是及其不安全的,读者有兴趣的可以尝试下,在外部调用:

    public static void main(String[] args) {
        Constants.ADDRESS_MAP.put("1","333");
        System.out.println(Constants.ADDRESS_MAP);
    }

很不幸,我们的值被改变了。

今天抽了半个小时的时间,学习了下,特总结之。


首先先介绍2个概念,不可变对象和可变对象。从别人博客上找来了一个这个的定义。引用自CSDN博客,可点击访问

可变类和不可变类(Mutable and Immutable Objects)的初步定义:
可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。
不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。

Map、List都是可变对象,因此我们将其定义成final域并没有实际的效果。

下面提供2种做法:(参考自effective java第13条)
Method 1:

public static final Map<String,String> MAP = Collections.unmodifiableMap(new HashMap<String,String>()
            {
                private static final long serialVersionUID = 1338447211708407707L;
                {
                    put("1","2");
                }
            }
    );

这个时候再想改变其值,就是不可能的了,当然这个时候的final修饰符也没什么意义了。


Method 2:
使用clone方法。将可变对象定义成private类型的,并且提供一个静态方法去获得这个对象的clone返回值。
当Map的value是不可变对象的时候,这个方法的确是可以的,但是当value是一个可变对象的时候,我们发现,这种方法并不有效。如下例子(这里的对象就不给出啦,很简单的一个对象)。

private static final HashMap<String,Book> ADDRESS_MAP=new HashMap<>();
static{
    ADDRESS_MAP.put("1",new Book("sss","qqq"));
    ADDRESS_MAP.put("2",new Book("qqqxx","mmmxx"));
}

public static Map<String,Book> get_address_map(){
    return  (Map<String, Book>) ADDRESS_MAP.clone();
}

note:但是本人不建议使用方法2,因为clone如果是浅拷贝则依旧会产生问题,这个时候外界一样可以对其进行修改。

综上,我更推荐使用第一种方式!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值