studio solucion programacion para móviles edición dinamicamente desarrollo curso crear clases aplicaciones java static methods

java - solucion - manual de programacion android pdf



¿Por qué no se está llamando a un método estático a través de una instancia un error para el compilador de Java? (11)

¿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 (intentarlo es un error de compilación).

El problema con el conocido ejemplo que das es muy específico para los hilos , no para las llamadas a métodos estáticos. Parece que está obteniendo activeCount() para el subproceso referido por thread , pero realmente está obteniendo el recuento del subproceso de llamada. Este es un error lógico que usted como programador está haciendo. Emitir una advertencia es lo apropiado para 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 un código engañoso, pero recuerda que el compilador y sus advertencias también forman parte del lenguaje. El lenguaje le permite hacer algo que el compilador considera dudoso, pero le da la advertencia para asegurarse de que sabe que podría causar problemas.

Estoy seguro de que todos ustedes conocen el comportamiento que quiero decir, código como:

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

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

EDITAR:

Para ser claro: la pregunta no tiene nada que ver con los hilos. Me doy cuenta de que a menudo se dan ejemplos de subprocesos al discutir esto debido a la posibilidad de realmente ensuciar las cosas con ellos. Pero realmente el problema es que ese uso siempre es una tontería y no puedes (competentemente) escribir tal llamada y decirlo en serio. Cualquier ejemplo de este tipo de llamada de método sería estúpido. Aquí está otro:

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

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


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 implicados. Sí, puede conducir a un código muy engañoso. Sí, debes evitarlo. Sí, debe asegurarse de que su IDE esté configurado para tratarlo como un error, IMO. Si alguna vez diseñas un idioma, tenlo en cuenta como un ejemplo del tipo de cosas que debes evitar :)

Solo 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 de someVariable . 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 ?

Curiosamente, Java no le permitirá usar una variable potencialmente no inicializada para llamar a un método estático, a pesar de que la única información que va a utilizar es el tipo declarado de la variable. Es un desastre incoherente 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 demostrar que:

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 de b se ignora por completo.


El propósito de la referencia de variable de instancia es solo proporcionar el tipo que incluye la estática. Si observa el código de bytes que invoca una instancia estática vía instance.staticMethod o EnclosingClass.staticMethod produce el mismo bytecode de método estático de invocación. No aparece ninguna referencia a la instancia.

La respuesta también es por qué está ahí, bueno, así es. Mientras uses la clase. y no a través de una instancia, ayudará a evitar confusiones en el futuro.


Lo realmente importante, desde la perspectiva del compilador, es que sea capaz de resolver símbolos. En el caso de un método estático, necesita saber qué clase buscar, ya que no está asociado a ningún objeto en particular. Los diseñadores de Java obviamente decidieron que dado que podían determinar la clase de un objeto, también podían resolver la clase de cualquier método estático para ese objeto desde cualquier instancia del objeto. Eligen permitir esto - influenciado, tal vez, por la observación de @TofuBeer - para darle al programador cierta conveniencia. Otros diseñadores de idiomas han tomado diferentes decisiones. Probablemente habría caído en el último campamento, pero no es tan importante para mí. Probablemente permitiría el uso que menciona @TofuBeer, pero habiéndolo permitido mi posición de no permitir el acceso desde una variable de instancia es menos defendible.


No es un error porque es parte de la especificación, pero obviamente está preguntando sobre la lógica, que todos podemos adivinar.

Mi suposición es que la fuente de esto es realmente permitir que un método en una clase invoque un método estático en la misma clase sin la molestia. Como llamar a x () es legal (incluso sin el nombre de la propia clase), llamar a this.x () debería ser legal también, y por lo tanto, llamar a través de cualquier objeto también se hizo legal.

Esto también ayuda a alentar a los usuarios a convertir las funciones privadas en estáticas si no cambian el estado.

Además, los compiladores generalmente intentan evitar la declaración de errores cuando no hay forma de que esto pueda generar un error directo. Como un método estático no cambia el estado ni se preocupa por el objeto invocado, no causa un error real (solo confusión) para permitir esto. Una advertencia es suficiente.


No hay opción para eso. En java (como muchas otras lenguas) puede tener acceso a todos los miembros estáticos de una clase a través de su nombre de clase o instancia de la clase. Depende de usted y de su caso y la solución de software que debe usar que le brinde más legibilidad.


Probablemente por la misma lógica que hace que esto no sea un error:

public class X { public static void foo() { } public void bar() { foo(); // no need to do X.foo(); } }


Probablemente puede cambiarlo en su IDE (en Preferencias de Eclipse -> Java -> Compilador -> Errores / Advertencias)


Respuesta corta: el idioma lo permite, así que no es un error.


Solo considero esto:

instanceVar.staticMethod();

para ser una abreviatura de esto:

instanceVar.getClass().staticMethod();

Si siempre tuvieras que hacer esto:

SomeClass.staticMethod();

entonces no sería capaz de aprovechar la herencia de los métodos estáticos.

Es decir, llamando al método estático a través de la instancia no necesita saber qué clase concreta es la instancia en tiempo de compilación, solo que implementa staticMethod () en algún lugar a lo largo de la cadena de herencia.

EDITAR: Esta respuesta es incorrecta. Ver comentarios para más detalles.


Ya no pueden convertirlo en un error, debido a todo el código que ya existe.

Estoy contigo en eso debería ser un error. Tal vez debería haber una opción / perfil para que el compilador actualice algunas advertencias a errores.

Actualización: cuando introdujeron la palabra clave assert en 1.4, que tiene problemas de compatibilidad potenciales similares con el código anterior, solo la pusieron a disposición si configura explícitamente el modo fuente en "1.4" . Supongo que uno podría convertirlo en un error en un nuevo modo fuente "java 7". Pero dudo que lo hagan, teniendo en cuenta que todos los problemas que causaría. Como han señalado otros, no es estrictamente necesario evitar que escriba un código confuso. Y los cambios de lenguaje en Java deberían limitarse a lo estrictamente necesario en este punto.