Perché i metodi statici non possono essere astratti in Java?


593

La domanda è in Java perché non posso definire un metodo statico astratto? per esempio

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

9
Pochi motivi: il metodo statico deve avere un corpo anche se fanno parte della classe astratta perché non è necessario creare un'istanza di una classe per accedere al suo metodo statico. Un altro modo di pensarci è se per un momento assumiamo che sia consentito, quindi il problema è che le chiamate ai metodi statici non forniscono alcuna informazione sul tipo di tempo di esecuzione (RTTI), ricordare che non è richiesta la creazione di istanze, quindi non possono essere reindirizzati per le loro specifiche implementazioni overriden e quindi consentire abstarct static non ha alcun senso. In altre parole, non poteva fornire alcun vantaggio sul polimorfismo, quindi non è permesso.
Sactiw,

6
Se hai qualcosa per rispondere alla domanda, pubblicala come risposta , non come commento
Solomon Ucko,

Risposte:


568

Perché "astratto" significa: "Non implementa alcuna funzionalità" e "statico" significa: "Esiste funzionalità anche se non si dispone di un'istanza di oggetto". E questa è una contraddizione logica.


353
Una risposta più concisa sarebbe "design del linguaggio volgare". Statico dovrebbe significare "appartiene alla classe" perché è così che viene utilizzato in modo intuitivo, come dimostra questa domanda. Vedi "classmethod" in Python.
Alexander Ljungberg,

12
@Tomalak mi scuso, non ero chiaro. Naturalmente un metodo statico 'appartiene alla classe'. Tuttavia, è solo nel senso che vive nello stesso spazio dei nomi. Un metodo statico non è un metodo dell'oggetto di classe stesso: non funziona con "this" come oggetto di classe e non partecipa correttamente alla catena di ereditarietà. Se fosse davvero un metodo di classe abstract staticavrebbe perfettamente senso. Sarebbe un metodo dell'oggetto classe stesso che gli oggetti della sottoclasse devono implementare. Certo, il modo in cui le cose stanno la tua risposta è corretto, nonostante la mia presa sulla lingua.
Alexander Ljungberg,

695
Non è una contraddizione logica, è una mancanza di lingua, più altre lingue supportano questa nozione. "astratto" significa "implementato in sottoclassi", "statico" significa "eseguito sulla classe anziché su istanze di classe" Non vi è alcuna contraddizione logica.
Eric Grange,

10
@Eric: E ancora , quello che dici non si applica a abstract static: Una funzione X che viene "implementato nella sottoclasse" non può al tempo stesso essere "eseguito sulla classe" - solo sulla sottoclasse . Dove quindi non è più astratto.
Tomalak,

