Por que os métodos estáticos não podem ser abstratos em Java?


593

A questão está em Java, por que não consigo definir um método estático abstrato? por exemplo

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

9
Algumas razões: o método estático deve ter um corpo, mesmo que faça parte da classe abstrata, porque não é necessário criar uma instância de uma classe para acessar seu método estático. Outra maneira de pensar é se, por um momento, assumimos que é permitido, o problema é que as chamadas de método estático não fornecem nenhuma informação de tipo de tempo de execução (RTTI), lembre-se de que nenhuma criação de instância é necessária, portanto, não podem ser redirecionadas para suas implementações substituídas específicas e, portanto, permitir uma quase estática não faz nenhum sentido. Em outras palavras, ele não poderia fornecer nenhum benefício de polimorfismo, portanto, não permitido.
sactiw

6
Se você tem algo a responder à pergunta, postá-lo como uma resposta , não é um comentário
Solomon Ucko

Respostas:


568

Como "abstrato" significa: "Não implementa funcionalidade" e "estático" significa: "Existe funcionalidade mesmo que você não tenha uma instância de objeto". E isso é uma contradição lógica.


353
Uma resposta mais concisa seria 'design de linguagem ruim'. Estático deve significar 'pertence à classe', porque é assim que é usado intuitivamente, como esta mesma pergunta demonstra. Veja "classmethod" em Python.
Alexander Ljungberg 15/05

12
@Tomalak Peço desculpas, não estava claro. Obviamente, um método estático 'pertence à classe'. Ainda assim, é apenas no sentido de que ele vive no mesmo espaço para nome. Um método estático não é um método do próprio objeto de classe: ele não opera com 'this' como objeto de classe e não participa adequadamente da cadeia de herança. Se realmente fosse um método de classe, abstract staticfaria todo o sentido. Seria um método do próprio objeto de classe que os objetos da subclasse devem implementar. Obviamente, a maneira como as coisas estão de acordo com a sua resposta está correta, apesar de eu ter me preocupado com o idioma.
Alexander Ljungberg 15/05

695
Não é uma contradição lógica, é uma falha de linguagem, várias outras línguas apóiam essa noção. "abstrato" significa "implementado nas subclasses", "estático" significa "executado na classe e não nas instâncias da classe" Não há contradição lógica.
Eric Grange

10
@ Eric: E ainda , o que você diz não se aplica a abstract static: Uma função X que é "implementada na subclasse" não pode ao mesmo tempo ser "executada na classe" - apenas na subclasse . Onde então não é mais abstrato.
amigos estão

72
@ Tomkak: Sua lógica é circular. staticnão significa "não vazio" - isso é apenas uma consequência do Java não permitir que métodos estáticos sejam abstratos. Significa "callable na classe". (Deveria significar "que pode ser chamado apenas na classe", mas isso é outro problema.) Se o Java suportasse abstract staticmétodos, eu esperaria que isso significasse que o método 1) deve ser implementado pelas subclasses e 2) é um método de classe da subclasse. Alguns métodos simplesmente não fazem sentido como métodos de instância. Infelizmente, o Java não permite que você especifique isso ao criar uma classe base abstrata (ou uma interface).
Michael Carman 29/03

326

Design de linguagem ruim. Seria muito mais eficaz chamar diretamente um método abstrato estático do que criar uma instância apenas para usar esse método abstrato. Especialmente verdadeiro ao usar uma classe abstrata como uma solução alternativa para a incapacidade de extensão, que é outro exemplo ruim de design. Espero que eles resolvam essas limitações em um próximo lançamento.


25
Java está cheio de limitações estranhas. Fechamentos acessando apenas variáveis ​​finais é outra. E a lista restante é quase interminável. O trabalho de um programador Java é conhecê-los e suas soluções alternativas. Para nos divertir, precisamos usar algo melhor que Java em nosso tempo livre. Mas eu não me incomodaria. Essa é a semente para alcançar o progresso.
ceving 04/12/12

22
Acredito que o que você chama de "Design de linguagem ruim" é realmente mais um "Design de linguagem de proteção", cujo objetivo é limitar as violações do princípio de OO que os programadores fazem devido a recursos desnecessários de linguagem.
ethanfar

22
O conceito de "estática abstrata" é uma violação dos princípios da OO?
Trevor

7
@threed, não em todos, mas é claro que existem pessoas que dizem que o simples conceito de staticsi já é uma violação ....
Pacerier

4
A necessidade de estática é uma demonstração clara de que os "princípios OO" não são tão abrangentes quanto se costuma afirmar.
Ben

147

Você não pode substituir um método estático, tornando-o abstrato não faria sentido. Além disso, um método estático em uma classe abstrata pertenceria a essa classe, e não a classe de substituição, portanto não poderia ser usado de qualquer maneira.


18
Sim, é realmente uma pena que métodos estáticos não possam ser substituídos em Java.
Michel

12
@ Michel: qual seria o objetivo? Se você deseja um comportamento baseado em instância, use métodos de instância.
Ran Biron

8
Esta resposta está incorreta. Métodos estáticos em classes abstratas funcionam bem e são comumente usados. Só que os métodos estáticos da própria classe podem não ser abstratos. @ Michel, não faz sentido substituir um método estático. Sem uma instância, como o tempo de execução saberia qual método chamar?
Erickson

63
@erickson - Mesmo sem uma instância, a hierarquia de classes está intacta - a herança em métodos estáticos pode funcionar como a herança dos métodos de instância. Smalltalk faz isso, e é bastante útil.
Jared

8
@matiasg que não é nada novo. As classes abstratas sempre tiveram permissão para ter métodos estáticos e não abstratos .
Matt Bola

70

A abstractanotação para um método indica que o método DEVE ser substituído em uma subclasse.

Em Java, um staticmembro (método ou campo) não pode ser substituído por subclasses (isso não é necessariamente verdadeiro em outras linguagens orientadas a objetos, consulte SmallTalk.) Um staticmembro pode estar oculto , mas isso é fundamentalmente diferente de substituído .

Como os membros estáticos não podem ser substituídos em uma subclasse, a abstractanotação não pode ser aplicada a eles.

Como um aparte - outras linguagens suportam herança estática, assim como herança de instância. De uma perspectiva de sintaxe, esses idiomas geralmente exigem que o nome da classe seja incluído na declaração. Por exemplo, em Java, supondo que você esteja escrevendo código na ClassA, estas são instruções equivalentes (se methodA () for um método estático e não houver um método de instância com a mesma assinatura):

ClassA.methodA();

e

methodA();

