¿Por qué los métodos estáticos no pueden ser abstractos en Java?


593

La pregunta es en Java ¿por qué no puedo definir un método estático abstracto? por ejemplo

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

99
Pocas razones: el método estático debe tener un cuerpo incluso si son parte de una clase abstracta porque uno no necesita crear una instancia de una clase para acceder a su método estático. Otra forma de pensar es si por un momento asumimos que está permitido, entonces el problema es que las llamadas a métodos estáticos no proporcionan ninguna información de tipo de tiempo de ejecución (RTTI), recuerde que no se requiere la creación de instancias, por lo que no pueden redirigirse a sus implementaciones específicas anuladas y, por lo tanto, permitir una estática abstarct no tiene ningún sentido. En otras palabras, no podría proporcionar ningún beneficio de polimorfismo, por lo que no está permitido.
Sactiw

66
Si tiene algo para responder la pregunta, publíquela como respuesta , no como comentario
Solomon Ucko

Respuestas:


568

Porque "abstracto" significa: "No implementa ninguna funcionalidad", y "estático" significa: "Hay funcionalidad incluso si no tiene una instancia de objeto". Y eso es una contradicción lógica.


353
Una respuesta más concisa sería 'mal diseño del lenguaje'. Estático debería significar 'pertenece a la clase' porque así es como se usa intuitivamente como lo demuestra esta misma pregunta. Ver "classmethod" en Python.
Alexander Ljungberg

12
@Tomalak Pido disculpas, no estaba claro. Por supuesto, un método estático 'pertenece a la clase'. Aún así, es solo en el sentido de que vive en el mismo espacio de nombres. Un método estático no es un método del objeto de clase en sí: no funciona con 'esto' como el objeto de clase, y no participa adecuadamente en la cadena de herencia. Si realmente fuera un método de clase abstract statictendría mucho sentido. Sería un método del propio objeto de clase que los objetos de subclase deben implementar. Por supuesto, la forma en que las cosas resuelven su respuesta es correcta a pesar de mi comprensión del idioma.
Alexander Ljungberg

695
No es una contradicción lógica, es una deficiencia del lenguaje, muchos otros idiomas admiten esta noción. "abstracto" significa "implementado en subclases", "estático" significa "ejecutado en la clase en lugar de las instancias de clase" No hay contradicción lógica.
Eric Grange

10
@Eric: Y aún así , lo que dices no se aplica a abstract static: Una función X que está "implementada en la subclase" no puede al mismo tiempo "ejecutarse en la clase", solo en la subclase . Donde entonces ya no es abstracto.
Tomalak

72
@Tomakak: Tu lógica es circular. staticno significa "no vacío", eso es solo una consecuencia de que Java no permite que los métodos estáticos sean abstractos. Significa "invocable en la clase". (Debería significar "invocable solo en la clase", pero ese es otro problema). Si Java admite abstract staticmétodos, esperaría que signifique que el método 1) debe ser implementado por subclases, y 2) es un método de clase de la subclase. Algunos métodos simplemente no tienen sentido como métodos de instancia. Desafortunadamente, Java no le permite especificar eso al crear una clase base abstracta (o una interfaz).
Michael Carman

326

Mal diseño del lenguaje. Sería mucho más efectivo llamar directamente a un método abstracto estático que crear una instancia solo por usar ese método abstracto. Especialmente cierto cuando se utiliza una clase abstracta como solución alternativa para la incapacidad de enumeración, que es otro mal ejemplo de diseño. Espero que resuelvan esas limitaciones en un próximo lanzamiento.


25
Java está lleno de limitaciones extrañas. Los cierres que acceden solo a las variables finales es otra. Y la lista restante es casi interminable. Es el trabajo de un programador de Java conocerlos y sus soluciones. Para divertirnos tenemos que usar algo mejor que Java en nuestro tiempo libre. Pero no me molestaría. Esa es la semilla para lograr el progreso.
abandono el

22
Creo que a lo que se refiere como "diseño de lenguaje pobre" es realmente más que un "diseño de lenguaje protector", cuyo propósito es limitar las violaciones del principio de OO que los programadores hacen debido a características de lenguaje innecesarias.
ethanfar

22
¿Es el concepto de "estática abstracta" una violación de los principios OO?
Trevor