72
@Tomakak: la tua logica è circolare. staticnon significa "non vuoto" - questa è solo una conseguenza di Java che non consente ai metodi statici di essere astratti. Significa "richiamabile sulla classe". (Dovrebbe significare "richiamabile solo sulla classe" ma questo è un altro problema.) Se i abstract staticmetodi supportati da Java mi aspetto che significhi che il metodo 1) deve essere implementato da sottoclassi e 2) è un metodo di classe della sottoclasse. Alcuni metodi semplicemente non hanno senso come metodi di istanza. Sfortunatamente Java non ti consente di specificarlo quando crei una classe base astratta (o un'interfaccia).
Michael Carman,

326

Design del linguaggio scadente. Sarebbe molto più efficace chiamare direttamente un metodo astratto statico rispetto alla creazione di un'istanza solo per l'utilizzo di quel metodo astratto. Soprattutto quando si utilizza una classe astratta come soluzione alternativa all'enorme incapacità di estendere, che è un altro esempio di progettazione scadente. Spero che risolvano questi limiti nella prossima versione.


25
Java è piena di strani limiti. Le chiusure che accedono solo alle variabili finali sono un'altra. E l'elenco rimanente è quasi infinito. È compito di un programmatore Java conoscere loro e le loro soluzioni alternative. Per divertirci dobbiamo usare qualcosa di meglio di Java nel nostro tempo libero. Ma non mi preoccuperei. Questo è il seme per ottenere progressi.
ceving

22
Credo che ciò che tu chiami come "design del linguaggio scadente" sia in realtà più un "design del linguaggio protettivo", il cui scopo è limitare le violazioni del principio OO che i programmatori fanno a causa di funzioni linguistiche non necessarie.
Ethanfar,

22
Il concetto di "statico astratto" è una violazione dei principi OO?
Trevor,

7
@threed, Niente affatto, ma ovviamente ci sono persone che affermano che il semplice concetto di staticse stesso sia già una violazione ...
Pacerier,

4
La necessità di statica è una chiara dimostrazione che i "principi OO" non sono così onnicomprensivi come di solito affermato.
Ben

147

Non è possibile ignorare un metodo statico, quindi renderlo astratto sarebbe privo di significato. Inoltre, un metodo statico in una classe astratta appartiene a quella classe, e non alla classe prevalente, quindi non può essere utilizzato comunque.


18
Sì, è davvero un peccato che i metodi statici non possano essere ignorati in Java.
Michel,

12
@Michel: quale sarebbe il punto? Se si desidera un comportamento basato sull'istanza, utilizzare i metodi di istanza.
Ran Biron,

8
Questa risposta non è corretta I metodi statici nelle classi astratte funzionano bene e sono comunemente usati. È solo che un metodo statico della classe stessa potrebbe non essere astratto. @Michel non ha senso ignorare un metodo statico. Senza un'istanza, come farebbe il runtime a sapere quale metodo richiamare?
Erickson,

63
@erickson - Anche senza un'istanza, la gerarchia di classi è intatta - l'ereditarietà sui metodi statici può funzionare proprio come l'ereditarietà dei metodi di istanza. Smalltalk lo fa ed è abbastanza utile.
Jared,

8
@matiasg non è affatto una novità. Alle classi astratte è sempre stato permesso di avere metodi statici, non astratti .
Matt Ball

70

L' abstractannotazione a un metodo indica che il metodo DEVE essere sostituito in una sottoclasse.

In Java, un staticmembro (metodo o campo) non può essere sovrascritto da sottoclassi (questo non è necessariamente vero in altri linguaggi orientati agli oggetti, vedere SmallTalk). Un staticmembro può essere nascosto , ma fondamentalmente diverso da sovrascritto .

Poiché i membri statici non possono essere sostituiti in una sottoclasse, l' abstractannotazione non può essere applicata ad essi.

A parte questo, altre lingue supportano l'ereditarietà statica, proprio come l'ereditarietà delle istanze. Dal punto di vista della sintassi, tali lingue richiedono generalmente che il nome della classe sia incluso nell'istruzione. Ad esempio, in Java, supponendo che tu stia scrivendo codice in ClassA, si tratta di istruzioni equivalenti (se methodA () è un metodo statico e non esiste un metodo di istanza con la stessa firma):

ClassA.methodA();

e

methodA();

In SmallTalk, il nome della classe non è facoltativo, quindi la sintassi è (si noti che SmallTalk non usa il. Per separare "soggetto" e "verbo", ma invece lo usa come terminatore di stato):

ClassA methodA.

Poiché il nome della classe è sempre richiesto, la "versione" corretta del metodo può sempre essere determinata attraversando la gerarchia di classi. Per quello che vale, a volte mi manca l' staticeredità ed è stato morso dalla mancanza di eredità statica in Java quando ho iniziato con esso. Inoltre, SmallTalk è duck-type (e quindi non supporta il programma per contratto). Pertanto, non ha abstractmodificatore per i membri della classe.


1
"Un membro statico non può essere sostituito da sottoclassi" è errato. È possibile, almeno in Java6. Non sono sicuro da quando è il caso.
Steven De Groote,

15
@Steven De Groote Un membro statico non può essere sovrascritto da sottoclassi. Se una sottoclasse ha un metodo statico con la stessa firma di un metodo statico nella superclasse, non la ignora, la nasconde. http://docs.oracle.com/javase/tutorial/java/IandI/override.html La differenza è che il polimorfismo funziona solo per metodi scavalcati, ma non per metodi nascosti.
Giovanni 29

2
@ John29 Grazie per il chiarimento, ma a parte la differenza di denominazione sembra simile nell'uso.
Steven De Groote,

2
@Steven De Groote Sì, è simile nell'uso, ma il comportamento è diverso. Questo è il motivo per cui non esistono metodi astratti statici: qual è il punto dei metodi astratti statici se non supportano il polimorfismo?
Giovanni 29

3
@Steven De Groote: la differenza diventa evidente quando hai una chiamata a quel metodo nella superclasse stessa. Supponiamo che Super.foo chiami Super.bar. Se una sottoclasse implementa Subclass.bar e quindi chiama foo, allora foo chiamerà comunque Super.bar, non Subclass.bar. Quindi, quello che hai davvero è due metodi completamente diversi e non correlati entrambi chiamati "bar". Questo non è prioritario in alcun senso utile.
Doradus,

14

Ho anche fatto la stessa domanda, ecco perché

Dal momento che dice la classe astratta, non darà l'implementazione e consentirà alla sottoclasse di fornirla

quindi la sottoclasse deve sovrascrivere i metodi di Superclass,

REGOLA N. 1 - Un metodo statico non può essere ignorato

Poiché i membri e i metodi statici sono elementi del tempo di compilazione, ecco perché sono consentiti il ​​sovraccarico (polimorfismo del tempo di compilazione) dei metodi statici piuttosto che l'override (polimorfismo di runtime)

Quindi, non possono essere astratti.

Non esiste nulla di simile allo statico astratto <--- Non consentito nell'universo Java


5
-1, Non è vero che "Java non consente di ignorare il metodo statico perché i membri ei metodi statici sono elementi del tempo di compilazione". Il controllo statico del tipo è sicuramente possibile con abstract staticvedi stackoverflow.com/questions/370962/… . Il vero motivo per cui Java non consente l'override dei metodi statici è perché Java non consente l'override dei metodi statici.
Pacerier,

Il sovraccarico non ha nulla a che fare con il polimorfismo. Il sovraccarico e l'override non hanno nulla in comune, tranne il prefisso "over" nello stesso modo in cui Java e JavaScript hanno entrambi "Java" al loro interno. Il nome di un metodo non è ciò che identifica, è la sua firma. quindi foo(String)non è lo stesso di foo(Integer)- questo è tutto.
Captain Man,

@CaptainMan Il sovraccarico è letteralmente chiamato "polimorfismo parametrico" perché, a seconda del tipo di parametro, viene chiamato un metodo diverso che è il polimorfismo.
Assapora il

12

Questo è un design del linguaggio terribile e davvero nessuna ragione per cui non è possibile.

In effetti, ecco un'implementazione su come può essere fatto in 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;
                }

        }
}

