431 votos

¿Por qué no puedo definir un método estático en una interfaz Java?

Aquí está el ejemplo:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

Por supuesto, esto no funcionará. Pero, ¿por qué no?

Uno de los posibles problemas sería, ¿qué sucede cuando usted llama:

IXMLizable.newInstanceFromXML(e);

En este caso, creo que sólo debe llamar a un método vacío (es decir. {}). Todas las subclases se vería obligado a aplicar el método estático, por lo que había de todos a estar bien cuando se llama al método estático. Entonces, ¿por qué no es posible?

EDIT: supongo que estoy buscando la respuesta que más profundo que el "porque esa es la manera en que Java es".

Hay una en particular tecnológico razón por la que los métodos estáticos no puede ser sobreescrito? Es decir, ¿por qué los diseñadores de Java decide hacer métodos de instancia overrideable pero no los métodos estáticos?

EDIT: El problema con mi diseño es que estoy tratando de utilizar interfaces para hacer cumplir una convención de codificación.

Es decir, el objetivo de la interfaz es doble:

  1. Quiero que el IXMLizable interfaz que me permita convertir las clases que implementan a los elementos XML (utilización de polimorfismo, funciona bien).

  2. Si alguien quiere hacer una nueva instancia de una clase que implementa la IXMLizable interfaz, siempre van a saber que habrá un newInstanceFromXML(Elemento e) constructor estático.

¿Hay alguna otra manera para asegurar esto, otros que simplemente poner un comentario en la interfaz?

462voto

erickson Puntos 127945

Hay dos cuestiones aquí:

  1. ¿Por qué no puede interfaces contienen métodos estáticos?
  2. ¿Por qué no puede métodos estáticos ser reemplazado?

No hay ninguna razón técnica por la que una interfaz no podría apoyar a métodos estáticos. Esto se resume muy bien el cartel de la pregunta que duplicado. Uno de los comentarios que he dejado allí hace hincapié en este punto. En fin, creo que esto fue sólo una opción por el lenguaje de los diseñadores. Este hecho podría ser considerado como un pequeño cambio de idioma. [Actualización: Una propuesta oficial fue hecha para agregar métodos estáticos para interfaces en Java 7,] y fue inicialmente programado para la inclusión, pero más tarde fue abandonado debido a complicaciones inesperadas.

Actualización: De hecho, en Java 8, las interfaces pueden tener métodos estáticos, así como invalidar-capaz de métodos con una implementación predeterminada. Que todavía no se puede tener campos de instancia, aunque. Estas características son parte de la expresión lambda de apoyo, y usted puede leer más acerca de ellos en la Parte H de JSR 335.

La respuesta a la segunda pregunta es un poco más complicado.

Los métodos estáticos son resolubles en tiempo de compilación. Envío dinámico, tiene sentido que los métodos de instancia, en el que el compilador no puede determinar el tipo concreto de objeto, y, por lo tanto, no puede resolver el método a invocar. Pero la invocación de un método estático requiere una clase, y puesto que la clase es conocido en tiempo de compilación, distribución dinámica es innecesario.

Un poco de historia acerca de cómo los métodos de instancia de trabajo es necesaria para entender lo que está pasando aquí. Estoy seguro de que la implementación actual es muy diferente, pero déjenme explicar mi concepto de método de envío, que los modelos de comportamiento observado con precisión.

Pretender que cada clase tiene una tabla hash que los mapas de las firmas de método (nombre y tipo de parámetros) a una porción de código para implementar el método. Cuando la máquina virtual se intenta invocar a un método de una instancia, se obtiene de la clase del objeto, y busca la solicita firma en la clase de la tabla. Si un método cuerpo es encontrado, se la invoca. De lo contrario, la clase principal de la clase es obtenido, y la búsqueda se repite allí. Esto continúa hasta que el método se encuentra, o no hay más clases para los padres-lo que se traduce en un NoSuchMethodError.

Si un super clase y una clase sub ambos tienen una entrada en sus tablas por el mismo método de firma, de la sub clase con la versión que se encuentra en primer lugar, y a la súper clase de la versión nunca utilizada-este es un "override".

Ahora, supongamos que saltar la instancia de objeto, y acaba de empezar con una subclase. La resolución puede proceder como en el anterior, dándole una especie de "overridable" método estático. Sin embargo, ya que el compilador es a partir de una clase se conoce en tiempo de compilación, en lugar de un objeto de tipo desconocido pasó en tiempo de ejecución, la resolución puede ocurrir en tiempo de compilación. No hay ningún punto en la "imperiosa" de un método estático, ya que uno siempre puede especificar la clase que contiene la versión deseada.


Aquí un poco más de material para la dirección de la reciente edición de la pregunta.

Parece que quieres eficazmente el mandato de un constructor-como método para cada aplicación de IXMLizable. Olvídese de hacer cumplir esto con una interfaz de un minuto, y pretender que tienen algunas clases que cumplan con este requisito. ¿Cómo se utiliza?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

Puesto que usted tiene explícitamente el nombre de la tipo concreto, Foo cuando "construir" el nuevo objeto, el compilador puede verificar que de hecho tienen la necesaria método de fábrica. Y si no, entonces, ¿qué? Si puedo implementar un IXMLizable que carece de la "constructor", y puedo crear una instancia y se pasa a su código, que es un IXMLizable de todos los recursos de la interfaz.

La construcción es parte de la aplicación, no de la interfaz. Cualquier código que funciona con éxito con la interfaz a la que no le importa el constructor. Cualquier código que se preocupa por el constructor necesita saber el tipo concreto de todos modos, y la interfaz puede ser ignorado.

43voto

DJClayworth Puntos 11288

Esto ya fue preguntado y respondido, aquí

Para duplicar mi respuesta:

Nunca hay un punto de la declaración de un método estático en una interfaz. No pueden ser ejecutadas por la llamada normal MyInterface.staticMethod(). Si se le llame por la especificación de la clase de implementación MyImplementor.staticMethod() entonces usted debe saber que la clase, por lo que es irrelevante si la interfaz contiene o no.

Lo que es más importante, los métodos estáticos son nunca anulados, y si tratas de hacer:

MyInterface var = new MyImplementingClass();
var.staticMethod();

las reglas para la estática decir que el método definido en el tipo declarado de var debe ser ejecutado. Ya que esta es una interfaz, esto es imposible.

La razón por la que no se puede ejecutar "resultado=MyInterface.staticMethod()" es que tendría que ejecutar la versión del método que se define en Miinterfaz. Pero no puede haber una versión definida en Miinterfaz, porque es una interfaz. No tiene código, por definición.

Mientras que usted puede decir que esto equivale a "ya que Java lo hace de esa manera", en realidad, la decisión es una consecuencia lógica de otras decisiones de diseño, también por una muy buena razón.

34voto

Peter Lawrey Puntos 229686

Normalmente esto se hace usando un patrón de fábrica

 public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}
 

19voto

Michael Myers Puntos 82361

Como los métodos estáticos no pueden sustituirse en subclases, y por lo tanto no pueden ser abstractas. Y todos los métodos en una interfaz son, de facto, abstracto.

5voto

cliff.meyers Puntos 10394

Interfaces tienen que ver con el polimorfismo que está intrínsecamente ligada a instancias de objetos, no clases. Por lo tanto estática no tiene sentido en el contexto de una interfaz.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X