Pourquoi les méthodes statiques ne peuvent-elles pas être abstraites en Java?


593

La question est en Java, pourquoi ne puis-je pas définir une méthode statique abstraite? par exemple

abstract class foo {
    abstract void bar( ); // <-- this is ok
    abstract static void bar2(); //<-- this isn't why?
}

9
Quelques raisons: la méthode statique doit avoir un corps même si elle fait partie d'une classe abstraite car il n'est pas nécessaire de créer une instance d'une classe pour accéder à sa méthode statique. Une autre façon de penser est que si pendant un moment nous supposons que c'est autorisé, le problème est que les appels de méthode statiques ne fournissent aucune information de type d'exécution (RTTI), rappelez-vous qu'aucune création d'instance n'est requise, donc ils ne peuvent pas être redirigés à leurs implémentations spécifiques remplacées et autorisant ainsi l'abstrait statique n'a aucun sens. En d'autres termes, il ne pouvait fournir aucun avantage de polymorphisme donc non autorisé.
sactiw

6
Si vous avez quelque chose à répondre à la question, postez-le comme une réponse , pas un commentaire
Solomon Ucko

Réponses:


568

Parce que "abstrait" signifie: "n'implémente aucune fonctionnalité" et "statique" signifie: "il y a une fonctionnalité même si vous n'avez pas d'instance d'objet". Et c'est une contradiction logique.


353
Une réponse plus concise serait «un mauvais langage». Statique devrait signifier «appartient à la classe» parce que c'est ainsi qu'il est utilisé intuitivement comme le démontre cette question. Voir "classmethod" en Python.
Alexander Ljungberg

12
@Tomalak Je m'excuse, je n'étais pas clair. Bien sûr, une méthode statique «appartient à la classe». Pourtant, ce n'est que dans le sens où il vit dans le même espace de noms. Une méthode statique n'est pas une méthode de l'objet classe lui-même: elle ne fonctionne pas avec «this» comme objet classe, et elle ne participe pas correctement à la chaîne d'héritage. Si c'était vraiment une méthode de classe, cela abstract staticaurait un sens parfait. Ce serait une méthode de l'objet de classe lui-même que les objets de sous-classe doivent implémenter. Bien sûr, la façon dont les choses se présentent, votre réponse est correcte malgré mon emprise sur la langue.
Alexander Ljungberg

695
Ce n'est pas une contradiction logique, c'est une lacune linguistique, plusieurs autres langues supportent cette notion. "abstrait" signifie "implémenté dans les sous-classes", "statique" signifie "exécuté sur la classe plutôt que sur les instances de classe" Il n'y a pas de contradiction logique.
Eric Grange

10
@Eric: Et pourtant , ce que vous dites ne s'applique pas abstract static: Une fonction X qui est "implémentée dans la sous-classe" ne peut pas en même temps "être exécutée sur la classe" - uniquement sur la sous - classe . Là où il n'est alors plus abstrait.
Tomalak

72
@Tomakak: Votre logique est circulaire. staticne signifie pas "pas vide" - c'est juste une conséquence de Java qui ne permet pas aux méthodes statiques d'être abstraites. Cela signifie "appelable sur la classe". (Cela devrait signifier "appelable uniquement sur la classe" mais c'est un autre problème.) Si les abstract staticméthodes prises en charge par Java , je m'attendrais à ce que cela signifie que la méthode 1) doit être implémentée par des sous-classes, et 2) est une méthode de classe de la sous-classe. Certaines méthodes n'ont tout simplement pas de sens en tant que méthodes d'instance. Malheureusement, Java ne vous permet pas de spécifier cela lors de la création d'une classe de base abstraite (ou d'une interface).
Michael Carman

326

Mauvaise conception de la langue. Il serait beaucoup plus efficace d'appeler directement une méthode abstraite statique que de créer une instance uniquement pour utiliser cette méthode abstraite. Cela est particulièrement vrai lorsque vous utilisez une classe abstraite comme solution de contournement pour l'incapacité d'énumération à s'étendre, ce qui est un autre exemple de conception médiocre. J'espère qu'ils résoudront ces limitations dans une prochaine version.


