Interesting generic mismatch between javac and Eclipse IDE compiler

I have an interesting discrepancy between the javac and the Eclipse IDE compiler, and I cannot figure out who is right. So the code below is compiled using javac, however Eclipse tells me that the static invocation initializer from "exportAll" is wrong, because:

The exportAll method (Iterable <X.Stat <? Extends Number β†’) in type X is not applicable for arguments (Collection <capture # 1-of? Extends X.Stat>)

Who is right? javac or eclipse?

import java.util.Map; public class X { interface Stat<T> { } public static void exportAll(Iterable<Stat<? extends Number>> vars) { } public static Map<Double, ? extends Stat> getPercentiles() { return null; } static { exportAll(getPercentiles().values()); } 

}

+4
source share
3 answers

It does not compile in javac. (after adding statics to getPercentiles)

Get your facts straight; do not waste time with other people.

Kids today, ADD too much.

-1
source

Your Map<Double, ? extends Stat>.values() Map<Double, ? extends Stat>.values() will be of type Collection<? extends Stat> Collection<? extends Stat> . This Stat really Stat<?> . Your Iterable requires that Stat not just the old Stat<?> , But rather Stat<? extends Number> Stat<? extends Number> . You will need to change getPercentiles() to Map<Double, ? extends Stat<? extends Number>> Map<Double, ? extends Stat<? extends Number>> Map<Double, ? extends Stat<? extends Number>> .

 public static void exportAll(Iterable<Stat<? extends Number>> vars) { } // ^ this must match // your values type on the map public Map<Double, ? extends Stat<? extends Number>> getPercentiles() { return null; } 

@emboss here, what would I do when I could:

 class Main { static interface Something<E> { void doSomething(); } static class ConcreteSomething<E> implements Something<E> { E data; ConcreteSomething(E data) { this.data = data; } public void doSomething() { System.out.println(data); } } public static void main(String[] args) { List<Something<Number>> list = new LinkedList<Something<Number>>(); list.add(new ConcreteSomething<Number>(Math.PI)); // an autoboxed Double list.add(new ConcreteSomething<Number>(new Integer(5))); // an Integer for(Something<Number> s : list) s.doSomething(); } } 
+1
source

You cannot compile your example - you call the non-static getPercentiles method from a static initializer, so I also assume that it is also a static method.

In any case, your compiler at least spat out the "unchecked" warning if you compiled with -XLint:unchecked (Stat accepts a type parameter!). I assume you would like to:

 public class X { interface Stat<T> { } public static void exportAll(Iterable<? extends Stat<? extends Number>> vars) { } public static Map<Double, ? extends Stat<Double>> getPercentiles() { return null; } static { exportAll(getPercentiles().values()); } 

I assume your percentiles are an arbitrary subclass of Stat<Double> , so I declared them as ? extends Stat<Double> ? extends Stat<Double> on the Map. So calling values() returns Collection<? extends Stat<Double>> Collection<? extends Stat<Double>> .

Collection implements Iterable , so we are safe on this side. But Collection<? extends Stat<Double>> Collection<? extends Stat<Double>> not covered by Iterable<Stat<? extends Number>> Iterable<Stat<? extends Number>> , so we need to declare the argument as Iterable<? extends Stat<? extends Number>> Iterable<? extends Stat<? extends Number>> Iterable<? extends Stat<? extends Number>> .

The beauty (well, except the syntax) of having exportAll accepts Iterable<? extends Stat<? extends Number>> Iterable<? extends Stat<? extends Number>> Iterable<? extends Stat<? extends Number>> , is that your Map can contain all kinds of ? extends Stats<N> ? extends Stats<N> , where N is a subclass of Number .

+1
source

All Articles