Question

Le code à la fin produit une erreur de compilation:

NotApplicable.java:7: run() in  cannot be applied to (int)
                run(42);
                ^
1 error

La question est pourquoi? Pourquoi javac pense-t-il que j'appelle run () et ne trouve-t-il pas run (int bar)? Il a correctement appelé foo (int bar). Pourquoi dois-je utiliser NotApplicable.this.run (42) ;? Est-ce un bug?

public class NotApplicable {

    public NotApplicable() {
        new Runnable() {
            public void run() {
                foo(42);
                run(42);
                // uncomment below to fix
                //NotApplicable.this.run(42);
            }
        };
    }

    private void run(int bar) {
    }

    public void foo(int bar) {
    }
}
Était-ce utile?

La solution

L'explication du comportement de votre exemple de code est que this est défini comme étant la classe dans laquelle vous êtes actuellement "most". à l'intérieur de. Dans ce cas, vous êtes "le plus". à l'intérieur de la classe interne anonyme qui sous-classe runnable et aucune méthode ne correspond à run (int) . Pour élargir votre recherche, spécifiez le ce que vous souhaitez utiliser en indiquant NotApplicable.this.run (42) .

Le JVM évaluera comme suit:

this - > instance en cours d'exécution de Runnable avec la méthode run ()

NotApplicable.this - > instance en cours d'exécution de NotApplicable avec la méthode run (int)

Le compilateur recherchera dans l'arbre de nidification la première méthode qui correspond au nom de la méthode. & # 8211; Merci à DJClayworth pour cette clarification

La classe interne anonyme n'est pas une sous-classe de la classe externe. En raison de cette relation, la classe interne et la classe externe doivent pouvoir utiliser une méthode avec exactement la même signature et le bloc de code le plus interne doit pouvoir identifier la méthode à exécuter.

public class Outer{

    public Outer() {
        new Runnable() {
            public void printit() {
                System.out.println( "Anonymous Inner" );
            }
            public void run() {
                printit(); // prints "Anonymous Inner"
                this.printit(); //prints "Anonymous Inner"

                // would not be possible to execute next line without this behavior
                Outer.this.printit(); //prints "Outer" 
            }
        };
    }

    public void printit() {
        System.out.println( "Outer" );
    }
}

Autres conseils

Pour autant que je m'en souvienne, les règles de sélection d'une méthode à exécuter entre des classes imbriquées sont approximativement les mêmes que les règles de sélection d'une méthode dans un arbre d'héritage. Cela signifie que ce que nous obtenons ici n'est pas une surcharge, mais une dissimulation. La différence entre eux est cruciale pour comprendre les méthodes en héritage.

Si votre Runnable était déclaré en tant que sous-classe, la méthode run () masquerait la méthode run (int) dans le parent. Tout appel à exécuter (...) essaierait d'exécuter celui-ci sur Runnable, mais échouerait s'il ne correspondait pas aux signatures. Puisque foo n’est pas déclaré dans l’enfant, celui du parent est appelé.

Le même principe se passe ici. Recherchez des références à " méthode masquant " et il devrait être clair.

Cela est dû au fait que run est re-déclaré lorsque vous entrez la portée new Runnable () {} . Toutes les liaisons précédentes à exécuter deviennent inaccessibles. C'est comme si vous faisiez ceci:

import java.util.*;

public class tmp
{
  private int x = 20;
  public static class Inner
  {
      private List x = new ArrayList();
      public void func()
      {
          System.out.println(x + 10);
      }
  }

  public static void main(String[] args)
  {
    (new Inner()).func();
  }
}

Le compilateur ne cherchera pas quelque chose qui correspond au type de x tout le long de la pile de la portée, il s'arrêtera juste lorsqu'il trouvera les premières références et verra que les types sont incompatibles. .

REMARQUE: ce n'est pas comme si elle ne pouvait pas faire ceci ... c'est simplement que, pour préserver votre santé mentale, il a été décidé que cela ne devrait pas .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top