nsv_productdetail.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int bottomMargin = ((ViewGroup.MarginLayoutParams) nsv_productdetail.getLayoutParams()).bottomMargin;
nsv_productdetail.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Si le code ci-dessus est converti en lambda, cela pointera vers la classe externe et l'écouteur ne peut pas être supprimé pour le moment.
Je voudrais donc demander, comment une classe interne anonyme (une classe interne anonyme qui peut être convertie en lambda) peut-elle s'obtenir dans le lambda ?
Remplacer certaines classes internes anonymes
Cette section expliquera comment utiliser les expressions Lambda pour simplifier l'écriture de classes internes anonymes. Cependant, les expressions Lambda ne peuvent pas remplacer toutes les classes internes anonymes. Elles ne peuvent être utilisées que pour remplacer l'abréviation de Functional Interface. Ne vous souciez pas encore des détails, regardons quelques exemples.
Exemple 1 : Abréviation de fonction sans paramètre
Si vous devez créer un nouveau fil de discussion, une façon courante de l'écrire est la suivante :
// Méthode d'écriture de classe interne anonyme JDK7
new Thread(new Runnable(){// nom de l'interface
}).start();
Le code ci-dessus transmet un objet Runnable anonyme à la classe Tread et surcharge la méthode run() de l'interface Runnable pour implémenter la logique correspondante. Il s'agit d'une manière courante d'écrire dans JDK7 et avant. Les classes internes anonymes vous évitent de nommer la classe, mais ce n'est toujours pas assez simple. Dans Java 8, cela peut être simplifié sous la forme suivante :
// Comment écrire une expression Lambda JDK8
nouveau fil de discussion(
).start();
Le code ci-dessus a la même fonction que la classe interne anonyme, mais il va plus loin que la classe interne anonyme. Ici, le nom du port de connexion et le nom de la fonction sont omis ensemble, ce qui rend l'écriture plus rafraîchissante. Si le corps de la fonction comporte plusieurs lignes, il peut être placé entre accolades, comme ceci :
// Comment écrire un bloc de code d'expression JDK8 Lambda
nouveau fil de discussion(
).start();
Exemple 2 : Abréviation de fonction avec paramètres
Si vous souhaitez passer un comparateur personnalisé à une liste de chaînes et le trier en fonction de la longueur de la chaîne, la forme d'écriture de Java 7 est la suivante :
// Comment écrire des classes internes anonymes dans JDK7
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String> ;() {//Nom de l'interface
});
Le code ci-dessus surcharge la méthode compare() de l'interface Comparator via la classe interne pour implémenter la logique de comparaison. L'utilisation de l'expression Lambda peut être abrégée comme suit :
// Comment écrire une expression Lambda JDK8
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) - > ;{// Omettre le type de table de paramètres
});
Le code ci-dessus a la même fonction que la classe interne anonyme. En plus d'omettre le nom de l'interface et le nom de la méthode, le type de la table des paramètres est également omis dans le code. Cela est dû au mécanisme d'inférence de type de javac. Le compilateur peut déduire le type des paramètres en fonction des informations contextuelles. Bien entendu, il arrive également que l'inférence échoue, auquel cas le type du paramètre doit être spécifié manuellement. Notez que Java est un langage fortement typé et que chaque variable et objet doit avoir un type clair.
La base de l'abréviation
Vous avez peut-être déjà pensé que la base de l'utilisation de Lambda est qu'il doit y avoir une interface fonctionnelle correspondante (une interface fonctionnelle fait référence à une interface avec une seule méthode abstraite à l'intérieur). Cela est cohérent avec le fait que Java est un langage fortement typé, ce qui signifie que vous ne pouvez pas écrire arbitrairement des expressions Lambda n'importe où dans le code. En fait, le type de Lambda est le type correspondant à l'interface de la fonction. Une autre base des expressions lambda est le mécanisme d'inférence de type. Si les informations contextuelles sont suffisantes, le compilateur peut déduire le type de la table de paramètres sans la nommer explicitement. Lambda exprime des formes écrites plus juridiques comme suit :
// Forme écrite de l'expression Lambda
Runnable run = () -> System.out.println("Hello World");// 1
Auditeur ActionListener = événement -> System.out.println("bouton cliqué" );// 2
Runnable multiLine = () -> {// 3 blocs de code
};
Interface de fonction personnaliséeBinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> montre l'abréviation de la fonction sans paramètre ; 2 montre l'abréviation de la fonction paramétrée et le mécanisme d'inférence de type ; 3 est la méthode d'écriture du bloc de code ; 4 et 5 montrent à nouveau le mécanisme d'inférence de type ;
L'interface de fonction personnalisée est simple, il vous suffit d'écrire une interface avec une seule méthode abstraite.
// Interface de fonction personnalisée@FunctionalInterface
}interface publique ConsumerInterface<T>{
@FunctionalInterface dans le code ci-dessus est facultatif, mais en ajoutant cette annotation, le compilateur vous aidera à vérifier si l'interface est conforme à la spécification de l'interface fonctionnelle. Tout comme l'ajout de l'annotation @Override vérifiera si la fonction est surchargée.
Avec la définition d'interface ci-dessus, vous pouvez écrire du code similaire à celui-ci :De plus, vous pouvez également l'utiliser comme ceci :
classe MyStream<T>{
}
MyStream<String> stream = new MyStream<String>();stream.myForEach(str -> System.out.println(str));// Utiliser une interface de fonction personnalisée pour écrire des expressions Lambda
Ce qui ne peut pas être fait, c'est que Lambda lui-même n'est pas un objet.