À quoi sert le mot-clé par défaut en Java?

94

Une interface en Java est similaire à une classe, mais le corps d'une interface ne peut inclure que des méthodes abstraites et des finalchamps (constantes).

Récemment, j'ai vu une question qui ressemble à ceci

interface AnInterface {
    public default void myMethod() {
        System.out.println("D");
    }
}

Selon la définition de l'interface, seules les méthodes abstraites sont autorisées. Pourquoi me permet-il de compiler le code ci-dessus? Quel est le defaultmot clé?

D'un autre côté, quand j'essayais d'écrire le code ci-dessous, il dit modifier default not allowed here

default class MyClass{

}

au lieu de

class MyClass {

}

Quelqu'un peut-il me dire le but du defaultmot-clé? Est-ce uniquement autorisé à l'intérieur d'une interface? En quoi diffère-t-il de default(pas de modificateur d'accès)?

Ravi
la source
4
les méthodes par défaut dans les interfaces ont été ajoutées dans Java 8. Ce n'est pas un modificateur d'accès, c'est une implémentation par défaut.
Eran
2
@Eran ne pensez-vous pas, introduction de la méthode par défaut violant la définition de l'interface? : s
Ravi
2
Cela a changé la définition de l'interface. Cette définition est maintenant dépassée.
Louis Wasserman
2
Ils ont été introduits pour soutenir les lambdas. Les détails expliquant pourquoi ils sont requis se trouvent dans la proposition de l'homme de paille pour le projet Lambda.
sprinter

Réponses:

74

C'est une nouvelle fonctionnalité de Java 8 qui permet à un interfacede fournir une implémentation. Décrit dans Java 8 JLS-13.5.6. Déclarations de méthode d'interface qui lit (en partie)

L'ajout d'une defaultméthode, ou la modification d'une méthode de abstractà default, ne rompt pas la compatibilité avec les binaires préexistants, mais peut provoquer un IncompatibleClassChangeErrorsi un binaire préexistant tente d'appeler la méthode. Cette erreur se produit si le type de qualification,, Test un sous-type de deux interfaces, Iet J, où les deux Iet Jdéclarent une defaultméthode avec la même signature et le même résultat, et ni Ini Jn'est une sous- interface de l'autre.

Quoi de neuf dans JDK 8 dit (en partie)

Les méthodes par défaut permettent d'ajouter de nouvelles fonctionnalités aux interfaces des bibliothèques et d'assurer la compatibilité binaire avec le code écrit pour les anciennes versions de ces interfaces.

Elliott Frisch
la source
16
Il semble que maintenant l'interface et la classe abstraite soient presque identiques. :)
Ravi
16
Les interfaces @jWeaver ne peuvent toujours pas avoir de constructeurs, de champs, de méthodes privées ou d'implémentations de equals / hashCode / toString.
Louis Wasserman
10
@Louis Wasserman: Dans Java 9, ils peuvent avoir des privateméthodes.
Holger
6
@Dan Pantry: les privateméthodes ne font pas vraiment partie de l'interface, mais peuvent servir de méthodes d'aide pour les defaultimplémentations ou dans les initialiseurs constants. Notez qu'ils existent déjà dans Java 8, car lorsque vous utilisez des expressions lambda dans les interfaces, des privateméthodes synthétiques sont générées. Donc Java 9 vous permet d'utiliser cette fonctionnalité pour des utilisations non synthétiques, non lambda aussi…
Holger
14
@jWeaver La différence entre les interfaces et les classes se réduit à l' état et au comportement . Les interfaces peuvent porter un comportement, mais seules les classes peuvent avoir un état. (Les champs, les constructeurs et les méthodes tels que equals / hashCode concernent l'état.)
Brian Goetz
26

Les méthodes par défaut ont été ajoutées à Java 8 principalement pour prendre en charge les expressions lambda. Les concepteurs (intelligemment, à mon avis) ont décidé de créer une syntaxe lambdas pour créer des implémentations anonymes d'une interface. Mais étant donné que les lambdas ne peuvent implémenter qu'une seule méthode, ils seraient limités aux interfaces avec une seule méthode, ce qui serait une restriction assez sévère. Au lieu de cela, des méthodes par défaut ont été ajoutées pour permettre l'utilisation d'interfaces plus complexes.

