Por que os methods estáticos não podem ser abstratos em Java?

A questão é em Java porque não posso 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? } 

Porque “abstract” significa: “Implementa sem funcionalidade”, e “static” significa: “Existe funcionalidade mesmo se você não tiver uma instância de object”. E isso é uma contradição lógica.

Design de linguagem pobre. 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 class abstrata como uma solução alternativa para a incapacidade de extensão do enum, que é outro exemplo de design ruim. Espero que eles resolvam essas limitações em um próximo lançamento.

Você não pode sobrescrever um método estático, portanto, torná-lo abstrato não teria sentido. Além disso, um método estático em uma class abstrata pertenceria a essa class, e não à class que sobrescreve, portanto, não poderia ser usado de qualquer maneira.

A anotação abstract para um método indica que o método DEVE ser substituído em uma subclass.

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

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

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

 ClassA.methodA(); 

e

 methodA(); 

No SmallTalk, o nome da class não é opcional, então a syntax é (note que o SmallTalk não usa o arquivo. Para separar o “assunto” e o “verbo”, mas o usa como terminador do statemend):

 ClassA methodA. 

Como o nome da class é sempre necessário, a “versão” correta do método sempre pode ser determinada ao percorrer a hierarquia de classs. Por que vale a pena, ocasionalmente sinto falta da inheritance static e fui mordido pela falta de inheritance estática em Java quando comecei a usá-la. Além disso, o SmallTalk é tipificado por pato (e, portanto, não suporta programa por contrato). Portanto, ele não possui nenhum modificador abstract para os membros da class.

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

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

então a Subclass tem que sobrescrever os methods da Superclass,

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

Como os membros e methods estáticos são elementos de tempo de compilation, é por isso que Overloading (Polymorphism de tempo de compilation) de methods estáticos é permitido em vez de Overriding (Runtime Polymorphism)

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

Não há nada como abstract static <--- Não é permitido no Java Universe

Este é um projeto de linguagem terrível e realmente nenhuma razão por que não pode ser possível.

De fato, aqui está uma implementação de como isso pode ser feito no 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 por 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(); } } } 
  • Um método abstrato é definido apenas para que possa ser substituído em uma subclass. No entanto, os methods estáticos não podem ser substituídos. Portanto, é um erro em tempo de compilation ter um método estático abstrato.

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

  • É porque os methods estáticos pertencem a uma determinada class e não à sua instância. Se você tentar replace um método estático, você não receberá nenhum erro de compilation ou runtime, mas o compilador apenas ocultará o método estático da superclass.

Suponha que existem duas classs, Parent e 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 do Parent deve especificar como o run() é executado.

No entanto, assuma agora que o Parent não é abstract .

 class Parent { static void run() {} } 

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

A definição de um método abstract é “Um método declarado mas não implementado”, o que significa que ele não retorna nada em si.

A definição de um método static é “Um método que retorna o mesmo valor para os mesmos parâmetros, independentemente da instância em que é chamado”.

O valor de retorno de um método abstract será alterado conforme a instância for alterada. Um método static não. Um método static abstract é praticamente um método em que o valor de retorno é constante, mas não retorna nada. Esta é uma contradição lógica.

Além disso, não há muita razão para um método static abstract .

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

Um método estático, por definição, não precisa saber this . Assim, não pode ser um método virtual (que é sobrecarregado de acordo com a informação da subclass dinâmica disponível através this ); em vez disso, uma sobrecarga de método estática é baseada somente em informações disponíveis no tempo de compilation (isto significa que, uma vez que você referencia um método estático de superclass, você chama o método de superclass, mas nunca um método de subclass).

De acordo com isso, methods abstratos de estática seriam completamente inúteis porque você nunca terá sua referência substituída por algum corpo definido.

Eu vejo que há um zilhão de respostas já, mas eu não vejo nenhuma solução prática. Claro que este é um problema real e não há uma boa razão para excluir esta syntax em Java. Como a questão 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 um monte de classs que são idênticas. Esses methods chamam um método estático que é específico da class:

 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() methods doWork() em C1 e C2 são idênticos. Pode haver muitos desses calsses: C3 C4 etc. Se o static abstract fosse 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 combinação static abstract não é permitida. No entanto, isso pode ser contornado com a construção de static class , 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(); } 

