FULL PRODUCT VERSION :
java version "1.8.0_20-ea"
Java(TM) SE Runtime Environment (build 1.8.0_20-ea-b23)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b22, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
OS X 10.9.4
A DESCRIPTION OF THE PROBLEM :
Some combination of generics and the new Stream APIs is not compiling with 8u20 b23 this is code that compiles find with 8u11. The error reported is: "no suitable method found", but the 8u11 compiler find a the correct method and the code runs as expected.
REGRESSION. Last worked in version 8u11
ADDITIONAL REGRESSION INFORMATION:
This version is working:
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The code being compiled is:
Class<? extends StandardRootBean> genericFindClass = null;
// most of these classes implement the SoftDelete interface (defined below)
if( StringUtils.equals(entityName, Agent.class.getName()) ) {
genericFindClass = AgentBean.class;
} else if( StringUtils.equals(entityName, PluginsRepo.class.getName()) ) {
genericFindClass = PluginsRepoBean.class;
} else if( StringUtils.equals(entityName, TestSuite.class.getName()) ) {
genericFindClass = TestSuiteBean.class;
} else if( StringUtils.equals(entityName, TestSubmission.class.getName()) ) {
genericFindClass = TestSubmissionBean.class;
} else if( StringUtils.equals(entityName, User.class.getName()) ) {
genericFindClass = UserBean.class;
} else {
throw new WebServiceException("Unhandled findAll class: "+entityName);
}
if( genericFindClass != null ) {
// Classes that just use the DB findAll() method...
List<?> dbList = db.findAll(genericFindClass, null);
// Filter deleted elements if applicable
if( SoftDelete.class.isAssignableFrom(genericFindClass) ) {
dbList = dbList.stream().filter( o-> !((SoftDelete)o).isDeletedFlag() ).collect( Collectors.toList()); // <-- error on this line with 8u20
}
GenericContainer result = new GenericContainer(
modelMapper.toXmlLayer( dbList ));
return result;
}
This line compiles fine with 8u11 and produces the error message below in 8u20 b23
SoftDelete is an interface defined as:
public interface SoftDelete {
public boolean isDeletedFlag();
public void setDeletedFlag(boolean deletedFlag);
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Successful compile
ACTUAL -
Users/scott/dev/TestAutomationServer/TASWebService/src/main/java/ca/digitalrapids/tas/ws/TASWS.java:149: error: no suitable method found for collect(Collector<Object,CAP#1,List<Object>>)
dbList = dbList.stream().filter( o-> !((SoftDelete)o).isDeletedFlag() ).collect( Collectors.toList());
^
method Stream.<R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super CAP#2>,BiConsumer<R#1,R#1>) is not applicable
(cannot infer type-variable(s) R#1
(actual and formal argument lists differ in length))
method Stream.<R#2,A>collect(Collector<? super CAP#2,A,R#2>) is not applicable
(cannot infer type-variable(s) R#2,A,CAP#3,T#2
(argument mismatch; Collector<CAP#2,CAP#4,List<CAP#2>> cannot be converted to Collector<? super CAP#2,CAP#4,List<CAP#2>>))
where R#1,T#1,R#2,A,T#2 are type-variables:
R#1 extends Object declared in method <R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super T#1>,BiConsumer<R#1,R#1>)
T#1 extends Object declared in interface Stream
R#2 extends Object declared in method <R#2,A>collect(Collector<? super T#1,A,R#2>)
A extends Object declared in method <R#2,A>collect(Collector<? super T#1,A,R#2>)
T#2 extends Object declared in method <T#2>toList()
where CAP#1,CAP#2,CAP#3,CAP#4 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?
CAP#3 extends Object from capture of ?
CAP#4 extends Object from capture of ?
1 error
:TASWebService:compileJava FAILED
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Users/scott/dev/TestAutomationServer/TASWebService/src/main/java/ca/digitalrapids/tas/ws/TASWS.java:149: error: no suitable method found for collect(Collector<Object,CAP#1,List<Object>>)
dbList = dbList.stream().filter( o-> !((SoftDelete)o).isDeletedFlag() ).collect( Collectors.toList());
^
method Stream.<R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super CAP#2>,BiConsumer<R#1,R#1>) is not applicable
(cannot infer type-variable(s) R#1
(actual and formal argument lists differ in length))
method Stream.<R#2,A>collect(Collector<? super CAP#2,A,R#2>) is not applicable
(cannot infer type-variable(s) R#2,A,CAP#3,T#2
(argument mismatch; Collector<CAP#2,CAP#4,List<CAP#2>> cannot be converted to Collector<? super CAP#2,CAP#4,List<CAP#2>>))
where R#1,T#1,R#2,A,T#2 are type-variables:
R#1 extends Object declared in method <R#1>collect(Supplier<R#1>,BiConsumer<R#1,? super T#1>,BiConsumer<R#1,R#1>)
T#1 extends Object declared in interface Stream
R#2 extends Object declared in method <R#2,A>collect(Collector<? super T#1,A,R#2>)
A extends Object declared in method <R#2,A>collect(Collector<? super T#1,A,R#2>)
T#2 extends Object declared in method <T#2>toList()
where CAP#1,CAP#2,CAP#3,CAP#4 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?
CAP#3 extends Object from capture of ?
CAP#4 extends Object from capture of ?
1 error
:TASWebService:compileJava FAILED
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.*;
import java.util.stream.Collectors;
interface SoftDelete {
public boolean isDeletedFlag();
public void setDeletedFlag(boolean deletedFlag);
}
class A implements SoftDelete {
private boolean deleted;
public boolean isDeletedFlag() {
return deleted;
}
public void setDeletedFlag(boolean deletedFlag) {
this.deleted = deletedFlag;
}
}
class B extends A {
public String toString() { return "B";}
}
class C extends A {
public String toString() { return "C";}
}
public class Test {
public static void main(String [] args) throws RuntimeException {
Class<? extends A> genericFindClass = null;
if( args.length == 1) {
genericFindClass = A.class;
} else {
genericFindClass = B.class;
}
if( genericFindClass != null ) {
List<?> dbList = findStuff(genericFindClass);
// Filter deleted elements if applicable
if( SoftDelete.class.isAssignableFrom(genericFindClass) ) {
dbList = dbList.stream().filter( o-> !((SoftDelete)o).isDeletedFlag() ).collect( Collectors.toList());
}
for (Object o : dbList) {
System.out.println(o);
}
}
}
static List<?> findStuff(Class someType) {
List list = new ArrayList();
if (someType == B.class)
list.add(new B());
else if (someType == C.class)
list.add(new C());
return list;
}
}
---------- END SOURCE ----------