2017-02-27 1 views
8

Je suis un peu confus avec le comportement différent d'une classe anonyme et d'une expression lambda.Valeur de "this" dans une classe anonyme vs une expression lambda

Lorsque j'utilise une expression lambda:

//Test.java 

Runnable r1 =() -> System.out.println(this); 
Runnable r2 =() -> System.out.println(toString()); 

@Override 
public String toString() { 
    return "Hello World!"; 
} 

// in main method 
new Test().r1.run(); 
new Test().r2.run(); 
Output : Hello World! 
     Hello World! 

Lorsque vous utilisez une classe anonyme:

Runnable r1 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(this); 
    } 
}; 

Runnable r2 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(toString()); 
    } 
}; 

@Override 
public String toString() { 
    return "Hello World!"; 
} 

// in main method 
new Test().r1.run(); 
new Test().r2.run(); 
Output : [email protected] 
     [email protected] 

Quelqu'un peut-il expliquer s'il vous plaît le comportement différent?

Répondre

10

Dans une expression lambda, this est lié lexicalement à la classe environnante, tandis que dans la classe anonyme this est lié lexicalement à la classe anonyme.

La spécification du langage Java décrit ce comportement à 15.27.2:

Contrairement code apparaissant dans les déclarations de classe anonymes, la signification des noms et des mots-clés this et super apparaissant dans un corps lambda, ainsi que l'accessibilité des référencé déclarations, sont les mêmes que dans le contexte environnant (sauf que les paramètres lambda introduisent de nouveaux noms).

La transparence de this (à la fois explicite et implicite) dans le corps d'une expression lambda - qui est, le traitement de la même chose que dans le contexte environnant - permet une plus grande flexibilité pour les implémentations, et empêche la signification des noms non qualifiés le corps d'être dépendant de la résolution de surcharge.

En pratique, il est inhabituel pour une expression lambda à besoin de parler de lui-même (soit pour lui-même appeler récursive ou d'invoquer ses autres méthodes), alors qu'il est plus fréquent de vouloir utiliser des noms pour désigner les choses dans la classe englobante qui serait autrement occultée (this, toString()). S'il est nécessaire qu'une expression lambda se réfère à elle-même (comme par l'intermédiaire de this), une référence de méthode ou une classe interne anonyme doit être utilisée à la place.

Pour référence this de la classe autour de l'intérieur d'une classe anonyme, vous devrez utiliser un qualified this.

Runnable r1 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(Test.this); // or Test.this.toString() 
    } 
}; 
+0

Merci pour la réponse :), mais ce qui est lié lexicalement? –

+2

@MehrajMalik Cela signifie qu'ils sont liés au moment de la compilation en fonction du contexte dans lequel ils ont été trouvés. – 4castle

+3

Cela n'affecte pas seulement 'this' et' super'. A l'intérieur d'une classe interne anonyme, il peut y avoir des membres hérités (pas seulement 'toString()') alors qu'une expression lambda n'hérite rien de l'interface fonctionnelle. – Holger