javac和Eclipse IDE编译器之间有趣的泛型相关差异

时间:2011-09-01 00:24:55

标签: java eclipse generics

我在javac和Eclipse IDE编译器之间有一个有趣的差异,并且无法弄清楚谁是对的。所以,下面的代码用javac编译,但是Eclipse告诉我静态初始化程序调用“exportAll”是错​​误的,原因是:

  

X类型中的方法exportAll(Iterable< X.Stat<?extends Number>>)不适用于参数(Collection< capture#1-of?extends X.Stat>)

谁是对的? javac还是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());
}

}

3 个答案:

答案 0 :(得分:1)

您的Map<Double, ? extends Stat>.values()类型为Collection<? extends Stat>。这个Stat确实是Stat<?>。您的Iterable要求Stat不仅仅是Stat<?>,而是Stat<? extends Number>。您必须将getPercentiles()更改为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这是我在那些情况下我会做的事情:

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 :(得分:1)

您无法编译您的示例 - 您正在从静态初始化程序中调用非静态方法getPercentiles,因此我将假设它也是一个静态方法。

在任何情况下,如果使用-XLint:unchecked编译,编译器至少会发出“未选中”警告(Stat需要一个类型参数!)。我假设你想要以下内容:

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());
}

我假设您的百分位数是Stat<Double>的任意子类,因此我在地图中将它们声明为? extends Stat<Double>。因此,values()调用将返回Collection<? extends Stat<Double>>

Collection实施Iterable,因此我们在这方面是安全的。但Collection<? extends Stat<Double>>不涵盖Iterable<Stat<? extends Number>>,因此我们需要将参数声明为{{1} }}

Iterable<? extends Stat<? extends Number>> exportAll Iterable<? extends Stat<? extends Number>>的{​​{1}}可能包含各种Map ? extends Stats<N>N的子类。

答案 2 :(得分:-1)

它不能在javac中编译。 (将静态添加到getPercentiles之后)

直截了当地了解事实;不要浪费别人的时间。

今天的孩子,ADD太多了。