web-dev-qa-db-fra.com

Comment puis-je écrire une fonction anonyme en Java?

Est-ce même possible?

83
DJTripleThreat

si vous voulez parler d'une fonction anonyme, et utilisez une version de Java antérieure à Java 8,, puis dans un mot, non. ( Lisez à propos des expressions lambda si vous utilisez Java 8+ )

Cependant, vous pouvez implémenter une interface avec une fonction comme celle-ci:

Comparator<String> c = new Comparator<String>() {
    int compare(String s, String s2) { ... }
};

et vous pouvez l'utiliser avec les classes internes pour obtenir une fonction presque anonyme :)

76
chris

Voici un exemple de classe interne anonyme.

System.out.println(new Object() {
    @Override public String toString() {
        return "Hello world!";
    }
}); // prints "Hello world!"

Ce n'est pas très utile tel quel, mais cela montre comment créer une instance d'une classe interne anonyme qui extends Object et @Override est sa méthode toString().

Voir également


Les classes internes anonymes sont très pratiques lorsque vous devez implémenter une interface qui risque de ne pas être hautement réutilisable (et qui ne mérite donc pas d'être refondue en une classe nommée). Un exemple instructif utilise un Java.util.Comparator<T> personnalisé pour le tri.

Voici un exemple de la manière dont vous pouvez trier un String[] en fonction de String.length().

import Java.util.*;
//...

String[] arr = { "xxx", "cd", "ab", "z" };
Arrays.sort(arr, new Comparator<String>() {
    @Override public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }           
});
System.out.println(Arrays.toString(arr));
// prints "[z, cd, ab, xxx]"

Notez l'astuce de comparaison par soustraction utilisée ici. Il faut dire que cette technique est généralement cassée: elle n’est applicable que si vous pouvez garantir qu’elle ne débordera pas (tel est le cas de String longueurs).

Voir également

43

Avec l'introduction de l'expression lambda dans Java 8, vous pouvez maintenant utiliser des méthodes anonymes.

Supposons que j'ai une classe Alpha et que je souhaite filtrer Alphas sur une condition spécifique. Pour ce faire, vous pouvez utiliser un Predicate<Alpha> . C'est une interface fonctionnelle qui a une méthode test qui accepte une Alpha et renvoie une boolean.

En supposant que la méthode de filtrage ait cette signature:

List<Alpha> filter(Predicate<Alpha> filterPredicate)

Avec l'ancienne solution de classe anonyme, vous auriez besoin de quelque chose comme:

filter(new Predicate<Alpha>() {
   boolean test(Alpha alpha) {
      return alpha.centauri > 1;
   }
});

Avec Java 8 lambdas, vous pouvez faire:

filter(alpha -> alpha.centauri > 1);

Pour plus d'informations, consultez le didacticiel Expressions lambda

11
Mark Rotteveel

Les classes internes anonymes implémentant ou étendant l'interface d'un type existant ont été utilisées dans d'autres réponses, bien qu'il soit utile de noter que plusieurs méthodes peuvent être implémentées (souvent avec des événements de type JavaBean, par exemple).

Une caractéristique peu reconnue est que, bien que les classes internes anonymes n'aient pas de nom, elles ont un type. De nouvelles méthodes peuvent être ajoutées à l'interface. Ces méthodes ne peuvent être invoquées que dans des cas limités. Principalement directement sur l'expression new elle-même et au sein de la classe (y compris les initialiseurs d'instance). Cela peut confondre les débutants, mais cela peut être "intéressant" pour la récursion.

private static String pretty(Node node) {
    return "Node: " + new Object() {
        String print(Node cur) {
            return cur.isTerminal() ?
                cur.name() :
                ("("+print(cur.left())+":"+print(cur.right())+")");
        }
    }.print(node);
}

(Au départ, j’écrivais cela en utilisant node plutôt que cur dans la méthode print. Dites NON à la capture de caractères "implicitement final"? )

Oui si vous utilisez la dernière version de Java, la version 8. Java8 permet de définir des fonctions anonymes, ce qui était impossible dans les versions précédentes.

Prenons un exemple de Java Docs pour savoir comment déclarer des fonctions anonymes, des classes

L'exemple suivant, HelloWorldAnonymousClasses, utilise anonymous classes dans les instructions d'initialisation des variables locales frenchGreeting et spanishGreeting, mais utilise une classe locale pour le initialisation de la variable englishGreeting:

public class HelloWorldAnonymousClasses {

    interface HelloWorld {
        public void greet();
        public void greetSomeone(String someone);
    }

    public void sayHello() {

        class EnglishGreeting implements HelloWorld {
            String name = "world";
            public void greet() {
                greetSomeone("world");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hello " + name);
            }
        }

        HelloWorld englishGreeting = new EnglishGreeting();

        HelloWorld frenchGreeting = new HelloWorld() {
            String name = "tout le monde";
            public void greet() {
                greetSomeone("tout le monde");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Salut " + name);
            }
        };

        HelloWorld spanishGreeting = new HelloWorld() {
            String name = "mundo";
            public void greet() {
                greetSomeone("mundo");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hola, " + name);
            }
        };
        englishGreeting.greet();
        frenchGreeting.greetSomeone("Fred");
        spanishGreeting.greet();
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp =
            new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }            
}

Syntaxe des classes anonymes

Considérons l'instanciation de l'objet frenchGreeting:

    HelloWorld frenchGreeting = new HelloWorld() {
        String name = "tout le monde";
        public void greet() {
            greetSomeone("tout le monde");
        }
        public void greetSomeone(String someone) {
            name = someone;
            System.out.println("Salut " + name);
        }
    };

L'expression de classe anonyme comprend les éléments suivants:

  • L'opérateur new
  • Nom d'une interface à implémenter ou d'une classe à étendre. Dans cet exemple , La classe anonyme implémente l'interface HelloWorld.

  • Les parenthèses qui contiennent les arguments d'un constructeur, exactement comme une expression de création d'instance de classe Normal. Remarque: Lorsque vous implémentez l'interface .__an, il n'y a pas de constructeur. Vous utilisez donc une paire vide de parenthèses .__, comme dans cet exemple.

  • Un corps, qui est un corps de déclaration de classe. Plus spécifiquement, dans le corps , Les déclarations de méthode sont autorisées, mais pas les instructions.

0
mumair