77
@threed, en absoluto, pero por supuesto hay personas que dicen que el mero concepto de staticsí mismo ya es una violación ...
Pacerier

44
La necesidad de estática es una demostración clara de que los "principios de OO" no abarcan tanto como se suele afirmar.
Ben

147

No puede anular un método estático, por lo que hacerlo abstracto no tendría sentido. Además, un método estático en una clase abstracta pertenecería a esa clase, y no a la clase superior, por lo que no podría usarse de todos modos.


18
Sí, es realmente una pena que los métodos estáticos no se puedan anular en Java.
Michel

12
@Michel: ¿cuál sería el punto? Si desea un comportamiento basado en instancias, use métodos de instancias.
Ran Biron

8
Esta respuesta es incorrecta. Los métodos estáticos en clases abstractas funcionan bien y se usan comúnmente. Es solo que los métodos estáticos de la clase en sí pueden no ser abstractos. @Michel no tiene sentido anular un método estático. Sin una instancia, ¿cómo sabría el motor de ejecución qué método invocar?
erickson

63
@erickson: incluso sin una instancia, la jerarquía de clases está intacta: la herencia en métodos estáticos puede funcionar igual que la herencia de los métodos de instancia. Smalltalk lo hace, y es bastante útil.
Jared

8
@matiasg eso no es nada nuevo en absoluto. Siempre se ha permitido que las clases abstractas tengan métodos estáticos, no abstractos .
Matt Ball el

70

La abstractanotación a un método indica que el método DEBE ser anulado en una subclase.

En Java, un staticmiembro (método o campo) no puede ser anulado por subclases (esto no es necesariamente cierto en otros lenguajes orientados a objetos, vea SmallTalk). Un staticmiembro puede estar oculto , pero eso es fundamentalmente diferente de anulado .

Dado que los miembros estáticos no se pueden reemplazar en una subclase, la abstractanotación no se puede aplicar a ellos.

Por otro lado, otros lenguajes admiten herencia estática, al igual que la herencia de instancia. Desde una perspectiva de sintaxis, esos idiomas generalmente requieren que se incluya el nombre de la clase en la declaración. Por ejemplo, en Java, suponiendo que está escribiendo código en la Clase A, estas son declaraciones equivalentes (si el método A () es un método estático y no hay un método de instancia con la misma firma):

ClassA.methodA();

y

methodA();

En SmallTalk, el nombre de la clase no es opcional, por lo que la sintaxis es (tenga en cuenta que SmallTalk no usa. Para separar el "sujeto" y el "verbo", sino que lo usa como el terminador de enmienda de estado):

ClassA methodA.

Debido a que siempre se requiere el nombre de la clase, la "versión" correcta del método siempre se puede determinar atravesando la jerarquía de la clase. Por lo que vale, ocasionalmente extraño la staticherencia, y me mordió la falta de herencia estática en Java cuando comencé con ella. Además, SmallTalk es de tipo pato (y, por lo tanto, no es compatible con el programa por contrato). Por lo tanto, no tiene un abstractmodificador para los miembros de la clase.


1
"Un miembro estático no puede ser anulado por subclases" está mal. Es posible, al menos en Java6. No estoy seguro desde cuándo es el caso.
Steven De Groote

15
@Steven De Groote Un miembro estático no puede ser anulado por las subclases. Si una subclase tiene un método estático con la misma firma que un método estático en la superclase, no lo anula, lo oculta. http://docs.oracle.com/javase/tutorial/java/IandI/override.html La diferencia es que el polimorfismo funciona solo para métodos anulados, pero no para métodos ocultos.
John29

2
@ John29 Gracias por la aclaración, pero aparte de la diferencia de nombres, parece similar en uso.
Steven De Groote

2
@Steven De Groote Sí, es similar en uso, pero el comportamiento es diferente. Esa es la razón por la que no hay métodos abstractos estáticos: ¿cuál es el punto de los métodos abstractos estáticos si no admiten el polimorfismo?
John29

3
@Steven De Groote: la diferencia se hace evidente cuando se llama a ese método en la superclase. Supongamos que Super.foo llama a Super.bar. Si una subclase implementa Subclass.bar y luego llama a foo, entonces foo seguirá llamando a Super.bar, no a Subclass.bar. Por lo tanto, lo que realmente tiene son dos métodos completamente diferentes y no relacionados, ambos llamados "barra". Esto no se anula en ningún sentido útil.
Doradus