No SmallTalk, o nome da classe não é opcional; portanto, a sintaxe é (observe que o SmallTalk não usa o.

ClassA methodA.

Como o nome da classe sempre é obrigatório, a "versão" correta do método sempre pode ser determinada percorrendo a hierarquia da classe. Pelo que vale, às vezes sinto falta da staticherança e fui mordido pela falta de herança estática no Java quando comecei com ela. Além disso, o SmallTalk é do tipo pato (e, portanto, não oferece suporte a programa por contrato.) Portanto, ele não possui abstractmodificadores para os membros da classe.


1
"Um membro estático não pode ser substituído por subclasses" está errado. É possível, pelo menos em Java6. Não tenho certeza desde quando é o caso.
9789 Steven St Groote

15
@ Steven De Groote Um membro estático realmente não pode ser substituído por subclasses. Se uma subclasse possui um método estático com a mesma assinatura que um método estático na superclasse, ela não a substitui, mas a oculta. http://docs.oracle.com/javase/tutorial/java/IandI/override.html A diferença é que o polimorfismo funciona apenas para métodos substituídos, mas não para métodos ocultos.
precisa saber é o seguinte

2
@ John29 Obrigado pelo esclarecimento, mas, além da diferença de nomes, parece semelhante no uso.
Steven De Groote

2
@ Steven De Groote Sim, é semelhante no uso, mas o comportamento é diferente. Essa é a razão pela qual não há métodos abstratos estáticos - qual é o sentido dos métodos abstratos estáticos se eles não suportam polimorfismo?
John29

3
@ Steven De Groote: A diferença se torna aparente quando você faz uma chamada para esse método na própria superclasse. Suponha que Super.foo chame Super.bar. Se uma subclasse implementar Subclass.bar e chamar foo, foo ainda chamará Super.bar, não Subclass.bar. Portanto, o que você realmente tem são dois métodos totalmente diferentes e não relacionados, ambos chamados de "barra". Isso não substitui em nenhum sentido útil.
Doradus 02/09

14

Eu também fiz a mesma pergunta, aqui está o porquê

Como a classe Abstract diz, ela não dará implementação e permitirá que a subclasse dê

então a subclasse precisa substituir os métodos da superclasse,

REGRA Nº 1 - Um método estático não pode ser substituído

Como membros e métodos estáticos são elementos de tempo de compilação, é por isso que Sobrecarga (Polimorfismo em tempo de compilação) de métodos estáticos é permitida, em vez de Substituir (Polimorfismo em tempo de execução)

Então, eles não podem ser abstratos.

Não existe algo como estática abstrata <--- Não é permitido no Universo Java


5
-1, não é verdade que "Java não permite que o método estático seja substituído porque membros e métodos estáticos são elementos de tempo de compilação". A verificação de tipo estática é definitivamente possível com abstract staticconsulte stackoverflow.com/questions/370962/… . A verdadeira razão pela qual o Java não permite que os métodos estáticos sejam substituídos é porque o Java não permite que os métodos estáticos sejam substituídos.
Pacerier 10/09

Sobrecarga não tem nada a ver com polimorfismo. Sobrecarga e substituição não têm nada em comum, exceto o prefixo "over", da mesma maneira que Java e JavaScript acontecem, ambos com "Java". O nome de um método não é o que o identifica, é sua assinatura. então foo(String)não é o mesmo que foo(Integer)- isso é tudo.
Captain Man

A sobrecarga do @CaptainMan é literalmente chamada de "polimorfismo paramétrico" porque, dependendo do tipo do parâmetro, um método diferente é chamado, que é o polimorfismo.
Davor 28/01

12

Este é um design de linguagem terrível e realmente não há razão para que isso não seja possível.

De fato, aqui está uma implementação de como PODE ser feito em 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;
                }

        }
}

================= Exemplo antigo abaixo =================

Procure getRequest e getRequestImpl ... setInstance pode ser chamado para alterar a implementação antes que a chamada seja feita.

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

}

Usado como segue:

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

     // Or

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

     // Later in the application you might use

     Core.getRequest(); 

}

6
Não entendi onde você forneceu um exemplo de abstract staticmétodo, conforme solicitado na pergunta, e escreveu em negrito PODE SER FEITO EM JAVA . Isso é completamente errado.
Blip

1
Por si só, não é possível defini-lo como estático abstrato, mas é possível obter um resultado semelhante no qual é possível alterar a implementação do método estático de s usando esse padrão / hack. Não é mal orientado. Isso pode ser feito, mas usando diferentes semânticas.
mmm

Este é um exemplo de estender uma classe abstrata e colocar os métodos estáticos no filho. Este não é um exemplo de PODE SER FEITO EM JAVA, de qualquer forma.
Mergulhador Steve

2
@ ScubaSteve Primeiro, você está errado em sua conclusão. Segundo, atinge o mesmo resultado. Significando que o acesso estático a uma classe pode ser alterado por outra implementação. Não é uma resposta para dizer que tornei a palavra-chave estática abstraível, mas usando esse padrão você pode usar métodos estáticos e ainda alterar sua implementação. Porém, ele tem o efeito negativo de ser global, mas, para um ambiente de teste / prod / dev, ele faz o truque para nós.
Mmm

5
  • Um método abstrato é definido apenas para que possa ser substituído em uma subclasse. No entanto, métodos estáticos não podem ser substituídos. Portanto, é um erro em tempo de compilação ter um método estático abstrato.

    Agora, a próxima pergunta é por que métodos estáticos não podem ser substituídos?

  • É porque os métodos estáticos pertencem a uma classe específica e não a sua instância. Se você tentar substituir um método estático, não receberá nenhum erro de compilação ou tempo de execução, mas o compilador apenas ocultará o método estático da superclasse.


4

Um método estático, por definição, não precisa saber this. Portanto, não pode ser um método virtual (sobrecarregado de acordo com as informações da subclasse dinâmica disponíveis por meio dethis ); em vez disso, uma sobrecarga de método estático é baseada exclusivamente nas informações disponíveis no tempo de compilação (isto significa: depois de consultar um método estático de superclasse, você chama o método de superclasse, mas nunca um método de subclasse).

