¿Por qué llamar a un método estático a través de una instancia no es un error para el compilador de Java?

Resuelto tmtest asked hace 15 años • 12 respuestas

Estoy seguro de que todos conocen el comportamiento al que me refiero: códigos como:

Thread thread = new Thread();
int activeCount = thread.activeCount();

provoca una advertencia del compilador. ¿Por qué no es un error?

EDITAR:

Para ser claros: la pregunta no tiene nada que ver con Threads. Me doy cuenta de que a menudo se dan ejemplos de hilos cuando se habla de esto debido a la posibilidad de que realmente se estropeen las cosas. Pero en realidad el problema es que ese uso siempre es una tontería y no se puede (de manera competente) escribir tal llamada y decirlo en serio. Cualquier ejemplo de este tipo de llamada a un método sería una locura. Aquí está otro:

String hello = "hello";
String number123AsString = hello.valueOf(123);

Lo que hace que parezca que cada instancia de String viene con un método "String valueOf(int i)".

tmtest avatar Mar 04 '09 20:03 tmtest
Aceptado

Básicamente, creo que los diseñadores de Java cometieron un error cuando diseñaron el lenguaje y es demasiado tarde para solucionarlo debido a los problemas de compatibilidad involucrados. Sí, puede dar lugar a un código muy engañoso. Sí, deberías evitarlo. Sí, debes asegurarte de que tu IDE esté configurado para tratarlo como un error, en mi opinión. Si alguna vez diseñas un lenguaje tú mismo, tenlo en cuenta como ejemplo del tipo de cosas que debes evitar :)

Sólo para responder al punto de DJClayworth, esto es lo que está permitido en C#:

public class Foo
{
    public static void Bar()
    {
    }
}

public class Abc
{
    public void Test()
    {
        // Static methods in the same class and base classes
        // (and outer classes) are available, with no
        // qualification
        Def();

        // Static methods in other classes are available via
        // the class name
        Foo.Bar();

        Abc abc = new Abc();

        // This would *not* be legal. It being legal has no benefit,
        // and just allows misleading code
        // abc.Def();
    }

    public static void Def()
    {
    }
}

¿Por qué creo que es engañoso? Porque si miro el código someVariable.SomeMethod()espero que use el valor desomeVariable . Si SomeMethod()es un método estático, esa expectativa no es válida; el código me está engañando. ¿Cómo puede ser eso algo bueno ?

Por extraño que parezca, Java no le permitirá utilizar una variable potencialmente no inicializada para llamar a un método estático, a pesar de que la única información que utilizará es el tipo declarado de la variable. Es un desastre inconsistente e inútil. ¿Por qué permitirlo?

EDITAR: Esta edición es una respuesta a la respuesta de Clayton, que afirma que permite la herencia de métodos estáticos. No es así. Los métodos estáticos simplemente no son polimórficos. Aquí hay un programa breve pero completo para demostrarlo:

class Base
{
    static void foo()
    {
        System.out.println("Base.foo()");
    }
}

class Derived extends Base
{
    static void foo()
    {
        System.out.println("Derived.foo()");
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Base b = new Derived();
        b.foo(); // Prints "Base.foo()"
        b = null;
        b.foo(); // Still prints "Base.foo()"
    }
}

Como puede ver, el valor del tiempo de ejecución bse ignora por completo.

Jon Skeet avatar Mar 04 '2009 13:03 Jon Skeet

¿Por qué debería ser un error? La instancia tiene acceso a todos los métodos estáticos. Los métodos estáticos no pueden cambiar el estado de la instancia (intentar hacerlo es un error de compilación).

El problema con el conocido ejemplo que usted da es muy específico de los subprocesos , no de las llamadas a métodos estáticos. Parece que estás obteniendo el activeCount()hilo al que hace referencia thread, pero en realidad estás obteniendo el recuento del hilo que llama. Este es un error lógico que usted, como programador, está cometiendo. Emitir una advertencia es lo apropiado que debe hacer el compilador en este caso. Depende de usted prestar atención a la advertencia y corregir su código.

EDITAR: Me doy cuenta de que la sintaxis del lenguaje es lo que te permite escribir código engañoso, pero recuerda que el compilador y sus advertencias también son parte del lenguaje. El lenguaje le permite hacer algo que el compilador considera dudoso, pero le advierte para asegurarse de que está consciente de que podría causar problemas.

Bill the Lizard avatar Mar 04 '2009 13:03 Bill the Lizard