2016-09-03 2 views
2

Je suis récemment tombé sur la syntaxe Class::method qui vous permet d'insérer du code lambda qui à partir d'une méthode statique comme ceci:Possible d'éviter la boxe et le déballage pour Lambda en utilisant la syntaxe de la classe Class ::? (Java)

public class Main { 

    public static void foo(int foo) { 
    System.out.println(foo); 
    } 

    public static void bar(Consumer<Integer> bar) { 
    bar.accept(1); 
    } 

    public static void main(String[] args) { 
    bar(Main::foo); 
    } 

} 

La question est, est-ce la boxe et unboxing de 1 se produisent encore? Après tout, le paramètre bar est un Consumer<Integer> qui devrait normalement contenir des primitives, alors que foo(int) est une méthode qui accepte une primitive, donc la boxe n'est pas nécessaire.

Alors, que se passe-t-il? Est-ce que 1 est transformé en Integer ou reste-t-il primitif? Sur une note de côté, je sais que IntConsumer offre une solution pour se débarrasser de la boxe et du déballage, mais pas toutes les interfaces fonctionnelles ont une alternative pour chaque type primitif, d'où la question.

+0

Si vous êtes dans une situation où vous êtes libre de choisir entre Consumer et IntConsumer, il est probable que vous soyez également libre de créer vos propres interfaces fonctionnelles utilisant des types primitifs. –

Répondre

2

Oui, il est encadré et ensuite déballé.

le code et Compiler décompilation le fichier de classe révèle ce qui suit:

import java.util.function.Consumer; 

public class Main { 
    public Main() { 
    } 

    public static void foo(int foo) { 
     System.out.println(foo); 
    } 

    public static void bar(Consumer<Integer> bar) { 
     bar.accept(Integer.valueOf(1)); 
    } 

    public static void main(String[] args) { 
     bar(Main::foo); 
    } 
} 

Le compilateur boîtes automatiquement 1, ce qui signifie qu'il sera Unboxed quand foo() est appelée.

+0

Merci pour la réponse. La réponse est assez décevante cependant. –

2

Si la réponse que vous avez reçue vous surprend, c'est parce que vous ne connaissez pas encore suffisamment Java. Alors ne l'appelez pas une déception, mais une désillusion .

Contrairement aux modèles C++, les génériques Java fonctionnent avec les types de référence uniquement.

Ainsi, il y a absolument aucun comme n'importe quelle construction utilisant un générique peut directement travailler avec les types primitifs! Donc, chaque fois que vous utilisez une valeur de type primitive dans un tel contexte, doit être être encadré.

Peut-être, un jour loin dans l'avenir, lorsque les parents de Java décideront de refaire des génériques, cela pourrait changer, mais nous ne sommes pas encore là.

+0

Eh bien, dans ce scénario très spécifique, il serait en fait possible de créer un 'Consumer ' qui accepte aussi les primitives puisqu'il provient d'une méthode statique qui accepte un primitif int. Cette méthode peut ne pas être visible lors de l'écriture du code mais peut être disponible pendant l'exécution. –

+0

Bien sûr, mais ** la surcharge de méthode ** ne fonctionne que lorsque les deux; "client" et "fournisseur" sont au courant de ce cas particulier. Et vous ne pourriez plus l'appeler un Consumer GhostCat

+0

Le projet Valhalla (types de valeur) corrigera beaucoup de ceci, mais pas maintenant. C'est Java 10ish. – Marcus