我已将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;
}
}
在我继续前行之前,我仍然需要社区让我放心或指出我所缺少的东西。
答案 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。