0
Function<Double,Integer> f1=(d)-> {
        if(d>5)
            return 0;
        return 1;
    };
DoubleToIntFunction f2=(d)-> {
        if(d>5)
            return 1;
        return 0;
    };
double d=5.0;
f1.apply(d);
f2.applyAsInt(d);

Will f1 be optimized into DoubleToIntFunction(someting like f2).

AmeyaKetkar
  • 117
  • 1
  • 9
  • 2
    What do you mean by "optimize"? Both `Function` and `DoubleToIntFunction` are interfaces - there is nothing to be optimized. – Oliver Charlesworth Apr 17 '17 at 19:25
  • I meant, that will there happen autoboxing for`f1.apply(d);`(double to Double) or will the compiler implicitly convert type of f1 to DoubleFunction or DoubleToIntFunction? – AmeyaKetkar Apr 17 '17 at 19:35
  • 1
    The compiler (`javac`) won't do anything, JIT might compile them into the same native code, depending on usage. – Kayaman Apr 17 '17 at 19:37
  • can you please explain, 'depending on usage'? – AmeyaKetkar Apr 17 '17 at 19:46
  • 2
    Well as they're not actually the same thing, there's no chance that it could be universally converted. However if the JIT is optimizing a small loop and the differences are eliminated (like null not being passed, result assigned to primitive and not wrapper), the resulting native code could at least in theory be the same. Of course this is all theoretical, since that's not a performance hotspot that would even require optimization. – Kayaman Apr 17 '17 at 19:51
  • It will be the same as `Function f1=d -> d>5? 0: 1;`, so you can use this shorter form instead of the verbose syntax variant. But there is no reason to elide auto-boxing in your code example, as skipping the entire operation (as no-one uses the result) is even faster… – Holger Apr 18 '17 at 11:30

3 Answers3

6

I don't see how it could, the upper lambda allows nulls while the lower one doesn't. The compiler would have to do a ton of static code analysis to see if a null could ever be passed to the Function in order to optimize it.

f1.apply(null); //works!
f2.applyAsInt(null); //won't compile!
Raudbjorn
  • 450
  • 2
  • 8
3

Assuming two things, this might happen in the future as far as I can tell. 1) Double and Integer could be value types; thus never null and 2) an AOT javac compiler would be in place.

Not sure if that is feasible still.. That would add a lot of time to the javac total compilation time due to the total number of possibilities and places where optimizations like this could happen.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 1
    I don’t see how this could happen in the future, as this would break the backward compatibility fundamentally. The signature `Function` not only implies reference types which allow `null`, but also assignment compatibility to, e.g. `Function`, which can be used with code that doesn’t cope with value types. – Holger Apr 18 '17 at 11:36
  • @Holger excellent point! After posting I had the same doubts for backward compatibility. The part about `? extends Number` could easily be detected at compile time and simply not optimized in this case I think... – Eugene Apr 19 '17 at 10:08
3

The Java compiler (javac) does not perform such kind of optimizations. In fact, as indicated in Optimization by Java Compiler, it only performs little optimizations in order to let all available information to the JIT compiler.

So if you declare some lambda as Function<Double,Integer>, the bytecode will represent it as such – well, with its raw type, Function.

Now, depending on the context and execution load of that portion of code, the JIT compiler might be able to inline the lambda (or other implementation of that Function) and produce very similar or even identical machine code to what it would produce with the DoubleToIntFunction version.

Note that in that case, the type information disappears entirely. It does not replace one with another.

Community
  • 1
  • 1
Didier L
  • 18,905
  • 10
  • 61
  • 103