================= Vecchio esempio di seguito =================

Cerca getRequest e getRequestImpl ... setInstance può essere chiamato per modificare l'implementazione prima di effettuare la chiamata.

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();
        }
    }       

}

Usato come segue:

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

     // Or

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

     // Later in the application you might use

     Core.getRequest(); 

}

6
Non ho capito dove hai fornito un esempio di un abstract staticmetodo come richiesto nella domanda e hai scritto in grassetto PUO 'ESSERE FATTO IN JAVA . Questo è completamente fuorviante.
Blip,

1
Di per sé non ti permette di definirlo come statico astratto, ma puoi ottenere un risultato simile per cui puoi cambiare l'implementazione del metodo statico usando questo modello / hack. È appena fuorviato. Può essere fatto, ma usando una semantica diversa.
mmm,

Questo è un esempio di estensione di una classe astratta, quindi dell'inserimento dei metodi statici nel figlio. Questo non è un esempio di CAN BE DONE IN JAVA, in alcun modo.
Scuba Steve

2
@ScubaSteve Innanzitutto, ti sbagli sulle tue conclusioni. In secondo luogo, ottiene lo stesso risultato. Ciò significa che l'accesso statico a una classe può essere modificato da un'altra implementazione. Non è una risposta per dire che ho reso la parola chiave statica estraibile, ma usando questo modello è possibile utilizzare metodi statici e comunque modificarne l'implementazione. Tuttavia ha l'effetto negativo di essere globali, ma per un ambiente test / prod / dev fa il trucco per noi.
mmm