De acordo com isso, métodos estáticos abstratos seriam bastante inúteis porque você nunca terá sua referência substituída por algum corpo definido.


4

Vejo que já existem um zilhão de respostas, mas não vejo soluções práticas. É claro que esse é um problema real e não há boas razões para excluir essa sintaxe em Java. Como a pergunta original não possui um contexto em que isso possa ser necessário, forneço um contexto e uma solução:

Suponha que você tenha um método estático em várias classes idênticas. Esses métodos chamam um método estático específico da 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()métodos C1e C2são idênticos. Pode haver muitas dessas calsses: C3 C4etc. Se static abstractfosse permitido, você eliminaria o código duplicado fazendo algo como:

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

mas isso não seria compilado porque a static abstractcombinação não é permitida. No entanto, isso pode ser contornado com a static classconstrução, que é permitida:

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

Com esta solução, o único código duplicado é

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

1
Como em sua solução final a classe C abstrata não possui métodos estáticos, por que não permitir que C1 e C2 a estendam e substituam o método doMoreWork () e deixem outras classes fazerem sua instância e chamarem os métodos necessários. Basicamente, você está fazendo o mesmo, ou seja, estendendo a classe C usando classe anônima e, em seguida, em C1 e C2 usando sua instância estática para permitir o acesso a partir de um método estático, mas isso não é necessário.
sactiw

Não entendo o contexto que você forneceu aqui. Na sua solução final, o que você pode fazer é ligar C1.doWork()ou C2.doWork()Mas você não pode ligar C.doWork(). Também no exemplo que você forneceu, que não funcionará, suponha que se fosse permitido, então como a classe Cencontrará a implementação dedoMoreWork() ? Finalmente, eu chamaria seu código de contexto de um design ruim. Por quê? simplesmente porque você criou uma função separada para o código exclusivo, em vez de criar uma função comum para o código e implementar uma função estática na classe C. Isso é mais fácil !!!
Blip

2

Suponha que há duas classes Parente Child. Parenté abstract. As declarações são as seguintes:

abstract class Parent {
    abstract void run();
}

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

Isso significa que qualquer instância de Parentdeve especificar como run()é executada.

No entanto, assuma agora que Parentnão é abstract.

class Parent {
    static void run() {}
}

Isso significa que Parent.run()irá executar o método estático.

A definição de um abstractmétodo é "Um método declarado, mas não implementado", o que significa que ele não retorna nada.

A definição de um staticmétodo é "Um método que retorna o mesmo valor para os mesmos parâmetros, independentemente da instância na qual é chamado".

O abstractvalor de retorno de um método será alterado conforme a instância. Um staticmétodo não. Um static abstractmétodo é basicamente um método em que o valor de retorno é constante, mas não retorna nada. Isso é uma contradição lógica.

Além disso, não há realmente um motivo para um static abstractmétodo.


2

Uma classe abstrata não pode ter um método estático porque a abstração é feita para obter DYNAMIC BINDING enquanto os métodos estáticos estão estaticamente ligados à sua funcionalidade.Um método estático significa comportamento não dependente de uma variável de instância, portanto, nenhuma instância / objeto é necessário. Os métodos estáticos pertencem à classe e não ao objeto. Eles são armazenados em uma área de memória conhecida como PERMGEN, de onde é compartilhada com todos os objetos. Métodos na classe abstrata são ligados dinamicamente à sua funcionalidade.


1
Classes abstratas certamente podem ter métodos estáticos. Mas não métodos abstratos estáticos.
precisa saber é o seguinte

2

Declarar um método como staticmeio, podemos chamá-lo por seu nome de classe e, se essa classe abstracttambém for, não faz sentido chamá-lo, pois ele não contém nenhum corpo e, portanto, não podemos declarar um método como statice abstract.


2

Como os métodos abstratos pertencem à classe e não podem ser substituídos pela classe de implementação. Mesmo se houver um método estático com a mesma assinatura, ele oculta o método, não o substitui. Portanto, é irrelevante declarar o método abstrato tão estático quanto nunca obterá o corpo. Assim, compile o erro de tempo.


