测试的时候发现项目中的LoadingCache没有刷新,但是明明调用了refresh方法了。后来发现LoadingCache是不支持缓存null值的,如果load回调方法返回null,则在get的时候会抛出异常。

通过几个例子开看这个问题:

public void test_loadNull() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
System.out.println("xx");
if (s.equals("hello"))
return "world";
else
return null;
}
}); try {
System.out.println(stringCache.get("hello")); // get触发load,load返回null则抛出异常:
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key other_key.
System.out.println(stringCache.get("other_key"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadNullWhenRefresh() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
int i = 0; @Override
public String load(String s) throws Exception {
if (i == 0) {
i++;
return "world";
}
return null;
}
}); try {
System.out.println(stringCache.get("hello"));
System.out.println(stringCache.get("hello")); // refresh的时候,如果load函数返回null,则refresh抛出异常:
// Exception thrown during refresh
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key hello.
stringCache.refresh("hello"); System.out.println(stringCache.get("hello"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadNullAfterInvalidate() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
int i = 0; @Override
public String load(String s) throws Exception {
if (i == 0) {
i++;
return "world";
}
return null;
}
}); try {
System.out.println(stringCache.get("hello"));
System.out.println(stringCache.get("hello")); // invalidate不会触发load
stringCache.invalidate("hello"); // invalidate后,再次get,触发load,抛出异常:
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key hello.
System.out.println(stringCache.get("hello"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadThrowException() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
if (s.equals("hello"))
return "world";
else
throw new IllegalArgumentException("only_hello");
}
}); try {
System.out.println(stringCache.get("hello")); // get触发load,load抛出异常,get也会抛出封装后的异常:
// com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalArgumentException: only_hello
System.out.println(stringCache.get("other_key"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}

所以如果你需要缓存“空”值,推荐的做法是使用Optional对象来封装结果:

public void test_loadUseOptional() {
LoadingCache<String, Optional<String>> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, Optional<String>>() {
@Override
public Optional<String> load(String s) throws Exception {
if (s.equals("hello"))
return Optional.of("world");
else
return Optional.absent();
}
}); try {
Optional<String> hello = stringCache.get("hello");
if(hello.isPresent()) {
System.out.println(hello.get());
} Optional<String> otherKey = stringCache.get("other_key");
if(otherKey.isPresent()){
System.out.println(otherKey.get());
}
} catch (ExecutionException e) {
e.printStackTrace();
}
}

如果你的场景中认为null是不存在的,那么你可以在load函数中抛出异常,这个异常会通过get抛出。

另外还有一个问题,如果是key==null呢?答案是直接抛出java.lang.NullPointerException。Guava对于null是很不待见的。

参考资料

本文独立博客地址:Guava LoadingCache不能缓存null值 | 木杉的博客

Guava LoadingCache不能缓存null值的更多相关文章

  1. Spring Cacheable 注解不缓存null值

    用Cacheable注解时,发现空值,也会被缓存下来.如果我们期望空值不被缓存,可以做如下设置: @Cacheable(key = "#id", unless="#res ...

  2. 使用google guava做内存缓存

    google guava中有cache包,此包提供内存缓存功能.内存缓存需要考虑很多问题,包括并发问题,缓存失效机制,内存不够用时缓存释放,缓存的命中率,缓存的移除等等. 当然这些东西guava都考虑 ...

  3. 本地缓存google.guava及分布式缓存redis 随笔

    近期项目用到了缓存,我选用的是主流的google.guava作本地缓存,redis作分布式 缓存,先说说我对本地缓存和分布式缓存的理解吧,可能不太成熟的地方,大家指出,一起 学习.本地缓存的特点是速度 ...

  4. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  5. 【Java必修课】四类方法删除List里面的所有null值

    1 简介 万恶的null已经折磨程序员许久了,也带来了许多难以发现却造成严重损失的NullPointerException.我们需要尽可能的避免它,有一种简单的办法就是在它进入下轮处理前,我们就把它扼 ...

  6. oracle 关于null值排序

    在oracle中根据字段来desc排序的话null值可能会在数据的最前面.然而有时候我们查看数据的时候并不希望能够在前面看到这些null值的排序数据. 因此我查了一下: 1.排序的时候运用nvl(). ...

  7. SQL中NULL值

    SQL的表达式,除了IS NULL和NOT NULL以外,只要出现NULL值结果都为FALSE 简单的例子: SELECT * FROM table WHERE name!='abc' 只要name值 ...

  8. 关于null值的排序

    关于空值null的排序问题   Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...

  9. SQL Server表分区的NULL值问题

    SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...

随机推荐

  1. 简单的jquery Ajax进行登录!

    本案例包括login.html.login.php.jquery-1.12.0.min.js三个文件,只需将这三个文件放到同一文件夹下,即可运行. login.html: <!DOCTYPE h ...

  2. No module named '_ctypes'

    3.7版本需要一个新的包libffi-devel,安装此包之后再次进行编译安装即可. #yum install libffi-devel -y #make install 若在安装前移除了/usr/b ...

  3. lena全身像

    数字图像处理中,Lena(Lenna)是一张被广泛使用的标准图片,特别在图像压缩的算法研究中 (为什么用这幅图,是因为这图的各个频段的能量都很丰富:即有低频(光滑的皮肤),也有高频(帽子上的羽毛),很 ...

  4. Python的 REPL 模式

    REPL Read Eval Print Loop读取,执行,输出,循环 在REPL环境中,你输入一句话,他就读取,执行,输出一个结果,所以也称为 交互式提示模式这是python代码最简单的方式,也揭 ...

  5. 吴裕雄 python 神经网络——TensorFlow variables_to_restore函数的使用样例

    import tensorflow as tf v = tf.Variable(0, dtype=tf.float32, name="v") ema = tf.train.Expo ...

  6. 显ipQQ

    链接:https://pan.baidu.com/s/1l1WN4b3jT8n4e66DH8d-cg 提取码:kjm4

  7. ElasticSearch应用

    1.什么是ElasticSearch Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本 身扩展性很好,可以扩展到上百台服务器,处理 ...

  8. python调用os模块锁定用户

    import timeimport osuser_info = { 'mac': {'pwd': '123', 'count': 0, 'locked': False}, 'tank': {'pwd' ...

  9. Python语言——列表生成式

    生成[1x1, 2x2, 3x3, ..., 10x10]列表: >>> L = [] >>> for x in range(1, 11):... >> ...

  10. Python笔记4

    JSON: JavaScript Object Notation,  JavaScript 对象标记 JSON 本质:是一种轻量级的数据交换格式 1. 轻量级 是 和 XML作比较 2. 数据交换格式 ...