14

También hice la misma pregunta, aquí es por qué

Como dice la clase Abstract, no dará implementación y permitirá que la subclase le dé

entonces la subclase tiene que anular los métodos de la superclase,

REGLA NO 1 - Un método estático no puede ser anulado

Debido a que los miembros y métodos estáticos son elementos de tiempo de compilación, es por eso que se permite la sobrecarga (polimorfismo en tiempo de compilación) de métodos estáticos en lugar de anulación (polimorfismo de tiempo de ejecución)

Por lo tanto, no pueden ser abstractos.

No hay nada como abstracto estático <--- No permitido en Java Universe


55
-1, no es cierto que "Java no permite que se anule el método estático porque los miembros y métodos estáticos son elementos de tiempo de compilación". La verificación de tipo estática es definitivamente posible con abstract staticver stackoverflow.com/questions/370962/… . La verdadera razón por la que Java no permite que se anulen los métodos estáticos es porque Java no permite que se anulen los métodos estáticos.
Pacerier

La sobrecarga no tiene nada que ver con el polimorfismo. La sobrecarga y la anulación no tienen nada en común, excepto el prefijo "over" de la misma manera en que Java y JavaScript tienen "Java" en ellas. El nombre de un método no es lo que lo identifica, sino su firma. así foo(String)que no es lo mismo que foo(Integer)eso es todo.
Capitán Man

@CaptainMan Overloading se llama literalmente "polimorfismo paramétrico" porque, dependiendo del tipo de parámetro, se llama un método diferente que es el polimorfismo.
Davor

12

Este es un diseño de lenguaje terrible y realmente no hay razón de por qué no puede ser posible.

De hecho, aquí hay una implementación sobre cómo PUEDE hacerse en 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;
                }

        }
}

================= Viejo ejemplo a continuación =================

Busque getRequest y getRequestImpl ... se puede llamar a setInstance para alterar la implementación antes de realizar la llamada.

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

}

Utilizado de la siguiente manera:

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

     // Or

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

     // Later in the application you might use

     Core.getRequest(); 

}

66
No entendí dónde ha proporcionado un ejemplo de un abstract staticmétodo como se le preguntó en la pregunta y ha escrito en negrita SE PUEDE HACER EN JAVA . Esto es completamente equivocado.
Blip

1
No per se le permite definirlo como estático abstracto, pero puede lograr un resultado similar mediante el cual puede cambiar la implementación del método estático de s utilizando este patrón / pirateo. Apenas está equivocado. Se puede hacer, pero usando diferentes semánticas.
mmm

Este es un ejemplo de extender una clase abstracta, luego poner los métodos estáticos en el niño. Este no es un ejemplo de PUEDE HACERSE EN JAVA, de ninguna manera.
Scuba Steve

2
@ScubaSteve Primero, estás equivocado en tu conclusión. En segundo lugar, logra el mismo resultado. Lo que significa que el acceso estático a una clase puede ser cambiado por otra implementación. No es una respuesta a decir que hice la palabra clave estática abstractable, pero usando este patrón puede usar métodos estáticos y aún así cambiar su implementación. Sin embargo, tiene el efecto negativo de ser global, pero para un entorno de prueba / producción / desarrollo, es el truco para nosotros.
mmm

5
  • Un método abstracto se define solo para que pueda ser anulado en una subclase. Sin embargo, los métodos estáticos no se pueden anular. Por lo tanto, es un error en tiempo de compilación tener un método abstracto y estático.

    Ahora la siguiente pregunta es ¿por qué los métodos estáticos no se pueden anular?

  • Es porque los métodos estáticos pertenecen a una clase particular y no a su instancia. Si intenta anular un método estático, no obtendrá ningún error de compilación o tiempo de ejecución, pero el compilador simplemente ocultará el método estático de la superclase.


4

Un método estático, por definición, no necesita saberlo this. Por lo tanto, no puede ser un método virtual (que se sobrecarga de acuerdo con la información de subclase dinámica disponible a través de this); en cambio, la sobrecarga de un método estático se basa únicamente en la información disponible en el momento de la compilación (esto significa: una vez que hace referencia a un método estático de superclase, llama al método de superclase, pero nunca a un método de subclase).

De acuerdo con esto, los métodos estáticos abstractos serían bastante inútiles porque nunca se sustituirá su referencia por algún cuerpo definido.


4

Veo que ya hay un millón de respuestas, pero no veo ninguna solución práctica. Por supuesto, este es un problema real y no hay una buena razón para excluir esta sintaxis en Java. Como la pregunta original carece de un contexto en el que esto pueda ser necesario, proporciono tanto un contexto como una solución:

Suponga que tiene un método estático en un grupo de clases que son idénticas. Estos métodos llaman a un método estático que es específico de la clase:

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()Los métodos C1y C2son idénticos. Puede haber muchas de estas clases: C3 C4etc. Si static abstractse permitiera, eliminaría el código duplicado haciendo 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
    }
}

pero esto no se compilaría porque la static abstractcombinación no está permitida. Sin embargo, esto se puede evitar con la static classconstrucción, que está 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();
    }
}

Con esta solución, el único código que se duplica es

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

1
Dado que en su solución final, la clase abstracta C no tiene ningún método estático, ¿por qué no dejar que C1 y C2 lo extiendan y anular el método doMoreWork () y dejar que cualquier otra clase haga su instancia y llame a los métodos necesarios. Básicamente está haciendo lo mismo, es decir, extendiendo la clase C usando una clase anónima y luego en C1 y C2 usando su instancia estática para permitir el acceso desde un método estático, pero esto no es obligatorio en absoluto.
Sactiw

No entiendo el contexto que has proporcionado aquí. En su solución final, lo que puede hacer es llamar C1.doWork()o C2.doWork()Pero no puede llamar C.doWork(). También en el ejemplo que ha proporcionado, que no funcionará, suponga que si estuviera permitido, ¿cómo Cencontrará la implementación la clase doMoreWork()? Finalmente, llamaría a su código de contexto un mal diseño. ¿Por qué? simplemente porque ha creado una función separada para el código que es única en lugar de crear una función para el código que es común y luego implementar una función estática en la clase C. ¡Esto es más fácil!
Blip

2

Suponga que hay dos clases, Parenty Child. Parentes abstract. Las declaraciones son las siguientes:

abstract class Parent {
    abstract void run();
}

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

Esto significa que cualquier instancia de Parentdebe especificar cómo run()se ejecuta.

Sin embargo, suponga que ahora Parentno lo es abstract.

class Parent {
    static void run() {}
}

Esto significa que Parent.run()ejecutará el método estático.

La definición de un abstractmétodo es "Un método que se declara pero no se implementa", lo que significa que no devuelve nada por sí mismo.

La definición de un staticmétodo es "Un método que devuelve el mismo valor para los mismos parámetros, independientemente de la instancia en la que se llame".

El abstractvalor de retorno de un método cambiará a medida que cambie la instancia. Un staticmétodo no lo hará. Un static abstractmétodo es más o menos un método donde el valor de retorno es constante, pero no devuelve nada. Esta es una contradicción lógica.

Además, realmente no hay muchas razones para un static abstractmétodo.


2

Una clase abstracta no puede tener un método estático porque la abstracción se realiza para lograr la VINCULACIÓN DINÁMICA mientras que los métodos estáticos están vinculados estáticamente a su funcionalidad. Un método estático significa comportamiento que no depende de una variable de instancia, por lo que no se requiere instancia / objeto. Solo la clase. Los métodos estáticos pertenecen a la clase y no al objeto. Se almacenan en un área de memoria conocida como PERMGEN desde donde se comparte con cada objeto. Los métodos en la clase abstracta están vinculados dinámicamente a su funcionalidad.


1
Las clases abstractas seguramente pueden tener métodos estáticos. Pero no métodos abstractos estáticos.
JacksOnF1re

2

Declarar un método como staticsignifica que podemos llamar a ese método por su nombre de clase y si esa clase también lo es abstract, no tiene sentido llamarlo ya que no contiene ningún cuerpo, y por lo tanto no podemos declarar un método como staticy abstract.


2

Como los métodos abstractos pertenecen a la clase y no pueden ser anulados por la clase implementadora. Incluso si hay un método estático con la misma firma, oculta el método, no lo anula. Por lo tanto, es irrelevante declarar el método abstracto como estático, ya que nunca obtendrá el cuerpo. Por lo tanto, error de tiempo de compilación.


1

Se puede llamar a un método estático sin una instancia de la clase. En su ejemplo, puede llamar a foo.bar2 (), pero no a foo.bar (), porque para la barra necesita una instancia. El siguiente código funcionaría:

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

Si llama a un método estático, se ejecutará siempre el mismo código. En el ejemplo anterior, incluso si redefine bar2 en ImplementsFoo, una llamada a var.bar2 () ejecutaría foo.bar2 ().

Si bar2 ahora no tiene implementación (eso es lo que significa abstracto), puede llamar a un método sin implementación. Eso es muy dañino.


1
Y podría llamarse a un método estático abstracto sin una instancia, pero requeriría que se creara una implementación en la clase secundaria. No es exactamente polimorfismo, pero la única forma de evitarlo es hacer que el niño concreto implemente una interfaz que "requiere" el método "abstracto estático". Desordenado, pero viable.
fijiaaron el

3
En realidad, estaba equivocado. Tampoco puede tener métodos estáticos en una interfaz. Defecto del lenguaje.
fijiaaron el

1

Creo que he encontrado la respuesta a esta pregunta, en forma de por qué los métodos de una interfaz (que funcionan como métodos abstractos en una clase principal) no pueden ser estáticos. Aquí está la respuesta completa (no la mía)

Básicamente, los métodos estáticos pueden vincularse en tiempo de compilación, ya que para llamarlos debe especificar una clase. Esto es diferente a los métodos de instancia, para los cuales la clase de la referencia desde la que está llamando al método puede ser desconocida en el momento de la compilación (por lo tanto, qué bloque de código se llama solo se puede determinar en tiempo de ejecución).

Si está llamando a un método estático, ya conoce la clase donde se implementa, o cualquier subclase directa de la misma. Si usted define

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

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

Entonces, cualquier Foo.bar();llamada es obviamente ilegal, y siempre la usará Foo2.bar();.

Con esto en mente, el único propósito de un método abstracto estático sería imponer subclases para implementar dicho método. Inicialmente, podría pensar que esto es MUY incorrecto, pero si tiene un parámetro de tipo genérico <E extends MySuperClass>, sería bueno garantizarlo a través de la interfaz que Epuede .doSomething(). Tenga en cuenta que debido al tipo de borrado, los genéricos solo existen en el momento de la compilación.

Entonces, ¿sería útil? Sí, y tal vez por eso Java 8 permite métodos estáticos en las interfaces (aunque solo con una implementación predeterminada). ¿Por qué no abstraer métodos estáticos con una implementación predeterminada en las clases? Simplemente porque un método abstracto con una implementación predeterminada es en realidad un método concreto.

¿Por qué no los métodos estáticos abstractos / de interfaz sin implementación predeterminada? Aparentemente, simplemente por la forma en que Java identifica qué bloque de código tiene que ejecutar (primera parte de mi respuesta).


1

Debido a que la clase abstracta es un concepto OOPS y los miembros estáticos no son parte de OOPS ...
Ahora, podemos declarar métodos completos estáticos en la interfaz y podemos ejecutar la interfaz declarando el método principal dentro de una interfaz

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

0

La idea de tener un método estático abstracto sería que no puede usar esa clase abstracta en particular directamente para ese método, pero solo la primera derivada podría implementar ese método estático (o para genéricos: la clase real del genérico que utilizar).

De esa manera, podría crear, por ejemplo, una clase abstracta de objeto sortable o incluso una interfaz con métodos estáticos (auto) abstractos, que definen los parámetros de las opciones de clasificación:

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

Ahora puede definir un objeto ordenable que se pueda ordenar por los tipos principales que son iguales para todos estos 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
    }
}

Ahora puedes crear un

public class SortableList<T extends SortableObject> 

que puede recuperar los tipos, crear un menú emergente para seleccionar un tipo para ordenar y recurrir a la lista obteniendo los datos de ese tipo, así como tener una función de agregar que, cuando se ha seleccionado un tipo de clasificación, puede auto -ordenar nuevos elementos. Tenga en cuenta que la instancia de SortableList puede acceder directamente al método estático de "T":

String [] MenuItems = T.getSortableTypes();

El problema con tener que usar una instancia es que SortableList puede no tener elementos todavía, pero ya necesita proporcionar la clasificación preferida.

Cheerio, Olaf.


0

Primero, un punto clave sobre las clases abstractas: una clase abstracta no se puede instanciar (ver wiki ). Por lo tanto, no puede crear ninguna instancia de una clase abstracta.

Ahora, la forma en que java trata los métodos estáticos es compartiendo el método con todas las instancias de esa clase.

Entonces, si no puede crear una instancia de una clase, esa clase no puede tener métodos estáticos abstractos ya que un método abstracto pide que se extienda.

Auge.


Cada método en una clase abstracta necesita que su clase se extienda de todos modos para ejecutarse, por lo que esto no es una excusa. Puede extender la clase abstracta (al mismo tiempo, implementando el método abstracto). Entonces esto no funciona como una explicación.
Pere

0

Según el documento de Java :

Un método estático es un método asociado con la clase en la que se define en lugar de con cualquier objeto. Cada instancia de la clase comparte sus métodos estáticos.

En Java 8, junto con los métodos predeterminados, también se permiten métodos estáticos en una interfaz. Esto nos facilita la organización de métodos auxiliares en nuestras bibliotecas. Podemos mantener métodos estáticos específicos para una interfaz en la misma interfaz en lugar de en una clase separada.

Un buen ejemplo de esto es:

list.sort(ordering);

en vez de

Collections.sort(list, ordering);

Otro ejemplo de uso de métodos estáticos también se da en el propio 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

Porque 'abstracto' significa que el método debe ser anulado y uno no puede anular los métodos 'estáticos'.


Esta respuesta no agrega nada que las respuestas anteriores aún no hayan abordado.
MarsAtomic

@MarsAtomic Creo que es más apropiado que la respuesta más votada. Además, es sucinto.
Praveen Kumar

Luego puede editar las respuestas anteriores para mejorarlas cuando tenga suficiente representante. Todo lo que está haciendo es agregar ruido a la señal creando respuestas duplicadas. Siga las reglas y costumbres establecidas de Stack Overflow en lugar de crear las suyas propias y esperar que todos los demás las sigan.
MarsAtomic

No estoy de acuerdo, por favor compare mi respuesta con otra, especialmente la respuesta más votada.
Praveen Kumar

"¿Por qué no puedo hacer esto?" Respuesta: "porque no puedes".
JacksOnF1re

0

Los métodos regulares pueden ser abstractos cuando están destinados a ser anulados por subclases y provistos de funcionalidad. Imagina que la clase Foose extiende porBar1, Bar2, Bar3 etc. Por lo tanto, cada uno tendrá su propia versión de la clase abstracta de acuerdo con sus necesidades.

Ahora, los métodos estáticos, por definición, pertenecen a la clase, no tienen nada que ver con los objetos de la clase o los objetos de sus subclases. Ni siquiera necesitan que existan, se pueden usar sin crear instancias de las clases. Por lo tanto, deben estar listos y no pueden depender de las subclases para agregarles funcionalidad.


0

Debido a que abstract es una palabra clave que se aplica sobre los métodos Abstract, no se especifica un cuerpo. Y si hablamos de palabras clave estáticas, pertenece al área de clase.


por favor sea un poco elaborado acerca de su respuesta.
Blip

0

porque si está utilizando algún miembro estático o variable estática en la clase, se cargará en el momento de carga de la clase.


3
¿Y por qué sería un problema?
EIS

-1

Puede hacer esto con interfaces en Java 8.

Esta es la documentación oficial al respecto:

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


2
¿Cómo? Busqué soluciones y no pude encontrar ninguna.
thouliha

Wut? No se puede. Todos los métodos de interfaces estáticas deben invocarse utilizando la clase de interfaz.
mmm

8
Esta respuesta es incorrecta y es errónea para las personas nuevas en Java. Esto lo hace para mostrar algún ejemplo de método estático abstracta, ya que no puede ser implementado y ha dicho en otras respuestas
Blip

-1

Porque si una clase extiende una clase abstracta, tiene que anular los métodos abstractos y eso es obligatorio. Y dado que los métodos estáticos son métodos de clase resueltos en tiempo de compilación, mientras que los métodos anulados son métodos de instancia resueltos en tiempo de ejecución y siguiendo un polimorfismo dinámico.


Por favor capitaliza y puntúa este desastre.
Marqués de Lorne
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.