web-dev-qa-db-fra.com

Pourquoi les énumérations ne peuvent-elles pas être déclarées localement dans une méthode?

Aujourd'hui, je me suis retrouvé à coder quelque chose comme ça ...

public class LocalEnums {

    public LocalEnums() {
    }

    public void foo() {
        enum LocalEnum {
            A,B,C
        };

        // ....
        // class LocalClass { }

    }
}

et j'ai été un peu surpris quand le compilateur a signalé une erreur sur le enum local:

Le membre enum LocalEnum ne peut pas être local

Pourquoi enums ne peut-il pas être déclaré local comme classes?

J'ai trouvé cela très utile dans certaines situations. Dans le cas où je travaillais, le reste du code n'avait besoin de rien savoir sur le enum.

Existe-t-il un conflit structurel/de conception qui explique pourquoi cela n'est pas possible ou pourrait-il s'agir d'un futur fonctionnalité de Java?

54
bruno conde

Les énumérations sont des classes imbriquées statiques car elles définissent les variables membres statiques (les valeurs d'énumération!), et ceci est désactivé pour les classes internes: http://docs.Oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.

Mise à jour: Je regardais les JLS ( spécification du langage Java) pour plus de détails sur le restrictions des classes imbriquées statiques, et ne l'ont pas trouvé (bien qu'il soit probablement là, caché sous un sujet différent). Du point de vue de l'implémentation pure, il n'y a aucune raison que cela ne puisse pas être fait. Je soupçonne donc qu'il s'agissait d'un problème de philosophie linguistique: cela ne devrait pas être fait, donc ne sera pas pris en charge. Mais je n'étais pas là, donc c'est de la pure spéculation.

En tant que commentaire: si vos méthodes sont suffisamment grandes pour nécessiter leurs propres énumérations, alors c'est un signe fort que vous avez besoin d'une refactorisation.

37
kdgregory

Je me retrouve rarement à écrire des types dans une méthode, sauf s'il s'agit d'une classe interne anonyme. Vous pouvez cependant écrire des énumérations imbriquées:

public class NestedEnum
{
    private enum MyEnum
    {
        X, Y, Z
    }

    public void foo()
    {
    }
}

Je ne pense pas que je voudrais vraiment lire une méthode qui a déclaré un nouveau type en son sein - avez-vous une raison concrète de vouloir le déclarer à l'intérieur de la méthode plutôt que comme un type imbriqué ? Je peux voir l'argument "aucune autre méthode n'a besoin de savoir", mais je pense qu'un commentaire peut trier cela et laisser un code plus lisible.

15
Jon Skeet
  1. "Les types d'énumération imbriqués sont implicitement statiques." 8,9 énumérations

  2. Il est raisonnable de déduire que les types d'énumération imbriqués contiennent implicitement le modificateur d'accès statique.

  3. "Il s'agit d'une erreur de compilation si une déclaration de classe locale contient l'un des modificateurs d'accès suivants: public, protégé, privé ou statique." 14.3 14.3 Déclarations de classe locale
10
emory

C'est bizarre parce que la définition de classe interne Java dit que les constantes au moment de la compilation peuvent être déclarées statiques, et qu'un membre d'un Enum est clairement une constante au moment de la compilation, plus enum est une classe statique, soi-disant. ..

Documentation :

8.1.3 Classes internes et instances de clôture

(...) Les classes internes ne peuvent pas déclarer de membres statiques, sauf s'il s'agit de champs constants au moment de la compilation.

class Outer{
    class Inner extends HasStatic{
        static final int x = 3;         // ok - compile-time constant
        static int y = 4;           // compile-time error, an inner class
    }
    static class NestedButNotInner{
        static int z = 5;           // ok, not an inner class
    }
    interface NeverInner{}              // interfaces are never inner
}
3
no_ripcord

http://mindprod.com/jgloss/enum.html donne une bonne description de Java énumérations - comme mentionné précédemment, les énumérations sont définies comme statiques afin qu'elles puissent '' t être déclaré comme des locaux

2
Peter