Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguity error while trying to print result of JAVA8 Collector

I am getting Ambiguity error while trying to print result of JAVA8 collectors.

I am trying to print result of summation of IDs in Product object, but getting the following error :

"The method println(double) is ambiguous for the type PrintStream"

Here is a small line of code where I am getting the compilation error:

Edited : Adding code snippet for more details :

  1. Product.java domain class.

package com.sample.reproduce.bugs;

public class Product {

    private double id;

    private String productName;

    public double getId() {
        return id;
    }

    public void setId(double id) {
        this.id = id;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

}
  1. Main.java class where I am getting compilation error :

Following is the line of code where I am getting compilation error :

System.out.println(productList.stream().collect(Collectors.summingDouble(x -> x.getId())));

Class Snapshot :

enter image description here

I don't get any error if I will use Collector in a separate line (out of println method).

Why ins't the compiler able to detect the exact return type of JAVA 8 Collectors if we use it in println() method?

Adding details of another approach with command prompt :

I tried with command prompt with same JDK version and the program was compiled and executed successfully. So the answer by Holger seems correct. This seems issue only with Eclipse compiler :

enter image description here

like image 391
Gunjan Shah Avatar asked Dec 18 '22 18:12

Gunjan Shah


1 Answers

This is a bug in the Eclipse compiler, and the rabbit hole goes even deeper than the compiler error. I reduced your code example to

public static void main(String[] args)
{
  println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) {}
public static void println(char[] x) {}
public static void println(String x) {}
public static void println(Object x) {}

I only kept the the println methods affecting the behavior of the compiler.

There are the methods println(Object x), which is the one which should be invoked, as it is the only one applicable without boxing operations, println(double), which is the one mentioned in the error message and applicable after unboxing, and the two methods println(char[] x) and println(String x), which are not applicable at all.

Removing the println(double x) method makes the error go away, which would be understandable, even if the error is not correct, but weirdly, removing the println(Object x) method does not solve the error.

And even worse, removing either of the inapplicable methods, println(char[] x) or println(String x), also removes the error, but generates code invoking the wrong, inapplicable method:

public static void main(String[] args)
{
  println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) { System.out.println("println(double)"); }
public static void println(char[] x) { System.out.println("println(char[])"); }
//public static void println(String x) { System.out.println("println(String)"); }
public static void println(Object x) { System.out.println("println(Object)"); }
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to [C
    at Tmp2.main(Unknown Source)
public static void main(String[] args)
{
  println(Stream.of(42).collect(Collectors.summingDouble(d -> d)));
}
public static void println(double x) { System.out.println("println(double)"); }
//public static void println(char[] x) { System.out.println("println(char[])"); }
public static void println(String x) { System.out.println("println(String)"); }
public static void println(Object x) { System.out.println("println(Object)"); }
Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
    at Tmp2.main(Unknown Source)

I think, we don’t need to dig into the depth of the formal Java Language Specification, to recognize this behavior as inappropriate.

Removing both inapplicable methods, println(char[] x) and println(String x), makes the compiler choose the correct method, println(Object x) over println(double x), but that’s not impressive.

For reference, I tested with version Oxygen.3a Release (4.7.3a), build 20180405-1200. There are likely other versions affected as well.

like image 80
Holger Avatar answered Apr 30 '23 12:04

Holger