1

Um método estático pode ser chamado sem uma instância da classe. No seu exemplo, você pode chamar foo.bar2 (), mas não foo.bar (), porque para bar você precisa de uma instância. O código a seguir funcionaria:

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

Se você chamar um método estático, ele será executado sempre com o mesmo código. No exemplo acima, mesmo se você redefinir bar2 no ImplementsFoo, uma chamada para var.bar2 () executaria foo.bar2 ().

Se bar2 agora não tem implementação (é isso que significa abstrato), você pode chamar um método sem implementação. Isso é muito prejudicial.


1
E um método estático abstrato pode ser chamado sem uma instância, mas exigiria que uma implementação fosse criada na classe filho. Não é exatamente polimorfismo, mas a única maneira de contornar isso é fazer com que o filho concreto implemente uma interface que "exija" o método "estático abstrato". Confuso, mas viável.
Fijiaaron

3
na verdade, eu estava errado. Você também não pode ter métodos estáticos em uma interface. Falha na linguagem.
Fijiaaron

1

Acredito que encontrei a resposta para essa pergunta, na forma de por que os métodos de uma interface (que funcionam como métodos abstratos em uma classe pai) não podem ser estáticos. Aqui está a resposta completa (não a minha)

Métodos basicamente estáticos podem ser vinculados em tempo de compilação, pois para chamá-los, você precisa especificar uma classe. Isso é diferente dos métodos de instância, para os quais a classe da referência da qual você está chamando o método pode ser desconhecida no momento da compilação (portanto, qual bloco de código é chamado pode ser determinado apenas em tempo de execução).

Se você está chamando um método estático, já conhece a classe em que é implementado ou qualquer subclasse direta dele. Se você definir

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

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

Qualquer Foo.bar();ligação é obviamente ilegal e você sempre usará Foo2.bar();.

Com isso em mente, o único objetivo de um método abstrato estático seria impor subclasses para implementar esse método. Você pode inicialmente achar que isso é MUITO errado, mas se você tiver um parâmetro de tipo genérico <E extends MySuperClass>, seria bom garantir via interface Epossível .doSomething(). Lembre-se de que, devido ao tipo de apagamento, os genéricos existem apenas no momento da compilação.

Então, seria útil? Sim, e talvez seja por isso que o Java 8 esteja permitindo métodos estáticos nas interfaces (embora apenas com uma implementação padrão). Por que não abstrair métodos estáticos com uma implementação padrão nas classes? Simplesmente porque um método abstrato com uma implementação padrão é realmente um método concreto.

Por que não abstrair / métodos estáticos de interface sem implementação padrão? Aparentemente, apenas por causa da maneira como o Java identifica qual bloco de código ele deve executar (primeira parte da minha resposta).


1

Como classe abstrata é um conceito OOPS e membros estáticos não fazem parte do OOPS ....
Agora, podemos declarar métodos estáticos completos na interface e podemos executar a interface declarando o método principal dentro de uma interface

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

0

A idéia de ter um método estático abstrato seria que você não pode usar essa classe abstrata específica diretamente para esse método, mas somente a primeira derivada poderá implementar esse método estático (ou para genéricos: a classe real do genérico você usar).

Dessa forma, você pode criar, por exemplo, uma classe abstrata sortableObject ou até mesmo fazer interface com métodos estáticos (auto-) abstratos, que definem os parâmetros das opções de classificação:

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

Agora você pode definir um objeto classificável que pode ser classificado pelos principais tipos que são iguais para todos esses objetos:

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

Agora você pode criar um

public class SortableList<T extends SortableObject> 

que pode recuperar os tipos, criar um menu pop-up para selecionar um tipo para classificar e recorrer à lista, obtendo os dados desse tipo, bem como criar uma função de adição que, quando um tipo de classificação foi selecionado, pode ser ativada automaticamente -sorte novos itens. Observe que a instância de SortableList pode acessar diretamente o método estático de "T":

String [] MenuItems = T.getSortableTypes();

O problema de ter que usar uma instância é que o SortableList pode ainda não ter itens, mas já precisa fornecer a classificação preferida.

Cheerio, Olaf.


0

