Question

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

Le contexte exact et ce que le code ci-dessous doit faire ne sont pas pertinents - ils sont là pour donner un type de contexte.

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

buttonClick(new Button.ClickEvent(button));

Mais Eclipse me donne le message d'erreur suivant:

  

Aucune instance englobante de type Button n'est accessible. Doit qualifier l'allocation avec une instance englobante 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

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

Informations de base: Button et Button.ClickEvent sont des classes publiques non abstraites.

Était-ce utile?

La solution

Les classes internes (telles que Button.ClickEvent ) ont 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 sur la valeur du bouton .

Voici un exemple - ignorez le manque d'encapsulation, c’est uniquement à des fins de 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 la section 8.1.3 de la spécification pour plus d'informations sur les classes internes et les instances englobantes.

Autres conseils

Button.ClickEvent étant une classe interne non statique, 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 ...

Une classe interne non statique en Java contient une référence masquée qui pointe vers une instance de la classe externe dans laquelle elle est déclarée. Ainsi, le message d'erreur que vous avez reçu à l'origine vous indique 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 doit être attachée.

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

Pour éviter toute confusion avec vos collègues 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 transmettre explicitement dans le constructeur.

Vous pouvez réellement le faire , mais vous devez déclarer ClickEvent comme statique dans le bouton . , et alors vous ne devriez pas avoir de problème à utiliser votre code:

buttonClick(new Button.ClickEvent(button));

Fondamentalement, static fait que la classe ClickEvent appartient directement au bouton de la classe au lieu d'une instance spécifique (c'est-à-dire new Button () ) du Bouton .

Après l'exemple de @Jon Skeet:

// Button.java
class Button
{

    public static class ClickEvent
    {
        public ClickEvent(Button b)
        {
            System.out.println("Instance: " + this.toString());
        }
    }
}

// Test.java
public class Test
{
    public static void main(String[] args)
    {
        Button button = new Button();
        buttonClick(new Button.ClickEvent(button));
    }

    public static void buttonClick (Button.ClickEvent ce) {
    }
}

Votre code serait compilé si vous aviez tapé

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

au lieu de

buttonClick (new Button.ClickEvent (button));

en tant que constructeur est une méthode et lorsque vous appelez une méthode en Java, vous devez transmettre la liste des arguments, même lorsqu'elle est vide.

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