dim*_*man 6 java android kotlin kotlin-android-extensions kotlin-null-safety
我有一个案例,其中Java to Kotlin转换器因为没有将方法参数标记为可空而使我失败.
示例:跟踪活动生命周期使用registerActivityLifecycleCallbacks:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {}
@Override
public void onActivityResumed(Activity activity) {}
// ... other overriden methods
});
Run Code Online (Sandbox Code Playgroud)
将此代码粘贴到Kotlin结果:
registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
// ... other overriden methods (all with non-nullable parameters)
})
Run Code Online (Sandbox Code Playgroud)
问题是savedInstanceState参数类型Bundle应该是Bundle?它的位置,因为它的值可以是null.
在这种情况下,当Activity创建没有实例状态时,我们将得到以下异常:
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter savedInstanceState
Run Code Online (Sandbox Code Playgroud)
注意,根本原因可能是onActivityCreated文档 没有提到Bundle可以为null,而onCreate文档可以解释为什么简单onCreate转换按预期工作:
// Java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我们如何知道哪些论据可以为可以阻止这些问题?该@Nullable注释并不在这里帮助.
如果注释没有帮助,我认为没有办法知道参数是否可为空。
关于您发布的代码,我想我知道发生了什么:
活动onCreate 标记为@Nullable:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
.
.
Run Code Online (Sandbox Code Playgroud)
虽然ActivityLifecycleCallbacks接口方法不是:(参见Application.java)
public interface ActivityLifecycleCallbacks {
void onActivityCreated(Activity activity, Bundle savedInstanceState);
void onActivityStarted(Activity activity);
void onActivityResumed(Activity activity);
void onActivityPaused(Activity activity);
void onActivityStopped(Activity activity);
void onActivitySaveInstanceState(Activity activity, Bundle outState);
void onActivityDestroyed(Activity activity);
}
Run Code Online (Sandbox Code Playgroud)
显然,Kotlin 翻译器正在处理注释,但使用Non-Null作为默认值,以我的愚见,这并不常见,因为将非注释参数视为Nullable更有意义。不过,我可以理解这个决定,以迫使开发人员关注翻译后的代码,并明确决定参数是否可为Null。
顺便说一下,请注意有几个@NonNull注释@Nullable(javax、android、jetbrains ...)如果 Kotlin 翻译器只识别其中的一些,我不会感到惊讶(但这只是猜测)
另外,关于您的代码,Java Lint 应该向您发出有关您的 overridden 的警告onCreate,表示您正在使用带注释的参数覆盖一个方法,但您尚未对它们进行注释。