Um método estático pode ser chamado sem uma instância da class. Em seu exemplo, você pode chamar foo.bar2 (), mas não foo.bar (), porque para a barra 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 o mesmo código. No exemplo acima, mesmo se você redefinir bar2 em ImplementsFoo, uma chamada para var.bar2 () executaria foo.bar2 ().

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

Acredito ter encontrado a resposta para essa pergunta, na forma de por que os methods de uma interface (que funcionam como methods abstratos em uma class pai) não podem ser estáticos. Aqui está a resposta completa (não minha)

Basicamente, os methods estáticos podem ser ligados em tempo de compilation, já que para chamá-los você precisa especificar uma class. Isso é diferente dos methods de instância, para os quais a class da referência da qual você está chamando o método pode ser desconhecida em tempo de compilation (portanto, qual bloco de código é chamado só pode ser determinado em tempo de execução).

Se você está chamando um método estático, você já conhece a class onde ele está implementado, ou qualquer subclass direta dele. Se você definir

 abstract class Foo { abstract static void bar(); } class Foo2 { @Override static void bar() {} } 

Então qualquer Foo.bar(); chamar é obviamente ilegal, e você sempre usará Foo2.bar(); .

Com isso em mente, o único propósito de um método abstrato estático seria impor subclasss para implementar tal método. Você pode inicialmente achar que isso é MUITO errado, mas se você tiver um parâmetro de tipo genérico seria legal garantir via interface que E pode .doSomething() . Tenha em mente que, devido ao tipo de exclusão, os genéricos só existem em tempo de compilation.

Então, seria útil? Sim, e talvez seja por isso que o Java 8 está permitindo methods estáticos em interfaces (embora apenas com uma implementação padrão). Por que não usar methods estáticos abstratos com uma implementação padrão nas classs? Simplesmente porque um método abstrato com uma implementação padrão é na verdade um método concreto.

Por que não usar methods estáticos abstract / interface sem nenhuma 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).

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

Dessa forma, você poderia criar, por exemplo, uma class abstrata sortableObject ou mesmo uma interface com methods estáticos (auto) abstratos, que define os parâmetros das opções de sorting:

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

Agora você pode definir um object classificável que pode ser classificado pelos principais tipos que são os mesmos para todos esses objects:

 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 

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 hainv uma function add que, quando um tipo de sorting é selecionado, pode auto -sortar 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 a SortableList pode não ter itens ainda, mas já precisa fornecer a sorting preferida.

Cheerio, Olaf.

Primeiro, um ponto chave sobre classs abstratas – Uma class abstrata não pode ser instanciada (veja wiki ). Então, você não pode criar nenhuma instância de uma class abstrata.

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

Portanto, se você não puder instanciar uma class, essa class não poderá ter methods estáticos abstratos, já que um método abstrato implora para ser estendido.

Estrondo.

De acordo com o documento Java:

Um método estático é um método associado à class na qual ele é definido, e não a qualquer object. Cada instância da class compartilha seus methods estáticos

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

Um bom exemplo disso é:

 list.sort(ordering); 

ao invés de

 Collections.sort(list, ordering); 

Outro exemplo de uso de methods estáticos também é dado 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)); } } 

Porque ‘abstrato’ significa que o método deve ser substituído e não se pode sobrescrever methods ‘estáticos’.

Você pode fazer isso com interfaces no Java 8.

Esta é a documentação oficial sobre isso:

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

Métodos regulares podem ser abstratos quando devem ser substituídos por subclasss e fornecidos com funcionalidade. Imagine que a class Foo é estendida por Bar1, Bar2, Bar3 etc. Então, cada um terá sua própria versão da class abstrata de acordo com suas necessidades.

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

Porque abstrato é uma palavra-chave que é aplicada sobre methods abstratos não especificam um corpo. E se falamos de palavra-chave estática, ela pertence à área da class.

porque se você estiver usando algum membro estático ou variável estática na class, ele carregará no tempo de carregamento da class.

Declarar um método como static significa que podemos chamar esse método pelo seu nome de class e se essa class também é abstract , não faz sentido chamá-lo como não contém nenhum corpo e, portanto, não podemos declarar um método como static e abstract .

Porque se uma class estende uma class abstrata, então ela deve sobrescrever methods abstratos e isso é obrigatório. And since static methods are class methods resolved at compile time whereas overridden methods are instance methods resolved at runtime and following dynamic polymorphism.

Intereting Posts