Primeiro, um ponto chave sobre as classes abstratas - Uma classe abstrata não pode ser instanciada (consulte o wiki ). Portanto, você não pode criar nenhuma instância de uma classe abstrata.

Agora, a maneira como o java lida com métodos estáticos é compartilhando o método com todas as instâncias dessa classe.

Portanto, se você não pode instanciar uma classe, essa classe não pode ter métodos estáticos abstratos, pois um método abstrato implora para ser estendido.

Estrondo.


Todo método em uma classe abstrata precisa que sua classe seja estendida de qualquer maneira para ser executada, portanto isso não é uma desculpa. Você pode estender a classe abstrata (ao mesmo tempo, implementando o método abstrato). Portanto, isso não funciona como uma explicação.
Pere

0

Conforme o documento Java :

Um método estático é um método associado à classe em que está definido, e não a qualquer objeto. Cada instância da classe compartilha seus métodos estáticos

No Java 8, junto com os métodos padrão, os métodos estáticos também são permitidos em uma interface. Isso facilita a organização de métodos auxiliares em nossas bibliotecas. Podemos manter métodos estáticos específicos para uma interface na mesma interface, em vez de em uma classe separada.

Um bom exemplo disso é:

list.sort(ordering);

ao invés de

Collections.sort(list, ordering);

Outro exemplo de uso de métodos estáticos também é fornecido no próprio documento :

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

Como 'abstrato' significa que o método deve ser substituído e não se pode substituir os métodos 'estáticos'.


Esta resposta não adiciona nada que as respostas anteriores ainda não tenham abordado.
MarsAtomic

@MarsAtomic Eu acho que é mais apropriado do que a resposta mais votada. Além disso, é sucinto.
precisa saber é o seguinte

Em seguida, você pode editar as respostas anteriores para melhorá-las quando tiver representante suficiente. Tudo o que você está fazendo é adicionar ruído ao sinal, criando respostas duplicadas. Siga as regras e os costumes estabelecidos do Stack Overflow, em vez de criar os seus próprios e esperar que todos os outros sigam.
MarsAtomic

Não concordo, compare minha resposta com outra, especialmente a resposta mais votada.
Praveen Kumar

"Por que eu não posso fazer isso?" Resposta: "porque você não pode".
precisa saber é o seguinte

0

Os métodos regulares podem ser abstratos quando devem ser substituídos por subclasses e fornecidos com funcionalidade. Imagine que a classe Fooé estendida porBar1, Bar2, Bar3 etc. Portanto, cada um terá sua própria versão da classe abstrata de acordo com suas necessidades.

Agora, os métodos estáticos por definição pertencem à classe, eles não têm nada a ver com os objetos da classe ou os objetos de suas subclasses. Eles nem precisam que eles existam, eles podem ser usados ​​sem instanciar as classes. Portanto, eles precisam estar prontos para uso e não podem depender das subclasses para adicionar funcionalidade a eles.


0

Como abstract é uma palavra-chave aplicada sobre métodos Abstract, não especifica um corpo. E se falamos de palavra-chave estática, ela pertence à área de classe.


por favor, seja um pouco mais elaborado sobre sua resposta.
Blip

0

porque se você estiver usando algum membro estático ou variável estática na classe, ele será carregado no momento do carregamento da classe.


3
e por que isso seria um problema?
eis

-1

Você pode fazer isso com interfaces no Java 8.

Esta é a documentação oficial sobre o assunto:

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


2
Quão? Procurei soluções e não encontrei nenhuma.
thouliha

Que? Você não pode. Todos os métodos de interfaces estáticas devem ser chamados usando a classe de interface.
mmm

8
Esta resposta está errada e é equivocada para as pessoas novas em java. Isso mostra qualquer exemplo de método estático abstrato, uma vez que não pode ser implementado e declarado em outras respostas.
Blip

-1

Porque se uma classe estende uma classe abstrata, ela deve substituir os métodos abstratos, e isso é obrigatório. E como os métodos estáticos são métodos de classe resolvidos em tempo de compilação, enquanto os métodos substituídos são métodos de instância resolvidos em tempo de execução e após o polimorfismo dinâmico.


Capitalize e pontue essa bagunça.
Marquês de Lorne
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.