J'ai fait ça:
public class LambdaConflict
{
public static void main(String args[]){
//*
System.out.println(LambdaConflict.get(
(str) -> "Hello World!! By ME?"
));
/*/
System.out.println(LambdaConflict.get(new Intf<String> (){
@Override public String get1(String str){
return "Hello World!! By get1 " + str;
}
}));
/*****/
}
public static String get(Intf<String> i, boolean b){
return i.get1("from 1");
}
}
interface Intf<T>
{
public T get1(T arg1);
public T get2(T arg1);
}
et obtenez cette exception:
types incompatibles: Intf n'est pas une interface fonctionnelle, plusieurs méthodes abstraites non prioritaires se trouvant dans l'interface Intf Remarque: Certains messages ont été simplifiés; recompiler avec -Xdiags: verbeux pour obtenir la sortie complète 1 erreur
Existe-t-il une condition selon laquelle je ne peux pas utiliser lambda pour remplacer une classe anonyme?
Non. Il n'y a aucun moyen de "surmonter" cela. Une interface fonctionnelle ne doit avoir qu'une seule méthode abstraite. Votre interface en a deux:
interface Intf<T> {
public T get1(T arg1);
public T get2(T arg1);
}
Remarque: vous n'avez pas besoin d'annoter votre interface comme mentionné dans les commentaires. Mais vous pouvez utiliser le @FunctionalInterface
annotation pour obtenir des erreurs de compilation si votre interface n'est pas une interface fonctionnelle valide. Cela vous apporte donc un peu plus de sécurité dans votre code.
Pour plus d'informations, voir par exemple http://Java.dzone.com/articles/introduction-functional-1
Juste pour référence et pour enrichir les réponses déjà données:
Selon JSR-335: Expressions Lambda pour le Java langage de programmation , dans la section Spécifications Lambda, Partie A: Interfaces fonctionnelles, il est dit:
Une interface fonctionnelle est une interface qui n'a qu'une seule méthode abstraite (en dehors des méthodes d'Object), et représente donc un contrat de fonction unique. (Dans certains cas, cette méthode "unique" peut prendre la forme de plusieurs méthodes abstraites avec des signatures équivalentes de substitution héritées des superinterfaces; dans ce cas, les méthodes héritées représentent logiquement une seule méthode.)
Donc, ce dont vous avez besoin est de fournir une implémentation par défaut pour l'une de vos méthodes ou de placer l'une de vos méthodes dans une interface différente.
Pensez-y:
Comment le compilateur doit-il savoir si vous souhaitez remplacer get1
ou get2
?
Si vous remplacez uniquement get1
, ce qui sera get2
la mise en œuvre? Même le code que vous avez commenté ne fonctionnera pas car vous n'implémentez pas get2
...
Il y a des raisons à cette limitation ...
Comme indiqué par @ Thomas-Uhrig, les interfaces fonctionnelles ne peuvent avoir que ne méthode.
Un moyen de résoudre ce problème, principalement parce que vous n'utilisez jamais public T get2(T arg1);
, consiste à modifier le Intf<T>
interface vers:
@FunctionalInterface
interface Intf<T>
{
public T get1(T arg1);
}