Si vous avez besoin de convaincre de l'allégation qui a defaultété introduite en raison des lambdas, notez que la proposition de l'homme de paille de l' du projet Lambda, par Mark Reinhold, en 2009, mentionne les `` méthodes d'extension '' comme une fonctionnalité obligatoire à ajouter pour prendre en charge les lambdas.

Voici un exemple illustrant le concept:

interface Operator {
    int operate(int n);
    default int inverse(int n) {
        return -operate(n);
    }
}

public int applyInverse(int n, Operator operator) {
    return operator.inverse(n);
}

applyInverse(3, n -> n * n + 7);

Très artificiel je me rends compte mais devrait illustrer comment defaultsoutient les lambdas. Comme il inverses'agit d'une valeur par défaut, elle peut facilement être remplacée par une classe d'implémentation si nécessaire.

sprinter
la source
8
Ce n'est pas vraiment correct. Les lambdas peuvent être la cause immédiate, mais ils n'étaient en réalité que la paille qui a brisé le dos du chameau. La vraie motivation était de permettre l' évolution des interfaces (permettant aux interfaces existantes d'être évoluées de manière compatible pour supporter de nouveaux comportements); lambdas a peut-être été le facteur qui a mis ce besoin au premier plan, mais la fonctionnalité est plus générale que cela.
Brian Goetz
@BrianGoetz: À mon humble avis, Java et .NET auraient énormément bénéficié si les méthodes par défaut avaient existé dès le départ. Si une opération commune pouvait être effectuée sur une implémentation d'une interface en utilisant uniquement des membres d'interface, mais que certaines implémentations auraient probablement un moyen plus efficace de les faire, l'interface devrait définir des méthodes pour ces opérations et leur fournir des implémentations par défaut. L'incapacité de spécifier les implémentations par défaut a induit une pression pour que les interfaces omettent de telles méthodes et les a empêchées de les ajouter ultérieurement.
supercat du
@BrianGoetz Je suis d'accord que les méthodes par défaut ont une valeur significative au-delà des lambdas. Mais je serais intéressé par toute référence que vous pourriez donner à cette valeur plus large motivant la décision de les inclure. Ma lecture est que les lambdas étaient la raison principale (c'est pourquoi j'ai utilisé le mot «principalement» dans ma réponse).
sprinter
2
Peut-être que ce document aidera: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html . La section 10 dit clairement: "Le but des méthodes par défaut (précédemment appelées méthodes d'extension virtuelle ou méthodes de défense) est de permettre aux interfaces d'évoluer de manière compatible après leur publication initiale." Les méthodes compatibles avec Lambda sont ensuite citées pour illustrer l' évolution de l'interface.
Brian Goetz
2
@Kartik Vous posez la mauvaise question! Nous ne choisissons pas une syntaxe basée sur "quel est le minimum absolu nécessaire au compilateur pour analyser correctement le programme"; nous le choisissons sur la base de «ce qui rendrait l'intention du programmeur plus immédiatement évidente pour les lecteurs». Nous concevons d'abord pour les utilisateurs, et ensuite pour les compilateurs (et en ce qui concerne les utilisateurs, nous concevons d'abord pour la lecture, et ensuite pour l'écriture.)
Brian Goetz
16

Un nouveau concept est introduit dans Java 8, appelé méthodes par défaut. Les méthodes par défaut sont les méthodes qui ont une implémentation par défaut et aident à faire évoluer les interfaces sans casser le code existant. Regardons un exemple:

 public interface SimpleInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword

    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

 class SimpleInterfaceImpl implements SimpleInterface{

  @Override
  public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Not required to override to provide an implementation
  * for doSomeOtherWork.
  */

 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }

et la sortie est:


Implémentation Do Some Work dans la classe Implémentation DoSomeOtherWork dans l'interface

Saurabh Gaur
la source
16

Un élément qui a été négligé dans les autres réponses était son rôle dans les annotations. Dès Java 1.5, le defaultmot - clé est apparu comme un moyen de fournir une valeur par défaut pour un champ d'annotation.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
    String value() default "AMD";
}

Son utilisation a été surchargée avec l'introduction de Java 8 pour permettre de définir une méthode par défaut dans les interfaces.

