简体   繁体   中英

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. 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.

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. What would you do? An assertion sounds tempting to me.. Or would you just change the method to throw a RuntimException ? Or an 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.

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.

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 . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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