2008-08-22 11 views
142

El tema dice más: ¿cuál es el motivo por el que los métodos estáticos no se pueden declarar en una interfaz?¿Por qué no puedo declarar métodos estáticos en una interfaz?

public interface ITest { 
    public static String test(); 
} 

El código anterior me da el siguiente error (en Eclipse, por lo menos): "modificador ilegal por el método de interfaz ITest.test(); solamente pública & abstracta se permiten".

+2

favor inaceptables desde la respuesta de Espo, ya que está viciado. Una interfaz tiene un archivo de clase que podría contener la implementación de un método estático (si el diseñador de Java lo permitiera), por lo que no hay problema para resolver la implementación del método estático. Funciona exactamente como con otras clases estáticas. – Mnementh

+0

estoy de acuerdo con la respuesta dada por "erickson" http://stackoverflow.com/questions/512877/why-cant-i-define-a-static-method-in-a-java-interface – Maverick

+8

This estará disponible en Java 8 por cierto. – m0skit0

Respuesta

78

Hay algunos problemas en juego aquí. El primero es el problema de declarar un método estático sin definirlo.Esta es la diferencia entre

public interface Foo { 
    public static int bar(); 
} 

y

public interface Foo { 
    public static int bar() { 
    ... 
    } 
} 

La primera es imposible por las razones que Espo menciones: usted no sabe lo que la implementación de la clase es la definición correcta.

Java podría permitir esto último; y de hecho, comenzando en Java 8, ¡sí!

+2

Sí, es idealógico, no técnico. La razón por la que me gustaría es que uno puede tener un método de "implementación" estático en una interfaz que solo hace referencia a otros métodos de "interfaz" en la interfaz que pueden reutilizarse fácilmente implementando clases. Pero uno puede declarar una * clase * estática en una interfaz así que uno podría tener tales cosas residir allí como MyInterface.Impl.doIt (MyInterface i, Object [] args) {...} – peterk

+9

Desde Java 8, puede definir 'static 'métodos en una' interfaz'. Los métodos deben ser 'públicos'. –

+4

@ OlivierGrégoire ... y no son heredados, lo cual es clave. –

7

Los métodos estáticos no son métodos de instancia. No hay contexto de instancia, por lo tanto, implementarlo desde la interfaz tiene poco sentido.

20

Voy a responder a su pregunta con un ejemplo. Supongamos que tenemos una clase de Matemáticas con un método estático add. Se podría llamar a este método así:

Math.add(2, 3); 

Si la matemáticas eran una interfaz en lugar de una clase, que no podía tener funciones definidas. Como tal, decir algo como Math.add (2, 3) no tiene sentido.

40

La razón por la que no puede tener un método estático en una interfaz reside en la forma en que Java resuelve las referencias estáticas. Java no se molestará en buscar una instancia de una clase cuando intente ejecutar un método estático. Esto se debe a que los métodos estáticos no dependen de la instancia y, por lo tanto, se pueden ejecutar directamente desde el archivo de clase. Dado que todos los métodos en una interfaz son abstractos, la VM debería buscar una implementación particular de la interfaz para encontrar el código detrás del método estático para que pueda ser ejecutado. Esto contradice la forma en que funciona la resolución de métodos estáticos e introduciría una incoherencia en el lenguaje.

+3

Esta explicación no explica el problema. Cada interfaz tiene su propio archivo de clase, podría contener el método estático. Por lo tanto, no se necesita buscar una implementación en particular. – Mnementh

+0

No todos los tipos de interfaz en Java están dentro de su propio archivo, ni deben estar de acuerdo con JLS. Además, JLS no estipula que las clases deben almacenarse siempre dentro de un sistema de archivos, sino todo lo contrario. –

+3

@Totophil: Las interfaces no deben estar en un solo archivo java, pero tendrán un propio archivo de clase después de la compilación. Eso es lo que escribí. – Mnementh

2

Una interfaz se utiliza para el polimorfismo, que se aplica a los objetos, no a los tipos. Por lo tanto (como ya se señaló) no tiene sentido tener un miembro de interfaz estático.

+0

En algunos contextos reflexivos casi parece tener sentido, aunque – Cruncher

-2

Quizás un ejemplo de código ayudaría, voy a usar C#, pero debería poder seguirlo.

vamos a pretender que tenemos una interfaz llamada IPayable

public interface IPayable 
{ 
    public Pay(double amount); 
} 

Ahora, tenemos dos clases concretas que implementan esta interfaz:

public class BusinessAccount : IPayable 
{ 
    public void Pay(double amount) 
    { 
     //Logic 
    } 
} 

public class CustomerAccount : IPayable 
{ 
    public void Pay(double amount) 
    { 
     //Logic 
    } 
} 

Ahora, vamos a pretender que tenemos una colección de varias cuentas, Para hacer esto, utilizaremos una lista genérica del tipo IPayable

List<IPayable> accountsToPay = new List<IPayable>(); 
accountsToPay.add(new CustomerAccount()); 
accountsToPay.add(new BusinessAccount()); 

Ahora, w e desea pagar $ 50.00 a todas esas cuentas:

foreach (IPayable account in accountsToPay) 
{ 
    account.Pay(50.00); 
} 

Ahora puede ver cómo las interfaces son increíblemente útiles.

Se utilizan únicamente en objetos instanciados. No en clases estáticas

Si ha hecho el pago estático, al pasar por el IPayable en accountsToPay no habría forma de averiguar si debería llamar a pagar en BusinessAcount o CustomerAccount.

