简体   繁体   English

可以避免使用Class :: method语法对Lambda进行装箱和拆箱吗? (JAVA)

[英]Possible to avoid boxing and unboxing for Lambda using Class::method syntax? (Java)

I've recently stumbled upon the Class::method syntax which allows you to insert lambda code which from a static method like this: 我最近偶然发现了Class::method语法,该语法允许您从这样的静态方法中插入lambda代码:

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);
  }

}

The question is, does boxing and unboxing of 1 still occur? 问题是,是否还会发生1的装箱和拆箱? After all, bar 's parameter is a Consumer<Integer> which should normally box primitives, yet foo(int) is a method which accepts a primitive, thus boxing is not neccessary. 毕竟, bar的参数是Consumer<Integer> ,通常应将原语装箱,而foo(int)是接受原语的方法,因此装箱不是必需的。

So, what happens? 那么,会发生什么呢? Does 1 get turned into an Integer or does it remain primitive? 1变成Integer还是保持原始状态?

On a side note, I am aware that IntConsumer delivers a solution to get rid of boxing and unboxing, but not every single functional interface has an alternative for every single primitive type, hence the question. 附带一提,我知道IntConsumer提供了一种摆脱装箱和拆箱的解决方案,但是并不是每个功能接口都为每个原始类型提供替代方案,因此提出了问题。

Yes it is boxed and then unboxed. 是的,将其装箱,然后再拆箱。

Compiling the code and then decompiling the class file reveals the following: 编译代码,然后反编译类文件将显示以下内容:

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);
    }
}

The compiler automatically boxes 1, meaning it will be unboxed when foo() is called. 编译器自动将1装箱,这意味着将在调用foo()时将其取消装箱。

If the answer you accepted surprises you, than because you don't know enough about Java yet. 如果您接受的答案使您感到惊讶,那是因为您对Java还不了解。 So don't call it a disappointment, but a disillusion . 因此,不要称它为失望,而是幻想

In contrast to C++ templates Java generics work with for reference types only . 与C ++模板相反,Java泛型适用于引用类型。

Thus there is absolutely no way any generic-using construct can directly work with primitive types! 因此,绝对没有任何通用使用的构造可以直接与原始类型一起使用! So whenever you use a primitive type value in such a context, it must be boxed. 因此,无论何时在这样的上下文中使用原始类型值,都必须将其装箱。

Maybe, one day far in the future, when the parents of Java decide to redo generics, that might change, but we are not there yet. 也许在将来的某一天,当Java的父母决定重做泛型时,这种情况可能会改变,但是我们还没有到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM