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


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

517
2017-12-16 10:45


origen


Respuestas:


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


507
2017-12-16 10:50



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


273
2017-10-20 14:27



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.


136
2017-12-16 10:48



los abstract la anotación a un método indica que el método DEBE ser anulado en una subclase.

En Java, un static miembro (método o campo) no puede ser reemplazado por subclases (esto no es necesariamente cierto en otros lenguajes orientados a objetos, consulte SmallTalk). A static miembro puede ser oculto, pero eso es fundamentalmente diferente de anulado.

Como los miembros estáticos no se pueden anular en una subclase, el abstract la anotación no se puede aplicar a ellos.

Como comentario aparte, otros lenguajes admiten herencia estática, al igual que la herencia de instancias. Desde una perspectiva de sintaxis, esos lenguajes generalmente requieren que el nombre de la clase se incluya en la declaración. Por ejemplo, en Java, suponiendo que está escribiendo código en Clase A, estas son declaraciones equivalentes (si methodA () es un método estático, y no hay ningún 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 el símbolo. Para separar el "sujeto" y el "verbo", sino que lo usa como el terminador de enmendar):

ClassA methodA.

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


63
2017-12-16 20:17



También hice la misma pregunta, aquí está el porqué

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

entonces Subclass tiene que anular los métodos de Superclass,

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 de tiempo de compilación) de los métodos estáticos en lugar de anulación (polimorfismo en tiempo de ejecución)

Entonces, ellos no pueden ser abstractos

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


14
2018-05-15 07:13



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

        }
}

================= Ejemplo anterior a continuación =================

Busque getRequest y getRequestImpl ... setInstance se puede llamar para modificar 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();
        }
    }       






}

9
2018-03-19 16:54



  • Un método abstracto se define solo para que pueda ser anulado en una subclase. Sin embargo, los métodos estáticos no pueden ser anulados. 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 pueden ser anulados?

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


5
2018-06-14 21:11



Supongamos que hay dos clases, Parent y Child. Parent es abstract. Las declaraciones son las siguientes:

abstract class Parent {
    abstract void run();
}

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

Esto significa que cualquier instancia de Parent debe especificar cómo run() es ejecutado.

Sin embargo, asuma ahora que Parent no es abstract.

class Parent {
    static void run() {}
}

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

La definición de un abstract mé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 static método es "Un método que devuelve el mismo valor para los mismos parámetros, independientemente de la instancia a la que se llama".

Un abstract El valor de retorno del método cambiará a medida que la instancia cambie. UN static método no lo hará. UN static abstract mé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 static abstract método.


2
2017-07-17 16:12



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 hay instancia / objeto es obligatorio. 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.


2
2017-12-05 13:16



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

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


2
2018-01-20 13:02



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. Dado que la pregunta original carece de un contexto donde esto pueda ser necesario, proporciono tanto un contexto como una solución:

Supongamos 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 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() métodos en C1 y C2 Son identicos. Puede haber muchos de estos calsses: C3  C4 etc. Si static abstract estaba permitido, eliminarías 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 compilaría porque static abstract la combinación no está permitida Sin embargo, esto se puede eludir con static class construir, que está permitido:

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

2
2017-12-16 11:11