5
  • Un metodo astratto è definito solo in modo che possa essere sovrascritto in una sottoclasse. Tuttavia, i metodi statici non possono essere ignorati. Pertanto, è un errore in fase di compilazione avere un metodo astratto e statico.

    Ora la domanda successiva è perché i metodi statici non possono essere ignorati ??

  • È perché i metodi statici appartengono a una classe particolare e non alla sua istanza. Se si tenta di sovrascrivere un metodo statico non si otterrà alcun errore di compilazione o runtime ma il compilatore nasconderebbe semplicemente il metodo statico di superclasse.


4

Un metodo statico, per definizione, non ha bisogno di sapere this. Pertanto, non può essere un metodo virtuale (che viene sovraccaricato in base alle informazioni della sottoclasse dinamica disponibile attraverso this); invece, un sovraccarico del metodo statico si basa esclusivamente sulle informazioni disponibili al momento della compilazione (questo significa: una volta che si fa riferimento a un metodo statico di superclasse, si chiama in particolare il metodo superclasse, ma mai un metodo di sottoclasse).

Secondo questo, i metodi statici astratti sarebbero del tutto inutili perché non si sostituirà mai il suo riferimento con un corpo definito.


4

Vedo che ci sono già un milione di risposte, ma non vedo alcuna soluzione pratica. Ovviamente questo è un vero problema e non c'è una buona ragione per escludere questa sintassi in Java. Poiché la domanda originale manca di un contesto in cui ciò potrebbe essere necessario, fornisco sia un contesto che una soluzione:

Supponiamo di avere un metodo statico in un gruppo di classi identiche. Questi metodi chiamano un metodo statico specifico della 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()i metodi in C1e C2sono identici. Potrebbero esserci molti di questi calsses: C3 C4ecc. Se static abstractfosse permesso, elimineresti il ​​codice duplicato facendo qualcosa del tipo:

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
    }
}

ma questo non si compilerebbe perché la static abstractcombinazione non è consentita. Tuttavia, questo può essere eluso con il static classcostrutto, che è consentito:

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();
    }
}

Con questa soluzione l'unico codice duplicato è

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

1
Dato che nella tua soluzione finale la classe astratta C non ha metodi statici, allora perché non lasciare che C1 e C2 lo estendano e sovrascrivano il metodo doMoreWork () e lasci che qualsiasi altra classe faccia la sua istanza e chiami i metodi richiesti. Fondamentalmente stai facendo la stessa cosa, cioè estendere la classe C usando la classe anonima e poi in C1 e C2 usando la sua istanza statica per consentire l'accesso da un metodo statico, ma ciò non è affatto necessario.
Sactiw,

Non capisco il contesto che hai fornito qui. Nella tua soluzione finale, ciò che puoi fare è chiamare C1.doWork()o C2.doWork()Ma non puoi chiamare C.doWork(). Anche nell'esempio che hai fornito, che non funzionerà, supponi che se fosse permesso, come Ctroverà l'implementazione della classe doMoreWork()? Infine, definirei il tuo codice di contesto un cattivo design. Perché? semplicemente perché hai creato una funzione separata per il codice che è unica invece di creare una funzione per il codice comune e quindi implementare una funzione statica nella classe C. Questo è più facile !!!
Blip,