25
Java est plein de limitations étranges. Les fermetures n'accédant qu'aux variables finales en sont une autre. Et la liste restante est presque sans fin. C'est le travail d'un programmeur Java de les connaître ainsi que leurs solutions de contournement. Pour nous amuser, nous devons utiliser quelque chose de mieux que Java dans notre temps libre. Mais je ne m'inquiéterais pas. C'est la graine pour réaliser des progrès.
ceving

22
Je crois que ce que vous appelez «conception de langage médiocre» est en réalité davantage une «conception de langage de protection», dont le but est de limiter les violations du principe OO commises par les programmeurs en raison de fonctionnalités linguistiques inutiles.
ethanfar

22
Le concept de "statique abstraite" est-il une violation des principes OO?
Trevor

7
@threed, Pas du tout, mais bien sûr, il y a des gens qui disent que le simple concept de staticlui-même est déjà une violation ....
Pacerier

4
Le besoin de statique est une démonstration claire que les «principes OO» ne sont pas aussi globaux que ce que l'on prétend habituellement.
Ben

147

Vous ne pouvez pas remplacer une méthode statique, donc la rendre abstraite n'aurait aucun sens. De plus, une méthode statique dans une classe abstraite appartiendrait à cette classe, et non à la classe prioritaire, elle ne pourrait donc pas être utilisée de toute façon.


18
Oui, c'est vraiment dommage car les méthodes statiques ne peuvent pas être remplacées en Java.
Michel

12
@Michel: quel serait l'intérêt? Si vous souhaitez un comportement basé sur une instance, utilisez des méthodes d'instance.
Ran Biron

8
Cette réponse est incorrecte. Les méthodes statiques dans les classes abstraites fonctionnent bien et sont couramment utilisées. C'est juste qu'une méthode statique de la classe elle-même peut ne pas être abstraite. @Michel, cela n'a pas de sens de remplacer une méthode statique. Sans instance, comment le runtime saurait-il quelle méthode appeler?
erickson

63
@erickson - Même sans instance, la hiérarchie des classes est intacte - l'héritage sur les méthodes statiques peut fonctionner comme l'héritage des méthodes d'instance. Smalltalk le fait, et c'est très utile.
Jared

8
@matiasg ce n'est rien de nouveau du tout. Les classes abstraites ont toujours été autorisées à avoir des méthodes statiques et non abstraites .
Matt Ball

70

L' abstractannotation à une méthode indique que la méthode DOIT être remplacée dans une sous-classe.

En Java, un staticmembre (méthode ou champ) ne peut pas être remplacé par des sous-classes (ce n'est pas nécessairement vrai dans d'autres langages orientés objet, voir SmallTalk.) Un staticmembre peut être masqué , mais cela est fondamentalement différent du remplacement .

Étant donné que les membres statiques ne peuvent pas être remplacés dans une sous-classe, l' abstractannotation ne peut pas leur être appliquée.

En passant, d'autres langages prennent en charge l'héritage statique, tout comme l'héritage d'instance. Du point de vue de la syntaxe, ces langages nécessitent généralement que le nom de la classe soit inclus dans l'instruction. Par exemple, en Java, en supposant que vous écrivez du code dans ClassA, ce sont des instructions équivalentes (si methodA () est une méthode statique et qu'il n'y a pas de méthode d'instance avec la même signature):

ClassA.methodA();

et

methodA();

Dans SmallTalk, le nom de classe n'est pas facultatif, donc la syntaxe est (notez que SmallTalk n'utilise pas le. Pour séparer le "sujet" et le "verbe", mais l'utilise à la place comme terminateur de statemend):

ClassA methodA.

Étant donné que le nom de classe est toujours requis, la "version" correcte de la méthode peut toujours être déterminée en parcourant la hiérarchie des classes. Pour ce que ça vaut, je manque parfois l' statichéritage, et j'ai été mordu par le manque d'héritage statique en Java lorsque j'ai commencé avec. De plus, SmallTalk est de type canard (et ne prend donc pas en charge le programme par contrat.) Ainsi, il n'a pas de abstractmodificateur pour les membres de la classe.