Autre chose qui a été négligée: la raison pour laquelle la déclaration default class MyClass {}est invalide est due à la façon dont les classes sont déclarées du tout . Il n'y a aucune disposition dans la langue qui permet à ce mot-clé d'y apparaître. Il ne semble pour les déclarations de méthode d'interface , bien que.

Makoto
la source
3

La nouvelle fonctionnalité Java 8 ( méthodes par défaut ) permet à une interface de fournir une implémentation lorsqu'elle est étiquetée avec le defaultmot - clé.

Par exemple:

interface Test {
    default double getAvg(int avg) {
        return avg;
    }
}
class Tester implements Test{
 //compiles just fine
}

Interface Test utilise le mot-clé default qui permet à l'interface de fournir une implémentation par défaut de la méthode sans avoir besoin d'implémenter ces méthodes dans les classes qui utilisent l'interface.

Compatibilité descendante: imaginez que votre interface est implémentée par des centaines de classes, la modification de cette interface obligera tous les utilisateurs à implémenter la méthode nouvellement ajoutée, même si ce n'est pas essentiel pour de nombreuses autres classes qui implémentent votre interface.

Faits et restrictions:

1-Ne peut être déclaré que dans une interface et non dans une classe ou une classe abstraite.

2-Doit fournir un corps

3-Il n'est pas supposé être public ou abstrait comme les autres méthodes normales utilisées dans une interface.

Ahmad Sanie
la source
3

Les méthodes par défaut dans une interface nous permettent d'ajouter de nouvelles fonctionnalités sans casser l'ancien code.

Avant Java 8, si une nouvelle méthode était ajoutée à une interface, toutes les classes d'implémentation de cette interface étaient tenues de remplacer cette nouvelle méthode, même si elles n'utilisaient pas la nouvelle fonctionnalité.

Avec Java 8, nous pouvons ajouter l'implémentation par défaut de la nouvelle méthode en utilisant le defaultmot - clé avant l'implémentation de la méthode.

Même avec des classes anonymes ou des interfaces fonctionnelles, si nous voyons que du code est réutilisable et que nous ne voulons pas définir la même logique partout dans le code, nous pouvons en écrire des implémentations par défaut et les réutiliser.

Exemple

public interface YourInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword
    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

    class SimpleInterfaceImpl implements YourInterface{

     /*
     * Not required to override to provide an implementation
     * for doSomeOtherWork.
     */
      @Override
      public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Main method
  */
 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }
Dickson le développeur
la source
2

Une très bonne explication se trouve dans les didacticiels Java ™ , une partie de l'explication est la suivante:

Prenons un exemple qui implique des fabricants de voitures contrôlées par ordinateur qui publient des interfaces standard de l'industrie qui décrivent les méthodes qui peuvent être invoquées pour faire fonctionner leurs voitures. Et si ces constructeurs automobiles contrôlés par ordinateur ajoutaient de nouvelles fonctionnalités, comme le vol, à leurs voitures? Ces fabricants devraient spécifier de nouvelles méthodes pour permettre à d'autres entreprises (comme les fabricants d'instruments de guidage électroniques) d'adapter leur logiciel aux voitures volantes. Où ces constructeurs automobiles déclareraient-ils ces nouvelles méthodes liées au vol? S'ils les ajoutent à leurs interfaces d'origine, alors les programmeurs qui ont implémenté ces interfaces devraient réécrire leurs implémentations. S'ils les ajoutent comme des méthodes statiques, les programmeurs les considéreront comme des méthodes utilitaires, et non comme des méthodes essentielles.

Les méthodes par défaut vous permettent d'ajouter de nouvelles fonctionnalités aux interfaces de vos bibliothèques et d'assurer la compatibilité binaire avec le code écrit pour les anciennes versions de ces interfaces.

Riyafa Abdul Hameed
la source
1

Les méthodes par défaut vous permettent d'ajouter de nouvelles fonctionnalités aux interfaces de vos applications. Il peut également être utilisé pour avoir un héritage multiple . En plus des méthodes par défaut, vous pouvez définir des méthodes statiques dans les interfaces. Cela vous permet d'organiser plus facilement les méthodes d'assistance

user3359139
la source