42 votes

Syntaxe étrange pour l'instanciation d'une classe interne

Je n'imaginais pas rencontrer une syntaxe radicalement nouvelle en Java à ce stade, mais voilà, je viens de rencontrer quelque chose :

Le contexte exact et ce que le code ci-dessous devrait faire n'est pas pertinent - il est là juste pour donner une sorte de contexte.

J'essaie de créer synthétiquement un événement dans IT Mill Toolkit, j'ai donc écrit ce genre de ligne :

buttonClick(new Button.ClickEvent(button));

Mais, Eclipse me donne le message d'erreur suivant :

Aucune instance englobante du type Bouton n'est accessible. Il faut qualifier l'allocation avec une instance de type Button (par exemple, x.new A() où x est une instance de Button).

Lorsque je réécris la ligne ci-dessus comme suit, il ne se plaint plus :

buttonClick(button.new ClickEvent(button)); // button instanceof Button

Donc, ma question est : Que signifie exactement cette dernière syntaxe, et pourquoi le premier extrait ne fonctionne-t-il pas ? De quoi Java se plaint-il, et que fait-il dans la deuxième version ?

Informations générales : Les deux Button y Button.ClickEvent sont des classes publiques non abstraites.

71voto

Jon Skeet Points 692016

Les classes internes (comme Button.ClickEvent ) a besoin d'une référence à une instance de la classe externe ( Button ).

Cette syntaxe crée une nouvelle instance de Button.ClickEvent avec sa référence de classe externe définie à la valeur de button .

Voici un exemple - ne tenez pas compte du manque d'encapsulation, etc., il s'agit juste d'une démonstration :

class Outer
{
    String name;

    class Inner
    {
        void sayHi()
        {
            System.out.println("Outer name = " + name);
        }
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.name = "Fred";

        Outer.Inner inner = outer.new Inner();
        inner.sayHi();
    }
}

Voir section 8.1.3 de la spec pour en savoir plus sur les classes internes et les instances englobantes.

10voto

pgras Points 7202

Button.ClickEvent est une classe interne non statique. Par conséquent, une instance de cette classe ne peut exister que dans une instance de Button.

Dans votre deuxième exemple de code, vous avez une instance de Button et vous créez une instance de ClickEvent incluse dans cette instance de Button...

9voto

Daniel Earwicker Points 63298

Une classe interne non statique en Java contient une référence cachée qui pointe vers une instance de la classe externe dans laquelle elle est déclarée. Le message d'erreur que vous avez reçu à l'origine vous indique donc que vous ne pouvez pas créer une nouvelle instance de la classe interne sans spécifier également une instance de la classe externe à laquelle elle est rattachée.

La raison pour laquelle vous n'avez pas vu cette syntaxe auparavant est peut-être que les classes internes sont souvent allouées dans une méthode de la classe externe, où le compilateur s'en occupe automatiquement.

3voto

starblue Points 29696

Pour éviter de vous embrouiller et d'embrouiller les autres programmeurs avec cette fonctionnalité rarement utilisée, vous pouvez toujours rendre les classes internes statiques.

Si une référence à la classe externe est nécessaire, vous pouvez la passer explicitement dans le constructeur.

-1voto

diginoise Points 124

Votre code aurait compilé, si vous aviez tapé

buttonClick(new Button().ClickEvent(button));

au lieu de

buttonClick(new Button.ClickEvent(button));

car un constructeur est une méthode et lorsque vous appelez une méthode en Java, vous devez passer la liste des arguments, même si elle est vide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X