5

J'ai eu un cas dans lequel le convertisseur de Java en Kotlin m'a échoué lamentablement en ne marquant pas les arguments de méthode comme nullable.Convertisseur Java en Kotlin et arguments de méthode nullable

Exemple: cycle de vie de l'activité de suivi à l'aide 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 
}); 

coller ce code aux résultats 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) 
}) 

Le problème est que le type d'argument savedInstanceState est Bundle où il devrait être Bundle? parce que sa valeur peut être null.

Dans ce cas, nous obtiendrons l'exception suivante lorsqu'un Activity est créé sans état d'instance:

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

Remarque, la cause de la racine à cela peut être que onActivityCreated documentationne mentionne pas que Bundle peut être nul alors que onCreate documentation ne qui peut expliquer pourquoi fonctionne comme prévu la conversion simple 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) 
} 

Ma question est Comment savons-nous quels arguments devraient être valables pour prévenir ce genre de problèmes? L'annotation @Nullable n'aide pas ici.

Répondre

3

Si les annotations n'aident pas, je ne pense pas qu'il existe un moyen de savoir si un argument est nullable ou non.

En ce qui concerne votre code affiché, je pense que je sais ce qui se passe:

Activité onCreateEST marqué comme @Nullable:

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

Alors que ActivityLifecycleCallbacks méthodes d'interface ne sont pas: (Voir 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); 
} 

Donc apparemment traducteur Kotlin est le traitement des annotations, mais en utilisant Non-Null par défaut, ce qui à mon humble avis n'est pas l'habitude, car il est plus logique pour les paramètres non annotés à considérer Nullable. Cependant, je peux comprendre cette décision afin de forcer les développeurs à prêter attention au code traduit et de décider explicitement si un paramètre est Nullable ou non.

Par ailleurs, l'esprit qu'il ya plusieurs @NonNull et @Nullable annotations (javax, androïde, JetBrains ...) Je ne serais pas surpris si traducteur Kotlin ne reconnaît que certains d'entre eux (mais il est juste une supposition)

En ce qui concerne votre code, Java Lint aurait dû vous donner un avertissement à propos de votre onCreate, en disant que vous surchargez une méthode avec des paramètres annotés et que vous ne les avez pas annotés.

+1

Je suppose que cela supporte votre argument: https://kotlinlang.org/docs/reference/java-interop.html # nullability-annotations. Je vais essayer de convertir avec une annotation encore une fois (ne fonctionnait pas pour moi avant) –

+1

Oui, Kotlin suppose que le code Java n'est pas nul par défaut à moins qu'il ne comporte une annotation. Il utilise '!' Pour le code Java, comme 'String! 'Pour vous dire que le code provient de Java. – Joshua