2016-03-19 1 views
5
public class Solution { 
    private String name; 

    Solution(String name) { 
     this.name = name; 
    } 

    private String getName() { 
     return name; 
    } 

    private void sout() 
    { 
     new Solution("sout") 
     { 
      void printName() 
      { 
       System.out.println(getName()); 
      } 
     }.printName(); 
    } 

    public static void main(String[] args) { 
     new Solution("main").sout(); 
    } 
} 

La méthode d'une classe anonyme se comporte de manière inattendue. Comment faire une méthode sout pour imprimer "sout", maintenant il imprime "main"?La méthode d'une classe anonyme se comporte de façon inattendue

+1

Vous devez toujours fournir plus d'informations que "se comporter de façon inattendue". Étudiez le centre d'aide pour avoir une idée de ce que vous devriez mettre dans votre question. – GhostCat

+2

Je suppose que cela a à voir avec le fait que 'getName' est privé, et la classe anonyme ne peut pas accéder aux méthodes privées de sa superclasse, mais elle peut accéder aux méthodes privées de sa classe englobante ... et c'est compliqué par le fait même classe. – immibis

+0

Où avez-vous trouvé ce code? C'est vraiment bizarre. Vous faites aussi ceci: http://stackoverflow.com/questions/32959680/invoking-a-method-of-an-anonymous-class –

Répondre

3

Le problème est que String getName() est private.

Ce que cela signifie est qu'il est inaccessible aux méthodes de classes dérivées. Cependant, la classe dérivée anonyme n'est pas seulement dérivée, mais c'est aussi une classe interne. En tant que tel, la classe a accès aux membres privés de la classe externe. C'est pourquoi main est imprimé, pas sout. Tout ce que vous devez faire pour faire ce travail est de rendre la méthode non privée: l'accès par défaut, protected, ou public fonctionnerait bien.

Demo.

+0

merci. Pas this.getName()? – kurumkan

+0

@ArturArsalanov si vous utilisez 'this.getName()' tout en gardant 'getName()' private, le code ne compilera pas ([demo] (http://ideone.com/pvtUpE)). – dasblinkenlight

+0

mais s'il n'est pas privé peut fonctionner avec this.getName(); mais si seulement getName sans cela -still imprime "main" – kurumkan

1

Vous utiliseriez

System.out.println(super.getName());

Vous avez une classe interne anonyme Solution l'intérieur d'un Solution, donc getName() fait implicitement référence à l'instance externe parce que la méthode est privée. Vous pouvez également protéger getName au lieu de privé.

L'explication est un peu ornery. getName est visible à la classe anonyme en raison de la portée, mais comme elle est privée, la classe anonyme ne peut normalement pas se référer à getName sur elle-même, car c'est en fait une sous-classe.

Le cas vraiment étrange c'est quand vous avez une sous-classe imbriquée statique:

class Example { 
    private void sayHello() { 
     System.out.println(); 
    } 

    static class Subclass extends Example { 
     Subclass() { 
      // This is a compiler error 
      // because it tries to call sayHello() 
      // on an enclosing instance which doesn't 
      // exist (as if Subclass is an inner class). 
      sayHello(); 
     } 
    } 
} 

Je marchais à travers la spécification dans ma réponse à une question demandant au sujet de la static cas, ce qui explique aussi pourquoi "main" est imprimé ici: https://stackoverflow.com/a/28971617/2891664.

+0

cas intéressant – kurumkan