简体   繁体   English

Java到Kotlin转换器和可空的方法参数

[英]Java to Kotlin converter and nullable method arguments

I had a case in which Java to Kotlin converter failed me miserably by not marking method arguments as nullable. 我有一个案例,其中Java to Kotlin转换器失败了我没有将方法参数标记为可空。

Example: tracking activity lifecycle using registerActivityLifecycleCallbacks : 示例:使用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
});

Pasting this code to Kotlin results: 将此代码粘贴到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)
})

The issue is that savedInstanceState argument type is Bundle where it should be Bundle? 问题是savedInstanceState参数类型是Bundle ,它应该是Bundle? because it's value can be null . 因为它的值可以为null

In this case we will get the following exception when an Activity is created without instance state: 在这种情况下,当创建一个没有实例状态的Activity时,我们将得到以下异常:

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter savedInstanceState

Note, the root cause to this can be that onActivityCreated documentation doesn't mention that Bundle can be null whereas onCreate documentation does which can explain why simple onCreate conversion works as expected: 注意,根本原因可能是onActivityCreated文档 没有提到Bundle可以为nullonCreate文档可以解释为什么简单的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)
}

My question is how do we know which arguments should be nullable to prevent those kind of issues? 我的问题是我们如何知道哪些论据可以为可以阻止这些问题? The @Nullable annotation doesn't help here. @Nullable注释在这里没有帮助。

If annotations don't help, I don't think there's a way to know if an argument is nullable or not. 如果注释没有帮助,我认为没有办法知道参数是否可以为空。

Regarding your posted code, I think I know what's going on: 关于你发布的代码,我想我知道发生了什么:

Activity onCreate IS marked as @Nullable : 活动onCreate IS标记为@Nullable

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    final AppCompatDelegate delegate = getDelegate();
    delegate.installViewFactory();
    delegate.onCreate(savedInstanceState);
    .
    .

While ActivityLifecycleCallbacks interface methods are not : (See Application.java ) 虽然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);
}

So apparently Kotlin translator is processing annotations, but using Non-Null as default, which in my humble opinion is not the usual, as it makes more sense for non-annotated parameters to be considered Nullable . 显然Kotlin翻译器正在处理注释,但是使用Non-Null作为默认值,这在我看来并不常见,因为非注释参数被认为是Nullable更有意义。 However I can understand that decision in order to force developers to pay attention to translated code and decide explicitly if a parameter is Nullable or not. 但是我可以理解这个决定,以迫使开发人员关注已翻译的代码并明确决定参数是否为Nullable

By the way, mind that there are several @NonNull and @Nullable annotations (javax, android, jetbrains ...) I wouldn't be surprised if Kotlin translator only recognises some of them (but it's just a guess) 顺便说一下,请注意有几个@NonNull@Nullable注释(javax,android,jetbrains ......)如果Kotlin翻译只识别其中一些(但这只是猜测),我不会感到惊讶

Also regarding your code, Java Lint should have given you a warning about your overridden onCreate , saying that you are overriding a method with annotated parameters and you have not annotated them. 另外关于你的代码,Java Lint应该给你一个关于你重写的onCreate的警告,说你要覆盖一个带有注释参数的方法而你没有注释它们。

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

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