+0

-1 Entonces, ¿por qué permitir campos estáticos en Interfaces entonces. – Stefan

+0

El hecho de que los métodos estáticos no tengan sentido en ESTE ejemplo, no significa que no tengan sentido en CUALQUIER ejemplo. En su ejemplo, si la interfaz IPable tenía el método estático "IncrementPayables" que registraba cuántas cuentas por pagar se agregaron, este sería un caso de uso real. Por supuesto, uno siempre puede usar una clase abstracta, pero eso no es a lo que te refieres. Su ejemplo en sí mismo no socava los métodos estáticos en las interfaces. – Cruncher

11

La razón radica en el principio de diseño, que java no permite herencia múltiple. El problema con la herencia múltiple se puede ilustrar con el siguiente ejemplo:

public class A { 
    public method x() {...} 
} 
public class B { 
    public method x() {...} 
} 
public class C extends A, B { ... } 

Ahora ¿Qué ocurre si se llama a C.x()? ¿Se ejecutará A.x() o B.x()? Cada idioma con herencia múltiple tiene que resolver este problema.

Las interfaces permiten en Java algún tipo de herencia múltiple restringida. Para evitar el problema anterior, no se les permite tener métodos. Si nos fijamos en el mismo problema con las interfaces y métodos estáticos:

public interface A { 
    public static method x() {...} 
} 
public interface B { 
    public static method x() {...} 
} 
public class C implements A, B { ... } 

mismo problema aquí, lo que sucedería si se llama a C.x()?

+0

¿Alguna razón para el downvote? Un comentario explicativo sería agradable. – Mnementh

+0

No soy el que menosprecia, ¿pero esto no es válido también para métodos no estáticos? – nawfal

+0

OK, aquí hay dos posibilidades diferentes. Un método podría implementarse o solo declararse. Entendí que el método estático debe ser implementado. En ese sentido, encuentro el problema presentado en mi respuesta.Si no haces eso, te topas con el problema que Espo describió, y que no entendí porque asumí que se implementaría el método estático. Tampoco puede declarar un método abstracto estático por este motivo, pruébelo, el compilador se quejará. – Mnementh

4

Hay una respuesta muy agradable y concisa a su pregunta here. (Me pareció una forma tan sencilla de explicarlo que quiero vincularlo desde aquí.)

+0

Esta no es una respuesta a la pregunta, en el mejor de los casos debería ser un comentario. – CubeJockey

2

Parece que el método estático en la interfaz podría ser compatible con Java 8, bueno, mi solución es simplemente definirlos en la clase interna

interface Foo { 
    // ... 
    class fn { 
     public static void func1(...) { 
      // ... 
     } 
    } 
} 

La misma técnica también se puede utilizar en las anotaciones:

public @interface Foo { 
    String value(); 

    class fn { 
     public static String getValue(Object obj) { 
      Foo foo = obj.getClass().getAnnotation(Foo.class); 
      return foo == null ? null : foo.value(); 
     } 
    } 
} 

La clase interna se debe acceder siempre en forma de Interface.fn... en lugar de Class.fn..., a continuación, usted puede deshacerse de un problema ambigua.

0

combinación ilegal de modificadores: estática y abstracta

Si un miembro de una clase se declara como estática, que puede ser utilizado con su nombre de la clase que se limita a esa clase, sin crear un objeto.

Si un miembro de una clase se declara como abstracto, debe declarar la clase como abstracta y debe proporcionar la implementación del miembro abstracto en su clase heredada (Subclase).

Debe proporcionar una implementación al miembro abstracto de una clase en la subclase en la que va a cambiar el comportamiento del método estático, también declarado como abstracto que está confinado a la clase base, lo que no es correcto

+0

¿Cómo responde esto la pregunta? El OP preguntó acerca de la interfaz mientras escribía sobre la clase. – Lucky

0

Dado que los métodos estáticos no se pueden heredar. Así que no sirve de nada colocarlo en la interfaz. La interfaz es básicamente un contrato que todos sus suscriptores deben seguir. Colocar un método estático en la interfaz obligará a los suscriptores a implementarlo. que ahora se vuelve contradictorio al hecho de que los métodos estáticos no pueden ser heredados.

+0

los métodos estáticos siempre se heredan pero no se pueden anular. – Akki

5

Ahora Java8 nos permite definir incluso métodos estáticos en la interfaz.

interface X { 
    static void foo() { 
     System.out.println("foo"); 
    } 
} 

class Y implements X { 
    //... 
} 

public class Z { 
    public static void main(String[] args) { 
     X.foo(); 
     // Y.foo(); // won't compile because foo() is a Static Method of X and not Y 
    } 
} 

Nota: Los métodos de interfaz aún son públicas abstracta por defecto si no utilizamos explícitamente el valor por defecto palabras clave/estática para que sean los métodos Defender y métodos estáticos resp.

1

Java 8 Había cambiado el mundo puede tener métodos estáticos en la interfaz, pero le obliga a proporcionar la implementación para eso.

public interface StaticMethodInterface { 
public static int testStaticMethod() { 
    return 0; 
} 

/** 
* Illegal combination of modifiers for the interface method 
* testStaticMethod; only one of abstract, default, or static permitted 
* 
* @param i 
* @return 
*/ 
// public static abstract int testStaticMethod(float i); 

default int testNonStaticMethod() { 
    return 1; 
} 

/** 
* Without implementation. 
* 
* @param i 
* @return 
*/ 
int testNonStaticMethod(float i); 

}

Cuestiones relacionadas