2

Supponiamo che ci siano due classi Parente Child. Parentlo è abstract. Le dichiarazioni sono le seguenti:

abstract class Parent {
    abstract void run();
}

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

Ciò significa che qualsiasi istanza di Parentdeve specificare come run()viene eseguita.

Tuttavia, supponiamo ora che Parentnon lo sia abstract.

class Parent {
    static void run() {}
}

Ciò significa che Parent.run()eseguirà il metodo statico.

La definizione di un abstractmetodo è "Un metodo dichiarato ma non implementato", il che significa che non restituisce nulla da solo.

La definizione di un staticmetodo è "Un metodo che restituisce lo stesso valore per gli stessi parametri indipendentemente dall'istanza su cui è chiamato".

abstractIl valore restituito di un metodo cambierà al variare dell'istanza. Un staticmetodo no. Un static abstractmetodo è praticamente un metodo in cui il valore restituito è costante, ma non restituisce nulla. Questa è una contraddizione logica.

Inoltre, non c'è davvero molto motivo per un static abstractmetodo.


2

Una classe astratta non può avere un metodo statico perché l'astrazione viene eseguita per ottenere il DYNAMIC BINDING mentre i metodi statici sono associati staticamente alla loro funzionalità. Un metodo statico significa un comportamento non dipendente da una variabile di istanza, quindi non è richiesta alcuna istanza / oggetto. I metodi statici appartengono alla classe e non all'oggetto. Sono memorizzati in un'area di memoria nota come PERMGEN da cui è condivisa con ogni oggetto. I metodi in classe astratta sono legati dinamicamente alla loro funzionalità.


1
Le classi astratte possono sicuramente avere metodi statici. Ma non metodi astratti statici.
JacksOnF1re

2

Dichiarare un metodo come staticmezzo che possiamo chiamare quel metodo con il nome della sua classe e se anche quella classe lo è abstract, non ha senso chiamarlo in quanto non contiene alcun corpo, e quindi non possiamo dichiarare un metodo sia come statice abstract.


2

Poiché i metodi astratti appartengono alla classe e non possono essere sovrascritti dalla classe di implementazione. Anche se esiste un metodo statico con la stessa firma, nasconde il metodo, non lo sovrascrive. Quindi è irrilevante dichiarare statico il metodo astratto in quanto non otterrà mai il corpo. Quindi, compilare l'errore nel tempo.


1

Un metodo statico può essere chiamato senza un'istanza della classe. Nel tuo esempio puoi chiamare foo.bar2 (), ma non foo.bar (), perché per bar hai bisogno di un'istanza. Il seguente codice funzionerebbe:

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

Se chiami un metodo statico, verrà eseguito sempre lo stesso codice. Nell'esempio sopra, anche se si ridefinisce bar2 in ImplementsFoo, una chiamata a var.bar2 () eseguirà foo.bar2 ().

Se bar2 ora non ha implementazione (questo è ciò che significa astratto), puoi chiamare un metodo senza implementazione. È molto dannoso.


1
E un metodo statico astratto potrebbe essere chiamato senza un'istanza, ma richiederebbe la creazione di un'implementazione nella classe figlio. Non è esattamente il polimorfismo, ma l'unico modo per aggirarlo è quello di far implementare al bambino concreto un'interfaccia che "richiede" il metodo "statico astratto". Disordinato, ma praticabile.
fijiaaron,

3
in realtà, mi sbagliavo. Non puoi avere metodi statici in un'interfaccia. Difetto del linguaggio.
fijiaaron,

1

Credo di aver trovato la risposta a questa domanda, nella forma del perché i metodi di un'interfaccia (che funzionano come metodi astratti in una classe genitore) non possono essere statici. Ecco la risposta completa (non la mia)

