这个对getString的调用实际上是否会返回null?

时间:2015-05-21 18:18:37

标签: java android android-studio

我已将Android Studio更新到最新版本1.2。我最近还更新了其他组件,例如Android Gradle Extensions。

现在我收到了关于我之前注释为 NotNull 的方法的警告。警告是: Expression可能会计算为null但由声明为@NotNull的方法返回

以下是一个例子:

public class MyApplication extends Application {
    private static SharedPreferences sPrefs = null;

    /**
     * Corresponds to a string value.
     *
     * @see #setDeviceInfo(String, String, String)
     */
    private static final String PREF_DEVICE_INFO_DEVICE_ADDRESS = "deviceaddress";

    @Override
    public void onCreate() {
        super.onCreate();
        sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    }

    @NonNull
    public static String getDeviceAddress() {
        return sPrefs.getString(PREF_DEVICE_INFO_DEVICE_ADDRESS, "");
    }
}

我认为 getString 在这种情况下无法返回null,因为我已经设置了默认值""

即使我查看 getString 的实现(无论如何在API 22中),似乎这是android studio完全忽略了我的默认值不为null的事实。假设默认值 为空,这是错误的假设 API 22实施:

public String getString(String key, String defValue) {
    synchronized (this) {
        awaitLoadedLocked();
        String v = (String)mMap.get(key);
        return v != null ? v : defValue;
    }
}

在我继续前行之前,我仍然需要社区让我放心或指出我所缺少的东西。

1 个答案:

答案 0 :(得分:2)

你很安全

你确实很安全。

您正在指定默认值,并且该方法无法返回null值(除非您将其指定为defValue)。

为什么警告呢?

由于多种原因,IntelliJ / AndroidStudio无法确定逃生路线,并确定您的方法使用是安全的。方法合约并未正式拒绝defValue的空值。

此外,您将方法注释为@NotNull,但getString本身未注释(并且这些 运行时检查)。

最后,我想知道你是不是错误地在@NotNull和@NonNull之间切换注释,并因此切换了实现提供程序以进行注释检查。您在错误和描述中提到@NotNull,但代码使用@NonNull。他们的行为不一样。例如,IntelliJ的NonNull是一个仅静态检查。

请参阅Which @NotNull Java annotation should I use?以获取精彩摘要。

其他可能的问题

提出这些以防万一...

对于NPE密钥,getString可能null。{h3>

但是,如果指定null键,则可能会获得地图引发的NullPointerException。但这取决于所使用的地图实现以及该地图是否允许空键(我还没有查看),这对您来说不是问题(至少在代码中没有)你提供的代码片段。)

由于SharedPreferences没有在合同中指定任何有关实现的内容,因此应该只相信JDK的Map.get()文档说明:

  

NullPointerException - 如果指定的键为null且此映射不允许空键(可选)

可能ClassCastException

请注意,SharedPreferences.getString文档会警告您,如果存储的首选项不是String类型,则可能会出现ClassCastException(我认为在您的情况下不太可能,但是我' m提到它以防万一):

  

如果存在此名称不是String的首选项,则抛出ClassCastException。