Pourquoi n'êtes-vous pas en mesure de déclarer une classe comme statique en Java?

459

Pourquoi n'êtes-vous pas en mesure de déclarer une classe comme statique en Java?

Mariselvam
la source
72
Contre-question: qu'attendriez-vous de l'effet si vous déclariez une classe de niveau supérieur static?
Joachim Sauer
3
Non, vous ne pouvez pas, sauf pour les classes internes statiques. Mais que voulez-vous réaliser avec ça?
manolowar
60
@Joachim Sauer: Eh bien, C # interprète les staticclasses car abstract final, par exemple, elles ne peuvent pas être instanciées et ne peuvent pas être étendues. Cela signifie qu'ils ne peuvent contenir que des membres statiques, ce qui est utile pour les classes qui ne contiennent que des méthodes d'assistance.
bcat
30
@bcat c'est vrai pour C #, mais une classe java peut être abstraite ou finale, pas les deux. Pour empêcher une classe d'être instanciée, on peut déclarer un constructeur privé.
Lorenzo Polidori
7
@JoachimSauer Simple, j'aimerais forcer tous les membres de la classe à être statiques (peut-être même à déclarer sur chaque méthode ou propriété).
hmartinezd

Réponses:

475

Seules les classes imbriquées peuvent être statiques. Ce faisant, vous pouvez utiliser la classe imbriquée sans avoir d'instance de la classe externe.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}

Sources :

Sur le même sujet:

