5

Interesting compilation error in Lambda Java 8 (Oracle JDK)

java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

I have a method call:

new CSVFile()
.of(new FileInputStream("MyFile.csv"))
.withColumnMapping("name", "fullName", s -> s.toUpperCase())
.withColumnMapping("gender", "gender", s -> s.toUpperCase());

This is the method I'm trying to call:

 public CSVFile withColumnMapping(final String columnName, final String   beanPropertyName, final Function<String, Object> columnTransformFunction) {
    columnMappings.add(new ColumnMapping(columnName, beanPropertyName, Optional.of(columnTransformFunction)));
    return this;
}

Compilation Error I get is:

[ERROR] /Users/sai/fun/reactivecsv/src/test/java/reactivecsv/CSVFileTest.java:[26,50] cannot find symbol
[ERROR] symbol:   method toUpperCase()
[ERROR] location: variable s of type java.lang.Object

Weirdly, This compiles

Function<String, Object> upperCaseConversion = String::toUpperCase;
new CSVFile()
.of(new FileInputStream("MyFile.csv"))
.withColumnMapping("name", "fullName", upperCaseConversion)
.withColumnMapping("gender", "gender", upperCaseConversion);

Why is the compiler not able to synthesise the lambda into a Function ?

user1189332
  • 1,773
  • 4
  • 26
  • 46

1 Answers1

8

When you create new CSVFile() for generic type, it becomes a raw type. You must not use raw types. Creating it as raw type changes all its methods to raw as well, thus withColumnMapping(String, String, Function<String, Object>) becomes withColumnMapping(String, String, Function) and type of your lambda argument cannot be inferred. To fix your problem specify the proper generic arguments when calling the constructor.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334