I metodi sostanzialmente statici possono essere associati al momento della compilazione, poiché per chiamarli è necessario specificare una classe. Questo è diverso dai metodi di istanza, per i quali la classe del riferimento da cui si chiama il metodo potrebbe essere sconosciuta al momento della compilazione (quindi quale blocco di codice viene chiamato può essere determinato solo in fase di esecuzione).

Se stai chiamando un metodo statico, conosci già la classe in cui è implementata o le sue sottoclassi dirette. Se lo definisci

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

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

Quindi ogni Foo.bar();chiamata è ovviamente illegale e la utilizzerai sempre Foo2.bar();.

Con questo in mente, l'unico scopo di un metodo astratto statico sarebbe quello di imporre sottoclassi per implementare tale metodo. Inizialmente potresti pensare che sia MOLTO sbagliato, ma se hai un parametro di tipo generico <E extends MySuperClass>sarebbe bello garantirlo tramite un'interfaccia che Epossa farlo .doSomething(). Tieni presente che a causa della cancellazione dei tipi i generici esistono solo al momento della compilazione.

Quindi sarebbe utile? Sì, e forse è per questo che Java 8 sta consentendo metodi statici nelle interfacce (anche se solo con un'implementazione predefinita). Perché non utilizzare metodi statici astratti con un'implementazione predefinita nelle classi? Semplicemente perché un metodo astratto con un'implementazione predefinita è in realtà un metodo concreto.

Perché non utilizzare metodi statici astratti / di interfaccia senza implementazione predefinita? Apparentemente, semplicemente per il modo in cui Java identifica quale blocco di codice deve eseguire (prima parte della mia risposta).


1

Perché la classe astratta è un concetto OOPS e i membri statici non fanno parte di OOPS ....
Ora il fatto è che possiamo dichiarare metodi statici completi nell'interfaccia e possiamo eseguire l'interfaccia dichiarando il metodo principale all'interno di un'interfaccia

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

0

L'idea di avere un metodo statico astratto sarebbe che non puoi usare quella particolare classe astratta direttamente per quel metodo, ma solo la prima derivata potrebbe implementare quel metodo statico (o per generici: la classe effettiva del generico che tu uso).

In questo modo, è possibile creare ad esempio una classe astratta sortableObject o addirittura interfacciarsi con metodi statici (auto) astratti, che definiscono i parametri delle opzioni di ordinamento:

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

Ora puoi definire un oggetto ordinabile che può essere ordinato in base ai tipi principali che sono gli stessi per tutti questi oggetti:

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
    }
}

Ora puoi creare un

public class SortableList<T extends SortableObject> 

che può recuperare i tipi, creare un menu a comparsa per selezionare un tipo su cui ordinare e ricorrere all'elenco ottenendo i dati da quel tipo, nonché avere una funzione di aggiunta che, quando è stato selezionato un tipo di ordinamento, può auto -ordinare nuovi elementi in. Si noti che l'istanza di SortableList può accedere direttamente al metodo statico di "T":

String [] MenuItems = T.getSortableTypes();

Il problema con la necessità di utilizzare un'istanza è che SortableList potrebbe non avere ancora elementi, ma è già necessario fornire l'ordinamento preferito.

Cheerio, Olaf.


0

Innanzitutto, un punto chiave sulle classi astratte: non è possibile creare un'istanza di una classe astratta (vedere wiki ). Quindi, non puoi creare alcuna istanza di una classe astratta.

Ora, il modo in cui java gestisce i metodi statici è condividendo il metodo con tutte le istanze di quella classe.

Pertanto, se non è possibile creare un'istanza di una classe, quella classe non può avere metodi statici astratti poiché un metodo astratto chiede di essere esteso.

Boom.


