java - signification - statique methode




Pourquoi ne puis-je pas déclarer de méthodes statiques dans une interface? (9)

Le sujet en dit le plus - quelle est la raison pour laquelle les méthodes statiques ne peuvent pas être déclarées dans une interface?

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

Le code ci-dessus me donne l'erreur suivante (dans Eclipse, au moins): "Modificateur illégal pour la méthode d'interface ITest.test (), seul public et abstrait sont autorisés".


Combinaison illégale de modificateurs: statique et abstraite

Si un membre d'une classe est déclaré statique, il peut être utilisé avec son nom de classe qui est limité à cette classe, sans créer d'objet.

Si un membre d'une classe est déclaré comme abstrait, vous devez déclarer la classe comme abstraite et vous devez fournir l'implémentation du membre abstrait dans sa classe héritée (sous-classe).

Vous devez fournir une implémentation au membre abstrait d'une classe dans une sous-classe où vous allez changer le comportement de la méthode statique, aussi déclarée comme abstraite qui est confinée à la classe de base, ce qui n'est pas correct


Il semble que la méthode statique dans l'interface puisse être supportée dans Java 8 , et bien, ma solution est juste de les définir dans la classe interne.

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

La même technique peut également être utilisée dans les annotations:

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 classe interne doit toujours être accessible sous la forme de Interface.fn... au lieu de Class.fn... , alors, vous pouvez vous débarrasser d'un problème ambigu.


Il y a une réponse très gentille et concise à votre question here . (Cela m'a semblé une façon si simple de l'expliquer que je veux la lier d'ici.)


Java 8 Avait changé le monde, vous pouvez avoir des méthodes statiques dans l'interface, mais il vous oblige à fournir une implémentation pour cela.

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

}


La raison pour laquelle vous ne pouvez pas avoir de méthode statique dans une interface réside dans la façon dont Java résout les références statiques. Java ne cherchera pas à rechercher une instance d'une classe lors de l'exécution d'une méthode statique. En effet, les méthodes statiques ne dépendent pas des instances et peuvent donc être exécutées directement à partir du fichier de classe. Étant donné que toutes les méthodes d'une interface sont abstraites, la machine virtuelle devrait rechercher une implémentation particulière de l'interface afin de trouver le code derrière la méthode statique afin qu'elle puisse être exécutée. Cela contredit alors la façon dont la résolution de méthode statique fonctionne et introduirait une incohérence dans le langage.


La raison réside dans le principe de conception, que Java n'autorise pas l'héritage multiple. Le problème avec l'héritage multiple peut être illustré par l'exemple suivant:

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

Maintenant, que se passe-t-il si vous appelez Cx ()? Sera Ax () ou Bx () exécuté? Chaque langue avec plusieurs héritages doit résoudre ce problème.

Les interfaces permettent en Java une sorte d'héritage multiple restreint. Pour éviter le problème ci-dessus, ils ne sont pas autorisés à avoir des méthodes. Si nous regardons le même problème avec les interfaces et les méthodes statiques:

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

Même problème ici, que se passe-t-il si vous appelez Cx ()?


Maintenant, Java8 nous permet de définir même des méthodes statiques dans l'interface.

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

Remarque: Les méthodes dans Interface sont toujours abstraites par défaut si nous n'utilisons pas explicitement les mots-clés default / static pour les rendre Defender et Static resp.


Peut-être qu'un exemple de code aiderait, je vais utiliser C #, mais vous devriez être capable de suivre.

Supposons que nous avons une interface appelée IPayable

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

Maintenant, nous avons deux classes concrètes qui implémentent cette interface:

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

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

Maintenant, faisons comme si nous avions une collection de différents comptes, pour cela nous utiliserons une liste générique du type IPayable

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

Maintenant, nous voulons payer 50,00 $ à tous ces comptes:

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

Alors maintenant, vous voyez comment les interfaces sont incroyablement utiles.

Ils sont utilisés uniquement sur des objets instanciés. Pas sur les classes statiques.

Si vous avez effectué une paie statique, lors de la lecture en boucle de l'IPayable dans accountsToPay, il n'y aurait aucun moyen de déterminer si elle doit appeler paye sur BusinessAcount ou CustomerAccount.


Une interface est utilisée pour le polymorphisme, qui s'applique aux objets, pas aux types. Par conséquent (comme déjà noté), cela n'a aucun sens d'avoir un membre d'interface statique.







static