1
"Un membre statique ne peut pas être remplacé par des sous-classes" est incorrect. C'est possible, au moins en Java6. Pas sûr depuis quand c'est le cas.
Steven De Groote

15
@Steven De Groote Un membre statique ne peut en effet pas être remplacé par des sous-classes. Si une sous-classe a une méthode statique avec la même signature qu'une méthode statique dans la superclasse, elle ne la remplace pas, elle la masque. http://docs.oracle.com/javase/tutorial/java/IandI/override.html La différence est que le polymorphisme ne fonctionne que pour les méthodes surchargées, mais pas pour les méthodes masquées.
John29

2
@ John29 Merci pour la clarification, mais à part la différence de dénomination, son utilisation semble similaire.
Steven De Groote

2
@Steven De Groote Oui, son utilisation est similaire, mais le comportement est différent. C'est la raison pour laquelle il n'y a pas de méthodes abstraites statiques - quel est l'intérêt des méthodes abstraites statiques si elles ne prennent pas en charge le polymorphisme?
John29

3
@Steven De Groote: La différence devient apparente lorsque vous avez un appel à cette méthode dans la superclasse elle-même. Supposons que Super.foo appelle Super.bar. Si une sous-classe implémente Subclass.bar, puis appelle foo, alors foo appellera toujours Super.bar, pas Subclass.bar. Par conséquent, ce que vous avez vraiment, ce sont deux méthodes totalement différentes et sans rapport, toutes deux appelées "bar". Ce n'est pas primordial dans un sens utile.
Doradus

14

J'ai aussi posé la même question, voici pourquoi

Puisque la classe Abstract dit, elle ne donnera pas d'implémentation et permettra à la sous-classe de la donner

donc Subclass doit remplacer les méthodes de Superclass,

RÈGLE NO 1 - Une méthode statique ne peut pas être remplacée

Étant donné que les membres et les méthodes statiques sont des éléments de temps de compilation, c'est pourquoi la surcharge (polymorphisme de compilation) des méthodes statiques est autorisée plutôt que la substitution (polymorphisme d'exécution)

Donc, ils ne peuvent pas être abstraits.

Il n'y a rien de tel que l' abstrait statique <--- Non autorisé dans Java Universe


5
-1, Il n'est pas vrai que "Java ne permet pas de remplacer la méthode statique car les membres statiques et les méthodes sont des éléments de temps de compilation". La vérification de type statique est certainement possible avec abstract staticvoir stackoverflow.com/questions/370962/… . La vraie raison pour laquelle Java n'autorise pas le remplacement des méthodes statiques est que Java n'autorise pas le remplacement des méthodes statiques.
Pacerier

La surcharge n'a rien à voir avec le polymorphisme. La surcharge et le remplacement n'ont rien en commun, sauf le préfixe "over", de la même manière que Java et JavaScript contiennent tous deux "Java". Le nom d'une méthode n'est pas ce qui l'identifie, c'est sa signature qui le fait. foo(String)n'est donc pas la même chose que foo(Integer)- c'est tout.
Captain Man

@CaptainMan Overloading est littéralement appelé "polymorphisme paramétrique" car, selon le type du paramètre, une méthode différente est appelée, qui est le polymorphisme.
Davor

12

C'est une conception de langage terrible et vraiment aucune raison pour laquelle cela ne peut pas être possible.

En fait, voici une implémentation sur la façon dont cela PEUT être fait dans JAVA :

public class Main {

        public static void main(String[] args) {
                // This is done once in your application, usually at startup
                Request.setRequest(new RequestImplementationOther());

                Request.doSomething();
        }

        public static final class RequestImplementationDefault extends Request {
                @Override
                void doSomethingImpl() {
                        System.out.println("I am doing something AAAAAA");
                }
        }

        public static final class RequestImplementaionOther extends Request {
                @Override
                void doSomethingImpl() {
                        System.out.println("I am doing something BBBBBB");
                }
        }

        // Static methods in here can be overriden
        public static abstract class Request {

                abstract void doSomethingImpl();

                // Static method
                public static void doSomething() {
                        getRequest().doSomethingImpl();
                }

