如何让Immutables构建未指定List属性时抛出异常?
嘿,我来帮你搞定Immutables这个必填属性的问题!
你遇到的情况其实是Immutables的默认行为导致的:对于String这类非集合的引用类型,Immutables会自动添加非空校验(只要没加@Value.Default),所以不设置name时构建器会直接抛异常。但对于List这类集合类型,Immutables默认会在你没设置的时候生成一个空的不可变集合,而不是null,自然不会触发非空校验,也就不会报错。
下面根据你的具体需求,给你两种场景的解决方案:
场景1:强制必须显式指定stuff(哪怕是空列表也得手动设置)
如果你希望用户必须主动调用stuff相关的构建器方法(比如setStuff或者addStuff),不能依赖默认的空列表,可以选下面两种方法之一:
方法1:用@Value.Parameter标记stuff属性
把stuff标记为构造参数,这样ImmutableData的构建器会强制要求传入该参数,或者必须显式设置:
@Value.Immutable public abstract class Data { @Value.Parameter public abstract String name(); @Value.Parameter public abstract List<String> stuff(); }
现在构建实例时,要么用ImmutableData.of(name, stuff)直接传入,要么通过构建器显式调用.stuff(stuffList),否则编译或运行时都会报错。
方法2:通过@Value.Style禁用集合默认空值
给类加上@Value.Style(defaultImmutableCollections = false),这样Immutables就不会为集合类型生成默认的空集合了。此时如果不设置stuff,该属性会是null,触发和name一样的非空校验:
@Value.Immutable @Value.Style(defaultImmutableCollections = false) public abstract class Data { public abstract String name(); public abstract List<String> stuff(); }
现在不设置stuff的话,构建器会抛出NullPointerException,和name的行为完全一致。
场景2:强制stuff列表不能为空(必须至少有一个元素)
如果你不仅要求必须设置stuff,还要求列表里至少得有一个元素,那可以用@Value.Check加自定义校验逻辑:
@Value.Immutable public abstract class Data { public abstract String name(); public abstract List<String> stuff(); @Value.Check protected void check() { if (stuff().isEmpty()) { throw new IllegalArgumentException("stuff列表不能为空!"); } } }
这样不管是显式传了空列表,还是依赖默认的空列表,构建实例时都会触发这个校验,直接抛异常。要是结合场景1的方法,还能同时确保必须显式设置stuff且列表非空,完美满足你的需求。
内容的提问来源于stack exchange,提问作者TheClassic

