Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does using a method reference instead of a lamda result in a compile error in this case?

Tags:

java

I have the following code:

final var fieldValuesStream = items.stream()
                .map(person -> PersonFieldGetter.getFieldValueAsNumber(functionsParameters.getFieldName(), person)) // Number
                .mapToDouble(number -> number.doubleValue());

IDEA highlights "number -> number.doubleValue()" with the message:

Lambda can be replaced with method reference
Replace Lamda with method reference

But when I change the code to .mapToDouble(Number::doubleValue) a compile error happens:

QueryProcessor.java:31:34 java: incompatible types: invalid method reference method doubleValue in class java.lang.Number cannot be applied to given types required: no arguments found: java.lang.Object reason: actual and formal argument lists differ in length

Full source code
Why is this happening?

Project to reproduce the problem

EDIT: Added link to GitHub project with example project that is failing to build using:

IntelliJ IDEA 2021.2.3 (Ultimate Edition)
Build #IU-212.5457.46, built on October 12, 2021
Runtime version: 11.0.12+7-b1504.40 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
SDK: Oracle OpenJDK 17.0.1

like image 931
Mateusz Budzisz Avatar asked Nov 04 '21 10:11

Mateusz Budzisz


People also ask

Is method reference a lambda?

Method references are a special type of lambda expressions. They're often used to create simple lambda expressions by referencing existing methods. There are four kinds of method references: Static methods. Instance methods of particular objects.

What is the use of method reference?

The method references can only be used to replace a single method of the lambda expression. A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same.

What is the use of method reference in java?

Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.

How to convert lambda expression to method reference?

To make the code clearer, you can turn that lambda expression into a method reference: Consumer<String> c = System. out::println; In a method reference, you place the object (or class) that contains the method before the :: operator and the name of the method after it without arguments.

When to use method references instead of lambda expressions?

In those cases, it looks clear to refer to the existing method by name. The method references can do this, they are compact, easy-to-read as compared to lambda expressions. A method reference is the shorthand syntax for a lambda expression that contains just one method call.

What is a lambda expression in Java 8?

Java 8 Object Oriented Programming Programming Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.

Why should I use lambda expressions instead of anonymous classes?

A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same. In general, one doesn’t have to pass arguments to method references.

Do all method references need desugaring?

First, most method references do not need desugaring by the lambda metafactory, they are simply used as the reference method. Under the section "Lambda body sugaring" of the Translation of Lambda Expressions ("TLE") article:


Video Answer


1 Answers

Not an answer, aiming to provide a simplified reproducible example for other to solve the problem.

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List.of(0.1d).stream().map(aDouble -> {
                    return List.of(1).stream().map(p -> aDouble).mapToDouble(Number::doubleValue);
                }
        );
    }
}

Seems the problem is the compiler can't recognize the type of aDouble in the nested stream and cause some strange error.

Some way to make it compiles

  1. Remove return
        Stream.of(0.1d).map(aDouble ->
                List.of(1).stream().map(p -> aDouble).mapToDouble(Double::doubleValue)
        );
  1. Specify type of aDouble
        Stream.of(0.1d).map((Double aDouble) -> {
                    return List.of(1).stream().map(p -> aDouble).mapToDouble(Double::doubleValue);
                }
        );
  1. Not use method reference
        Stream.of(0.1d).map(aDouble -> {
                    return List.of(1).stream().map(p -> aDouble).mapToDouble(d -> d.doubleValue());
                }
        );
like image 195
samabcde Avatar answered Oct 29 '22 05:10

samabcde