                private static Request request;
                private static Request getRequest() {
                        // If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too. 
                        if ( request == null ) {
                                return request = new RequestImplementationDefault();
                        }
                        return request;
                }
                public static Request setRequest(Request r){
                        return request = r;
                }

        }
}

================= Ancien exemple ci-dessous =================

Recherchez getRequest, et getRequestImpl ... setInstance peut être appelé pour modifier l'implémentation avant l'appel.

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Mo. Joseph
 * @date 16 mar 2012
 **/

public abstract class Core {


    // ---------------------------------------------------------------        
    private static Core singleton; 
    private static Core getInstance() {
        if ( singleton == null )
            setInstance( new Core.CoreDefaultImpl() );  // See bottom for CoreDefaultImpl

        return singleton;
    }    

    public static void setInstance(Core core) {
        Core.singleton = core;
    }
    // ---------------------------------------------------------------        



    // Static public method
    public static HttpServletRequest getRequest() {      
        return getInstance().getRequestImpl();
    }


    // A new implementation would override this one and call setInstance above with that implementation instance
    protected abstract HttpServletRequest getRequestImpl();




    // ============================ CLASSES =================================

    // ======================================================================
    // == Two example implementations, to alter getRequest() call behaviour 
    // == getInstance() have to be called in all static methods for this to work
    // == static method getRequest is altered through implementation of getRequestImpl
    // ======================================================================

    /** Static inner class CoreDefaultImpl */
    public static class CoreDefaultImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }
    }

     /** Static inner class CoreTestImpl : Alternative implementation */
    public static class CoreTestImpl extends Core { 
        protected HttpServletRequest getRequestImpl() {
            return new MockedRequest();
        }
    }       

}

Utilisé comme suit:

static {
     Core.setSingleton(new Core.CoreDefaultImpl());

     // Or

     Core.setSingleton(new Core.CoreTestImpl());

     // Later in the application you might use

     Core.getRequest(); 

}

6
Je n'ai pas compris où vous avez fourni un exemple de abstract staticméthode comme demandé dans la question et vous avez écrit en gras CAN BE DONE IN JAVA . C'est complètement erroné.
Blip

1
Il ne vous permet pas en soi de le définir comme statique abstrait, mais vous pouvez obtenir un résultat similaire grâce auquel vous pouvez modifier l'implémentation de la méthode statique en utilisant ce modèle / hack. Ce n'est guère erroné. Cela peut être fait, mais en utilisant une sémantique différente.
mmm

Ceci est un exemple d'extension d'une classe abstraite, puis de placement des méthodes statiques dans l'enfant. Ce n'est pas un exemple de CAN BE DONE IN JAVA, de quelque manière que ce soit.
Scuba Steve

2
@ScubaSteve Premièrement, vous vous trompez sur votre conclusion. Deuxièmement, il atteint le même résultat. Cela signifie que l'accès statique à une classe peut être modifié par une autre implémentation. Ce n'est pas une réponse que de dire que j'ai rendu le mot-clé statique abstrait, mais en utilisant ce modèle, vous pouvez utiliser des méthodes statiques tout en modifiant leur implémentation. Cela n'a cependant que l'effet négatif d'être global, mais pour un environnement test / prod / dev, il fait l'affaire pour nous.
mmm

5
  • Une méthode abstraite n'est définie que pour pouvoir être remplacée dans une sous-classe. Cependant, les méthodes statiques ne peuvent pas être remplacées. Par conséquent, c'est une erreur de compilation d'avoir une méthode abstraite et statique.

    Maintenant, la question suivante est de savoir pourquoi les méthodes statiques ne peuvent pas être remplacées.

  • C'est parce que les méthodes statiques appartiennent à une classe particulière et non à son instance. Si vous essayez de remplacer une méthode statique, vous n'obtiendrez aucune erreur de compilation ou d'exécution, mais le compilateur masquera simplement la méthode statique de superclasse.


4

Une méthode statique, par définition, n'a pas besoin de savoir this. Ainsi, il ne peut pas s'agir d'une méthode virtuelle (qui est surchargée en fonction des informations de sous-classe dynamique disponibles via this); au lieu de cela, une surcharge de méthode statique est uniquement basée sur les informations disponibles au moment de la compilation (cela signifie: une fois que vous référez une méthode statique de superclasse, vous appelez notamment la méthode de superclasse, mais jamais une méthode de sous-classe).

Selon cela, les méthodes statiques abstraites seraient tout à fait inutiles car vous n'aurez jamais sa référence substituée par un corps défini.


4

Je vois qu'il y a déjà un dieu-zillion de réponses mais je ne vois pas de solutions pratiques. Bien sûr, c'est un vrai problème et il n'y a aucune bonne raison d'exclure cette syntaxe en Java. Étant donné que la question d'origine manque de contexte où cela peut être nécessaire, je fournis à la fois un contexte et une solution:

Supposons que vous ayez une méthode statique dans un groupe de classes identiques. Ces méthodes appellent une méthode statique spécifique à la classe:

class C1 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C1
    }
}
class C2 {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    private static void doMoreWork(int k) {
        // code specific to class C2
    }
}

doWork()dans C1et C2sont identiques. Il peut y avoir beaucoup de ces calsses: C3 C4etc. Si static abstractc'était autorisé, vous élimineriez le code en double en faisant quelque chose comme:

abstract class C {
    static void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }

    static abstract void doMoreWork(int k);
}

class C1 extends C {
    private static void doMoreWork(int k) {
        // code for class C1
    }
}

class C2 extends C {
    private static void doMoreWork(int k) {
        // code for class C2
    }
}

mais cela ne compilerait pas car la static abstractcombinaison n'est pas autorisée. Cependant, cela peut être contourné avec la static classconstruction, ce qui est autorisé:

abstract class C {
    void doWork() {
        ...
        for (int k: list)
            doMoreWork(k);
        ...
    }
    abstract void doMoreWork(int k);
}
class C1 {
    private static final C c = new  C(){  
        @Override void doMoreWork(int k) {
            System.out.println("code for C1");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}
class C2 {
    private static final C c = new C() {
        @Override void doMoreWork(int k) {
            System.out.println("code for C2");
        }
    };
    public static void doWork() {
        c.doWork();
    }
}

Avec cette solution, le seul code dupliqué est

    public static void doWork() {
        c.doWork();
    }

1
Étant donné que dans votre solution finale, la classe abstraite C n'a pas de méthodes statiques, alors pourquoi ne pas laisser C1 et C2 l'étendre et remplacer la méthode doMoreWork () et laisser toute autre classe créer son instance et appeler les méthodes requises. Fondamentalement, vous faites la même chose, c'est-à-dire en étendant la classe C en utilisant une classe anonyme, puis en C1 et C2 en utilisant son instance statique pour autoriser l'accès à partir d'une méthode statique, mais ce n'est pas du tout nécessaire.
sactiw

Je ne comprends pas le contexte que vous avez fourni ici. Dans votre solution finale, vous pouvez appeler C1.doWork()ou C2.doWork()Mais vous ne pouvez pas appeler C.doWork(). Toujours dans l'exemple que vous avez fourni, qui ne fonctionnera pas, supposez que cela ait été autorisé, alors comment la classe Ctrouvera-t-elle l'implémentation de doMoreWork()? Enfin, j'appellerais votre code de contexte une mauvaise conception. Pourquoi? tout simplement parce que vous avez créé une fonction distincte pour le code qui est unique au lieu de créer une fonction pour le code qui est commun, puis d'implémenter une fonction statique dans la classe C. C'est plus facile !!!
Blip

2

Supposons qu'il existe deux classes, Parentet Child. Parentest abstract. Les déclarations sont les suivantes:

abstract class Parent {
    abstract void run();
}

class Child extends Parent {
    void run() {}
}

Cela signifie que toute instance de Parentdoit spécifier comment run()est exécutée.

Cependant, supposez maintenant que ce Parentn'est pas le cas abstract.

class Parent {
    static void run() {}
}

Cela signifie que Parent.run()va exécuter la méthode statique.

La définition d'une abstractméthode est "Une méthode déclarée mais non implémentée", ce qui signifie qu'elle ne retourne rien elle-même.

La définition d'une staticméthode est "Une méthode qui renvoie la même valeur pour les mêmes paramètres quelle que soit l'instance sur laquelle elle est appelée".

abstractLa valeur de retour d' une méthode change à mesure que l'instance change. Une staticméthode ne le fera pas. Une static abstractméthode est à peu près une méthode où la valeur de retour est constante, mais ne renvoie rien. C'est une contradiction logique.

De plus, il n'y a vraiment pas beaucoup de raison pour une static abstractméthode.


2

Une classe abstraite ne peut pas avoir de méthode statique car l'abstraction est effectuée pour obtenir une LIAISON DYNAMIQUE alors que les méthodes statiques sont liées statiquement à leur fonctionnalité.Une méthode statique signifie un comportement ne dépendant pas d'une variable d'instance, donc aucune instance / objet n'est requis.Juste la classe. Les méthodes statiques appartiennent à la classe et non à l'objet. Ils sont stockés dans une zone mémoire appelée PERMGEN d'où ils sont partagés avec chaque objet. Les méthodes de la classe abstraite sont liées dynamiquement à leur fonctionnalité.


1
Les classes abstraites peuvent sûrement avoir des méthodes statiques. Mais pas des méthodes abstraites statiques.
JacksOnF1re

2

Déclarer une méthode staticsignifie que nous pouvons l'appeler par son nom de classe et si cette classe l'est abstractégalement, cela n'a aucun sens de l'appeler car elle ne contient aucun corps, et donc nous ne pouvons pas déclarer une méthode à la fois comme staticet abstract.


2

Comme les méthodes abstraites appartiennent à la classe et ne peuvent pas être remplacées par la classe d'implémentation, même s'il existe une méthode statique avec la même signature, elle masque la méthode, ne la remplace pas. Il est donc indifférent de déclarer la méthode abstraite comme statique car elle n'obtiendra jamais le corps. Ainsi, compiler l'erreur de temps.


1

Une méthode statique peut être appelée sans instance de la classe. Dans votre exemple, vous pouvez appeler foo.bar2 (), mais pas foo.bar (), car pour bar, vous avez besoin d'une instance. Le code suivant fonctionnerait:

foo var = new ImplementsFoo();
var.bar();

Si vous appelez une méthode statique, elle sera toujours exécutée avec le même code. Dans l'exemple ci-dessus, même si vous redéfinissez bar2 dans ImplementsFoo, un appel à var.bar2 () exécuterait foo.bar2 ().

Si bar2 n'a maintenant aucune implémentation (c'est ce que signifie abstrait), vous pouvez appeler une méthode sans implémentation. C'est très dangereux.


1
Et une méthode statique abstraite pourrait être appelée sans instance, mais elle nécessiterait la création d'une implémentation dans la classe enfant. Ce n'est pas exactement du polymorphisme, mais la seule façon de le contourner est d'avoir l'enfant concret implémenter une interface qui "nécessite" la méthode "statique abstraite". Désordonné, mais réalisable.
fijiaaron

3
en fait, j'avais tort. Vous ne pouvez pas non plus avoir de méthodes statiques dans une interface. Défaut de langue.
fijiaaron

1

Je crois avoir trouvé la réponse à cette question, sous la forme de pourquoi les méthodes d'une interface (qui fonctionnent comme des méthodes abstraites dans une classe parente) ne peuvent pas être statiques. Voici la réponse complète (pas la mienne)

Les méthodes essentiellement statiques peuvent être liées au moment de la compilation, car pour les appeler, vous devez spécifier une classe. Ceci est différent des méthodes d'instance, pour lesquelles la classe de la référence à partir de laquelle vous appelez la méthode peut être inconnue au moment de la compilation (ainsi, quel bloc de code est appelé ne peut être déterminé qu'au moment de l'exécution).

Si vous appelez une méthode statique, vous connaissez déjà la classe où elle est implémentée, ou ses sous-classes directes. Si vous définissez

abstract class Foo {
    abstract static void bar();
}

class Foo2 {
    @Override
    static void bar() {}
}

Ensuite, tout Foo.bar();appel est évidemment illégal et vous l'utiliserez toujours Foo2.bar();.

Dans cet esprit, le seul but d'une méthode abstraite statique serait d'imposer des sous-classes pour implémenter une telle méthode. Vous pourriez initialement penser que c'est TRÈS faux, mais si vous avez un paramètre de type générique, <E extends MySuperClass>ce serait bien de garantir via une interface qui le Epeut .doSomething(). Gardez à l'esprit qu'en raison du type d'effacement, les génériques n'existent qu'au moment de la compilation.

Alors, serait-ce utile? Oui, et c'est peut-être pour cela que Java 8 autorise les méthodes statiques dans les interfaces (mais uniquement avec une implémentation par défaut). Pourquoi pas des méthodes statiques abstraites avec une implémentation par défaut dans les classes? Tout simplement parce qu'une méthode abstraite avec une implémentation par défaut est en fait une méthode concrète.

Pourquoi pas des méthodes statiques abstraites / d'interface sans implémentation par défaut? Apparemment, simplement à cause de la façon dont Java identifie le bloc de code à exécuter (première partie de ma réponse).


1

Parce que la classe abstraite est un concept OOPS et que les membres statiques ne font pas partie d'OOPS ....
Maintenant, le problème est que nous pouvons déclarer des méthodes complètes statiques dans l'interface et nous pouvons exécuter l'interface en déclarant la méthode principale à l'intérieur d'une interface

interface Demo 
{
  public static void main(String [] args) {
     System.out.println("I am from interface");
  }
}

0

L'idée d'avoir une méthode statique abstraite serait que vous ne pouvez pas utiliser cette classe abstraite particulière directement pour cette méthode, mais seule la dérivée première serait autorisée à implémenter cette méthode statique (ou pour les génériques: la classe réelle du générique vous utilisation).

De cette façon, vous pouvez créer par exemple une classe abstraite sortableObject ou même une interface avec des méthodes statiques (auto-) abstraites, qui définit les paramètres des options de tri:

public interface SortableObject {
    public [abstract] static String [] getSortableTypes();
    public String getSortableValueByType(String type);
}

Vous pouvez maintenant définir un objet triable qui peut être trié par les principaux types qui sont les mêmes pour tous ces objets:

public class MyDataObject implements SortableObject {
    final static String [] SORT_TYPES = {
        "Name","Date of Birth"
    }
    static long newDataIndex = 0L ;

    String fullName ;
    String sortableDate ;
    long dataIndex = -1L ;
    public MyDataObject(String name, int year, int month, int day) {
        if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
        if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
        this.fullName = name ;
        this.sortableDate = MyUtils.createSortableDate(year,month,day);
        this.dataIndex = MyDataObject.newDataIndex++ ;
    }
    public String toString() {
        return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
    }

    // override SortableObject 
    public static String [] getSortableTypes() { return SORT_TYPES ; }
    public String getSortableValueByType(String type) {
        int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
        switch(index) {
             case 0: return this.name ;
             case 1: return this.sortableDate ;
        }
        return toString(); // in the order they were created when compared
    }
}

Vous pouvez maintenant créer un

public class SortableList<T extends SortableObject> 

qui peut récupérer les types, créer un menu contextuel pour sélectionner un type sur lequel trier et recourir à la liste en obtenant les données de ce type, ainsi que disposer d'une fonction d'ajout qui, lorsqu'un type de tri a été sélectionné, peut automatiquement -sort les nouveaux éléments. Notez que l'instance de SortableList peut accéder directement à la méthode statique de "T":

String [] MenuItems = T.getSortableTypes();

Le problème lié à l'utilisation d'une instance est que la SortableList peut ne pas encore contenir d'éléments, mais doit déjà fournir le tri préféré.

Cheerio, Olaf.


0

Tout d'abord, un point clé sur les classes abstraites - Une classe abstraite ne peut pas être instanciée (voir wiki ). Vous ne pouvez donc pas créer d' instance d'une classe abstraite.

Maintenant, la façon dont java traite les méthodes statiques consiste à partager la méthode avec toutes les instances de cette classe.

Donc, si vous ne pouvez pas instancier une classe, cette classe ne peut pas avoir de méthodes statiques abstraites car une méthode abstraite demande à être étendue.

Boom.


Chaque méthode dans une classe abstraite a besoin que sa classe soit étendue de toute façon pour être exécutée, donc ce n'est pas une excuse. Vous pouvez étendre la classe abstraite (en même temps, implémenter la méthode abstraite). Donc cela ne fonctionne pas comme explication.
Pere

0

Selon le document Java :

Une méthode statique est une méthode associée à la classe dans laquelle elle est définie plutôt qu'à n'importe quel objet. Chaque instance de la classe partage ses méthodes statiques

En Java 8, avec les méthodes par défaut, les méthodes statiques sont également autorisées dans une interface. Cela nous permet d'organiser plus facilement les méthodes d'assistance dans nos bibliothèques. Nous pouvons conserver des méthodes statiques spécifiques à une interface dans la même interface plutôt que dans une classe distincte.

Un bel exemple de ceci est:

list.sort(ordering);

au lieu de

Collections.sort(list, ordering);

Un autre exemple d'utilisation de méthodes statiques est également donné dans la doc elle-même:

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

0

Parce que «abstrait» signifie que la méthode est censée être remplacée et que l'on ne peut pas remplacer les méthodes «statiques».


Cette réponse n'ajoute rien que les réponses précédentes n'ont pas déjà abordé.
MarsAtomic

@MarsAtomic Je pense que c'est plus approprié que la réponse la plus votée. De plus, c'est succinct.
Praveen Kumar

Ensuite, vous pouvez modifier les réponses antérieures pour les améliorer lorsque vous avez suffisamment de représentants. Tout ce que vous faites, c'est ajouter du bruit au signal en créant des réponses en double. Veuillez suivre les règles et coutumes établies de Stack Overflow plutôt que de créer les vôtres et de vous attendre à ce que tout le monde les suive.
MarsAtomic

Je ne suis pas d'accord, veuillez comparer ma réponse à d'autres, en particulier la réponse la plus votée.
Praveen Kumar

"Pourquoi je ne peux pas faire ça?" Réponse: "parce que vous ne pouvez pas".
JacksOnF1re

0

Les méthodes régulières peuvent être abstraites lorsqu'elles sont censées être remplacées par des sous-classes et dotées de fonctionnalités. Imaginez que la classe Foosoit étendue par Bar1, Bar2, Bar3etc. Ainsi, chacun aura sa propre version de la classe abstraite en fonction de ses besoins.

Or, les méthodes statiques appartiennent par définition à la classe, elles n'ont rien à voir avec les objets de la classe ou les objets de ses sous-classes. Ils n'en ont même pas besoin pour exister, ils peuvent être utilisés sans instancier les classes. Par conséquent, ils doivent être prêts à l'emploi et ne peuvent pas dépendre des sous-classes pour leur ajouter des fonctionnalités.


0

Parce que l'abstrait est un mot-clé appliqué aux méthodes abstraites, ne spécifiez pas de corps. Et si nous parlons de mot-clé statique, il appartient à la zone de classe.


veuillez être un peu plus élaboré sur votre réponse.
Blip

0

car si vous utilisez un membre statique ou une variable statique dans la classe, il se chargera au moment du chargement de la classe.


3
et pourquoi serait-ce un problème?
2018 à

-1

Vous pouvez le faire avec des interfaces dans Java 8.

Voici la documentation officielle à ce sujet:

https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html


2
Comment? J'ai cherché des solutions et je n'en ai pas trouvé.
thouliha

Wut? Vous ne pouvez pas. Toutes les méthodes d'interfaces statiques doivent être appelées à l'aide de la classe d'interface.
mmm

8
Cette réponse est fausse et induit en erreur les personnes nouvelles en Java. Cela ne montre aucun exemple de méthode statique abstraite car elle ne peut pas être implémentée et indiquée dans d'autres réponses
Blip

-1

Parce que si une classe étend une classe abstraite, elle doit remplacer les méthodes abstraites et c'est obligatoire. Et puisque les méthodes statiques sont des méthodes de classe résolues au moment de la compilation alors que les méthodes remplacées sont des méthodes d'instance résolues au moment de l'exécution et après le polymorphisme dynamique.


Veuillez capitaliser et ponctuer ce gâchis.
Marquis de Lorne
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.