Ogni metodo in una classe astratta ha bisogno che la sua classe sia estesa comunque per essere eseguita, quindi questa non è una scusa. È possibile estendere la classe astratta (allo stesso tempo, implementando il metodo astratto). Quindi questo non funziona come una spiegazione.
Pere,

0

Secondo il documento Java :

Un metodo statico è un metodo associato alla classe in cui è definito anziché a qualsiasi oggetto. Ogni istanza della classe condivide i suoi metodi statici

In Java 8, insieme ai metodi predefiniti, sono consentiti anche metodi statici in un'interfaccia. Questo ci facilita l'organizzazione dei metodi di supporto nelle nostre librerie. Possiamo mantenere metodi statici specifici di un'interfaccia nella stessa interfaccia piuttosto che in una classe separata.

Un bell'esempio di questo è:

list.sort(ordering);

invece di

Collections.sort(list, ordering);

Un altro esempio di utilizzo di metodi statici è riportato anche nel documento stesso:

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

Perché "astratto" significa che il metodo deve essere ignorato e non è possibile ignorare metodi "statici".


Questa risposta non aggiunge nulla che le risposte precedenti non abbiano già affrontato.
MarsAtomic,

@MarsAtomic Penso che sia più appropriata della risposta più votata. Inoltre, è sintetico.
Praveen Kumar,

Quindi puoi modificare le risposte precedenti per migliorarle quando hai un rappresentante sufficiente. Tutto quello che stai facendo è aggiungere rumore al segnale creando risposte duplicate. Segui le regole e le consuetudini stabilite da Stack Overflow anziché crearne di tue e aspettarti che tutti gli altri seguano.
MarsAtomic,

Non sono d'accordo, si prega di confrontare la mia risposta con altre, in particolare la risposta più votata.
Praveen Kumar,

"Perché non posso farlo?" Risposta: "perché non puoi".
JacksOnF1re

0

I metodi regolari possono essere astratti quando devono essere sovrascritti da sottoclassi e dotati di funzionalità. Immagina che la classe Foosia estesa di Bar1, Bar2, Bar3ecc. Quindi, ognuno avrà la propria versione della classe astratta in base alle proprie esigenze.

Ora, i metodi statici per definizione appartengono alla classe, non hanno nulla a che fare con gli oggetti della classe o gli oggetti delle sue sottoclassi. Non hanno nemmeno bisogno che esistano, possono essere usati senza creare un'istanza delle classi. Pertanto, devono essere pronti all'uso e non possono dipendere dalle sottoclassi per aggiungere funzionalità ad esse.


0

Perché abstract è una parola chiave che viene applicata ai metodi Abstract non specifica un corpo. E se parliamo di parola chiave statica appartiene all'area di classe.


si prega di essere un po 'elaborato sulla tua risposta.
Blip,

0

perché se si utilizza un membro statico o una variabile statica in classe, verrà caricato al momento del caricamento della classe.


3
e perché dovrebbe essere un problema?
Eis,

-1

Puoi farlo con le interfacce in Java 8.

Questa è la documentazione ufficiale al riguardo:

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


2
Come? Ho cercato soluzioni e non sono riuscito a trovarne.
thouliha,

Wut? Non puoi. Tutti i metodi delle interfacce statiche devono essere richiamati utilizzando la classe interface.
mmm

8
Questa risposta è sbagliata ed è fuorviante per le persone nuove a java. Questo per mostrare qualsiasi esempio di metodo statico astratto in quanto non può essere implementato e dichiarato in altre risposte
Blip

-1

Perché se una classe estende una classe astratta, deve sovrascrivere i metodi astratti e questo è obbligatorio. E poiché i metodi statici sono metodi di classe risolti in fase di compilazione, mentre i metodi sovrascritti sono metodi di istanza risolti in fase di esecuzione e seguendo il polimorfismo dinamico.


Si prega di capitalizzare e punteggiare questo casino.
Marchese di Lorne,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.