简体   繁体   English

返回null的方法中的java @Nonnull批注

[英]java @Nonnull annotation in a method that returns null

I have a method that gets something from a hashmap, a simplified example (that doesn't make much sense but is good enough for now) is: 我有一个从哈希图中获取内容的方法,一个简化的示例(虽然没有多大意义,但目前已经足够好了)是:

private Map<String,String> map = new HashMap<String,String>();

public String get(String key) {
    return map.get(key);
}

This method can return a null when an entry doesn't exist for a given key obviously. 当给定键的条目明显不存在时,此方法可以返回null。 The thing is, I want to annotate this method with @NonNull (because it is used in a gazillion places and I don't like Intellij spamming me with inspection warnings about producing a NPE and I don't want to turn off that inspection, and I also don't want to check whether the value returned is different than null everywhere I call this method. This is because I always use this method with a bunch of keys that are ALWAYS in the map. So due to the program logic this method is bound to return a @NonNull value. 事实是,我想用@NonNull注释此方法(因为它用在了数不胜数的地方,而且我不喜欢Intellij向我发送有关生产NPE的检查警告,因此我不想关闭该检查,而且我也不想在每次调用此方法时都检查返回的值是否不同于null,这是因为我总是将此方法与始终在映射中的一堆键一起使用。因此,由于程序逻辑方法必须返回一个@NonNull值。

I am tempted to just annotate it with a @NonNull , but who knows someone may call it with something other than the defined keys somewhere and actually cause a NullPointerException. 我很想只用@NonNull对其进行注释,但是谁知道有人可能会使用某处定义的键以外的名称来调用它,并实际上导致NullPointerException。 What would you do? 你会怎么做? An assertion sounds tempting to me.. Or would you just change the method to throw a RuntimException ? 一个断言对我来说很诱人。还是您只是更改该方法以引发RuntimException? Or an AssertionError? 还是AssertionError?

Thanks. 谢谢。

Edit: 编辑:

here's the actual implementation: 这是实际的实现:

/**
 * Typesafe heterogeneous container pattern - implementation
 */
public class HandlersMap {

    private final Map<Class<? extends TableHandler>, TableHandler> handlers;

    public HandlersMap() {
        handlers = new HashMap<Class<? extends TableHandler>, TableHandler>();
        putHandler(RolesTableHandler.class, new RolesTableHandler());
        putHandler(UsersTableHandler.class, new UsersTableHandler());
        putHandler(DevicesTableHandler.class, new DevicesTableHandler());
    }

    private <T extends TableHandler> void putHandler(@NonNull final Class<T> type, @NonNull final T instance) {
        handlers.put(type, type.cast(instance));
    }

    @NonNull
    public <T extends TableHandler> T getHandler(@NonNull final Class<T> type) {
        assert handlers.get(type) != null;
        return type.cast(handlers.get(type));
    }

    public Collection<TableHandler> values() {
        return handlers.values();
    }

    public int size() {
        return handlers.size();
    }

    public Map<Class<? extends TableHandler>, TableHandler> getMap() {
        return this.handlers;
    }

}

Annotating with @Nonnull without verifying if the given key exists is definitely the wrong thing to do. @Nonnull注释而不验证给定密钥是否存在绝对是错误的选择。

Since you seem to indicate that the given key is expected to exist, this means a missing key is an invalid argument, so checking for this case and throwing an IllegalArgumentException for missing elements would be the proper thing to do. 由于您似乎表明给定键应该存在,所以这意味着缺少键是无效的参数,因此检查这种情况并为缺少的元素抛出IllegalArgumentException是正确的做法。

Alternatively, depending on how your map is initialized, you might want to consider creating an enum for your key values, use an EnumMap instead of a HashMap , and have your get() method take this enum rather than a free-form String . 另外,根据地图的初始化方式,您可能需要考虑为键值创建一个枚举,使用EnumMap代替HashMap ,并让get()方法使用此枚举而不是自由格式的String That way, you would have some compile-time checking to ensure proper values are used as well. 这样,您将进行一些编译时检查,以确保也使用正确的值。

Even in that case though, you'd still need to check for existence, just in case the requested enum value is not yet added to the map. 即使在那种情况下,您仍然需要检查是否存在,以防万一请求的枚举值尚未添加到地图中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM