Domanda

Il codice alla fine produce un errore di compilazione:

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

La domanda è perché? Perché javac pensa che io stia chiamando run () e non trova run (int bar)? Si chiamava correttamente foo (int bar). Perché devo usare NotApplicable.this.run (42) ;? È 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) {
    }
}
È stato utile?

Soluzione

La spiegazione del comportamento del tuo esempio di codice è che this è definito come la classe che sei attualmente " la maggior parte " all'interno di. In questo caso, sei "più" " all'interno della classe interna anonima che esegue la sottoclasse eseguibile e non esiste alcun metodo corrispondente a run (int) . Per ampliare la ricerca, specificare quale questo si desidera utilizzare dichiarando NotApplicable.this.run (42) .

Il jvm valuterà come segue:

this - > attualmente esegue l'istanza di eseguibile con il metodo run()

NotApplicable.this - > attualmente esegue l'istanza di NotApplicable con il metodo run(int)

Il compilatore cercherà l'albero di annidamento per il primo metodo che corrisponde al NAME del metodo. & # 8211; Grazie a DJClayworth per questo chiarimento

La classe interna anonima non è una sottoclasse della classe esterna. A causa di questa relazione, sia la classe interna che la classe esterna dovrebbero essere in grado di avere un metodo con esattamente la stessa firma e il blocco di codice più interno dovrebbe essere in grado di identificare quale metodo vuole eseguire.

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" );
    }
}

Altri suggerimenti

Per quanto ricordo le regole per la selezione di un metodo da eseguire tra classi nidificate sono approssimativamente le stesse delle regole per la selezione di un metodo in un albero ereditario. Ciò significa che ciò che stiamo ottenendo qui non è un sovraccarico, si nasconde. La differenza tra questi è fondamentale per comprendere i metodi ereditari.

Se Runnable è stato dichiarato come sottoclasse, il metodo run () nasconderebbe il metodo run (int) nel genitore. Qualsiasi chiamata da eseguire (...) proverebbe a eseguire quella su Runnable, ma fallirebbe se non potesse corrispondere alle firme. Poiché foo non è dichiarato nel figlio, viene chiamato quello sul genitore.

Lo stesso principio sta accadendo qui. Cerca riferimenti a " metodo che nasconde " e dovrebbe essere chiaro.

Questo perché esegui viene ri-dichiarato quando si inserisce l'ambito new Runnable () {} . Tutte le associazioni precedenti da eseguire diventano inaccessibili. È come se stessi facendo questo:

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();
  }
}

Il compilatore non cercherà qualcosa che corrisponda al tipo di x fino in cima allo stack dell'ambito, si fermerà appena troverà i primi riferimenti e vedrà che i tipi sono incompatibili .

NOTA: Non è come se non potesse farlo ... è solo che, per preservare il tuo buonsenso, è stato deciso che non dovrebbe .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top