Colin Hebert
la source
3
+1 malgré la première phrase qui n'est pas exacte. Comme l'indique le didacticiel, les classes imbriquées non statiques sont appelées classes internes. (JLS: "Une classe interne est une classe imbriquée qui n'est pas explicitement ou implicitement déclarée statique.")
user85421
74
Vous avez certainement raison; mais je ne vois pas comment cela répond à la question
Joeri Hendrickx
2
@Carlos Heuberger, vous avez raison, j'ai mis à jour le message. @Joeri Hendrickx, La question était, "pourquoi une classe ne peut pas être déclarée comme statique ..?", Ils le peuvent, et [lire mon post ici]. C'est une explication sur l'utilisation des classes statiques et pourquoi elles doivent être des classes imbriquées.
Colin Hebert
1
La solution donnée ici est très bien ... Mais je me demande quand même si ppl n'a pas expliqué logiquement que les classes statiques ne sont pas possibles dans java..sous l'explication du concept de POO serait la bonne réponse. Je l'
attends
9
C'est vrai, mais la question à laquelle vous pensez se résout généralement lorsque vous commencez à vous demander ce que serait une "classe statique". En java, un élément statique signifie que vous pouvez y accéder / l'invoquer sans une instance de la classe englobante; qu'est-ce que cela pourrait éventuellement signifier si vous appliquez le mot-clé à la classe elle-même? Quelles sont tes intentions? Qu'attendriez-vous? Maintenant que vous avez une idée de ce que cela pourrait être, je suis presque sûr que ce sera "pas vraiment logique" ou "farfelu" (cela aurait du sens, mais à la fin c'est juste un choix qui a été faite).
Colin Hebert
39

Les classes de niveau supérieur sont statiques par défaut. Les classes internes ne sont pas statiques par défaut. Vous pouvez modifier la valeur par défaut des classes internes en les marquant explicitement comme statiques. Les classes de niveau supérieur, en raison de leur niveau supérieur, ne peuvent pas avoir de sémantique non statique car il ne peut y avoir de classe parent à laquelle se référer. Par conséquent, il n'existe aucun moyen de modifier la valeur par défaut pour les classes de niveau supérieur.

nécromancien
la source
14
»Les classes de niveau supérieur sont statiques par défaut.« C'est la meilleure réponse. Ils sont statiques car vous n'avez besoin d'aucune instance de quoi que ce soit pour s'y référer. Ils peuvent être consultés de n'importe où. Ils sont en stockage statique (comme dans les classes de stockage C). - Comme d'autres l'ont noté (Iain Elder dans un commentaire à une autre réponse), les concepteurs de langage auraient pu permettre au staticmot - clé d'une classe de niveau supérieur de dénoter et d'appliquer qu'il ne peut contenir que des membres statiques et ne pas être instanciés; cela pourrait cependant avoir dérouté les gens comme cela statica une signification différente pour les classes imbriquées.
Lumi
35

Donc, je viens en retard à la fête, mais voici mes deux cents - ajoutant philosophiquement à la réponse de Colin Hebert.

À un niveau élevé, votre question porte sur la différence entre les objets et les types. Bien qu'il existe de nombreuses voitures (objets), il n'y a qu'une seule classe de voitures (type). Déclarer quelque chose comme statique signifie que vous travaillez dans l'espace "type". Il n'y a qu'un seul. Le mot-clé de classe de niveau supérieur définit déjà un type dans l'espace "type". Par conséquent, la «voiture de classe statique publique» est redondante.

Eric Jankowski
la source
1
Oui. En d'autres termes, les classes de niveau supérieur sont statiques par défaut, donc il n'y a pas besoin de mot-clé.
Warren Dew
1
Eh bien, j'ajouterais à ce que Warren Dew a dit: "Les classes de niveau supérieur sont statiques par défaut lors de l'accès aux membres statiques".
Dexter
1
Réponse sous-estimée. Un nouveau mot clé pour forcer chaque méthode d'une classe à être statique et le constructeur privé serait bien. Je ne dirais pas que c'est statique parce que c'est juste déroutant.
G_V
@G_V Bien que Java puisse créer un tel monstre, Java fait presque tout son possible pour rendre les choses stupides difficiles. La statique est une mauvaise idée en général, les classes statiques sont horribles (pire que les singletons qui sont eux-mêmes considérés comme un anti-modèle). Beaucoup de gens ne comprennent pas cela, donc lui donner un mot-clé serait une très mauvaise idée. Au lieu de cela, nous rendons les mauvaises choses difficiles et nous en restons là. Notez qu'il n'y a pas non plus de mot clé "Singleton". et aucun mot-clé Property. Tout cela cause du mauvais code (bien que les gens utilisent encore tellement les propriétés que Java pourrait aussi bien les supporter)
Bill K
29

La classe avec constructeur privé est statique.

Déclarez votre classe comme ceci:

public class eOAuth {

    private eOAuth(){}

    public final static int    ECodeOauthInvalidGrant = 0x1;
    public final static int    ECodeOauthUnknown       = 0x10;
    public static GetSomeStuff(){}

}

et vous pouvez utiliser sans initialisation:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...
Sergey Vakulenko
la source
3
Ce n'est pas statique, mais contient des propriétés statiques. Si vous écrivez public final int ECodeOauthUnknown = 0x10; ce n'est plus statique.
user1883212
9
Au cas où quelqu'un se demanderait ce qui se passe ici, cela correspond à la définition C # d'une "classe statique" - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Étant donné la définition Java de "classe statique", toutes les classes non internes sont statiques (voir les réponses des frères et sœurs).
Calum
1
Mis à part @ user1883212 a raison, je dirais même que cette réponse confond le lecteur que le constructeur privé est en quelque sorte important ici, alors qu'il n'a vraiment aucune importance.
tlwhitec
Dans le monde .NET, si une classe est marquée à la fois comme abstraite et finale (l'effet d'une static classdéclaration en C #), le compilateur ne permettra même pas au code de déclarer des variables de ce type, ni de l'utiliser comme paramètre de type générique. Un simple manque de constructeurs accessibles dans une classe qui pourraient autrement être soit instanciés soit hérités n'empêcherait pas la déclaration de variables de ce type, ni son utilisation comme paramètre de type générique.
supercat
Cette réponse est complètement incorrecte. Les constructeurs privés n'y sont pour rien. Le code n'est qu'un exemple d'une classe qui n'a que des attributs et des méthodes statiques. Cela n'a rien à voir avec les classes statiques.
Marquis de Lorne
13

Bien sûr qu'ils le peuvent, mais uniquement les classes imbriquées internes . Là, cela signifie que les instances de la classe imbriquée ne nécessitent pas d'instance englobante de la classe externe.

Mais pour les classes de haut niveau, les concepteurs de langage ne pouvaient penser à rien d'utile à faire avec le mot-clé, donc ce n'est pas autorisé.

Michael Borgwardt
la source
+1 malgré la première phrase qui n'est pas exacte. Comme l'indique le JLS: "Une classe interne est une classe imbriquée qui n'est pas explicitement ou implicitement déclarée statique." (Juste de la terminologie, je sais ...)
user85421
7
Bien qu'une classe de niveau supérieur ne puisse pas être déclarée static, il serait parfois logique de pouvoir le faire. Par exemple, une classe contenant uniquement des méthodes d'assistance statiques n'a aucun sens pour être instanciée, mais le langage Java ne vous empêche pas de le faire. Vous pouvez rendre la classe non instanciable (et pratiquement «statique») à d'autres classes en déclarant le constructeur par défaut private, ce qui interdit l'instanciation car aucun constructeur n'est visible.
Iain Samuel McLean Elder
12

Vous pouvez créer une classe utilitaire (qui ne peut pas avoir d'instances créées) en déclarant un type enum sans instances. c'est-à-dire que vous déclarez spécifiquement qu'il n'y a pas d'instances.

public enum MyUtilities {;
   public static void myMethod();
}
Peter Lawrey
la source
25
une énumération en tant que type est une attente spécifique: il s'agit d'un ensemble énuméré d'éléments. L'utiliser pour une "classe utilitaire", alors que vous pourriez autrement avoir simplement une classe avec un constructeur privé, est sémantiquement déroutant.
Visionary Software Solutions
5
@VisionarySoftwareSolutions Pour moi, cette spécificité dit qu'il n'y a pas d'instances de cette classe, plutôt que de rendre indirectement impossible la création d'instances d'une classe.
Peter Lawrey
8
public class Outer {
   public static class Inner {}
}

... il peut être déclaré statique - tant qu'il s'agit d'une classe membre.

Du JLS:

Les classes membres peuvent être statiques, auquel cas elles n'ont pas accès aux variables d'instance de la classe environnante; ou ils peuvent être des classes internes (§8.1.3).

et ici:

Le mot clé statique peut modifier la déclaration d'un type de membre C dans le corps d'une classe non interne T. Son effet est de déclarer que C n'est pas une classe interne. Tout comme une méthode statique de T n'a pas d'instance actuelle de T dans son corps, C n'a pas non plus d'instance actuelle de T, ni aucune instance lexicalement englobante.

Un mot clé statique n'aurait aucun sens pour une classe de niveau supérieur, simplement parce qu'une classe de niveau supérieur n'a pas de type englobant.

Andreas Dolk
la source
Si ce n'est pas intérieur, pourquoi l'appeler Inner? Nestedaurait été un choix moins déroutant.
Marquis de Lorne
5

Comme expliqué ci-dessus, une classe ne peut être statique que si elle est membre d'une autre classe.

Si vous cherchez à concevoir une classe "dont il ne peut pas y avoir plusieurs instances", vous voudrez peut-être examiner le modèle de conception "Singleton".

Débutant Singleton info ici .

Caveat:

Si vous songez à utiliser le motif singleton, résistez de toutes vos forces. C'est l'un des DesignPatterns les plus faciles à comprendre, probablement le plus populaire et certainement le plus abusé. (source: JavaRanch comme indiqué ci-dessus)

S.Jones
la source
4

En plus de la façon dont Java définit les classes internes statiques, il existe une autre définition des classes statiques selon le monde C # [1] . Une classe statique est une classe qui n'a que des méthodes (fonctions) statiques et qui est destinée à prendre en charge la programmation procédurale. De telles classes ne sont pas vraiment des classes dans la mesure où l'utilisateur de la classe ne s'intéresse qu'aux fonctions d'assistance et non à la création d'instances de la classe. Bien que les classes statiques soient prises en charge en C #, aucune prise en charge directe n'existe en Java. Vous pouvez cependant utiliser des énumérations pour imiter les classes statiques C # en Java afin qu'un utilisateur ne puisse jamais créer d'instances d'une classe donnée (même en utilisant la réflexion) [2] :

public enum StaticClass2 {
    // Empty enum trick to avoid instance creation
    ; // this semi-colon is important

    public static boolean isEmpty(final String s) {
        return s == null || s.isEmpty();
    }
}
simulacre
la source
3

Tout ce que nous codons en java va dans une classe. Chaque fois que nous exécutons une classe, la JVM instancie un objet. JVM peut créer un certain nombre d'objets, par définition statique signifie que vous avez le même jeu de copie pour tous les objets.

Ainsi, si Java aurait permis à la classe supérieure d'être statique chaque fois que vous exécutez un programme, il crée un objet et continue de remplacer le même emplacement mémoire.

Si vous remplacez simplement l'objet à chaque fois que vous l'exécutez, quel est l'intérêt de le créer?

C'est donc la raison pour laquelle Java s'est débarrassé de la statique pour la classe de niveau supérieur.

Il pourrait y avoir des raisons plus concrètes, mais cela avait beaucoup de sens logique pour moi.

user2626445
la source
3
Les classes internes sont associées aux classes externes et c'est la raison pour laquelle elles peuvent être statiques, car vous avez un objet différent sur lequel dépendre.
user2626445
1
Vous voulez dire "c'est la raison pour laquelle ils ne peuvent pas être statiques".
Marquis de Lorne
2

Les seules classes qui peuvent être statiques sont les classes internes. Le code suivant fonctionne très bien:

public class whatever {
    static class innerclass {
    }
}

Le point des classes internes statiques est qu'elles n'ont pas de référence à l'objet de classe externe.

user2645256
la source
1
«intérieur statique» est une contradiction dans les termes. «statique» et «intérieur» s'excluent mutuellement. Le mot que vous recherchez est «imbriqué» et non «intérieur».
Marquis de Lorne
1

Je pense que c'est aussi simple que de boire un verre de café!. Jetez un coup d'oeil à cela. Nous n'utilisons pas explicitement de mot clé statique lors de la définition de classe.

public class StaticClass {

    static private int me = 3;
    public static void printHelloWorld() {
       System.out.println("Hello World");
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

N'est-ce pas une définition de la classe statique? Nous utilisons simplement une fonction liée à une seule classe. Attention, dans ce cas, nous pouvons utiliser une autre classe dans celle imbriquée. Regarde ça:

class StaticClass1 {

    public static int yum = 4;

    static void  printHowAreYou() {
        System.out.println("How are you?");
    }
}

public class StaticClass {

    static int me = 3; 
    public static void printHelloWorld() {
       System.out.println("Hello World");
       StaticClass1.printHowAreYou();
       System.out.println(StaticClass1.yum);
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}
Erfankam
la source
Je pense que nous pouvons considérer ces classes comme une classe statique en faisant référence à la définition de classe statique et non pas simplement en utilisant un mot clé statique comme qualificatif.
Erfankam
Assurez-vous de créer un constructeur privé, sinon vous pourriez dire new StaticClass()et cela n'a pas vraiment de sens. Avec un constructeur privé, il n'en autoriserait pas les instances.
grinch
1

On peut regarder PlatformUIdans Eclipse pour une classe avec des méthodes statiques et un constructeur privé lui-même étant final.

public final class <class name>
{
   //static constants
   //static memebers
}
user175881
la source
0

si l'avantage d'utiliser une classe statique n'était pas d'instancier un objet et d'utiliser une méthode, il suffit de déclarer la classe comme publique et cette méthode comme statique.

eeadev
la source