6

私はJavaでユーティリティメソッドを書きました:

public static final ImmutableSortedSet<TimeUnit> REVERSED_TIMEUNITS = ImmutableSortedSet.copyOf(
        Collections.<TimeUnit>reverseOrder(),
        EnumSet.allOf(TimeUnit.class)
);


/**
 * Get the number of ..., minutes, seconds and milliseconds
 *
 * You can specify a max unit so that you don't get days for exemple
 * and can get more than 24 hours if you want to display the result in hours
 *
 * The lowest unit is milliseconds
 * @param millies
 * @param maxTimeUnit
 * @return the result map with the higher unit first
 */
public static Map<TimeUnit,Long> getCascadingDateDiff(long millies,TimeUnit maxTimeUnit) {
    if ( maxTimeUnit == null ) {
        maxTimeUnit = TimeUnit.DAYS;
    }
    Map<TimeUnit,Long> map = new TreeMap<TimeUnit,Long>(Collections.<TimeUnit>reverseOrder());
    long restInMillies = millies;
    Iterable<TimeUnit> forUnits = REVERSED_TIMEUNITS.subSet(maxTimeUnit,TimeUnit.MICROSECONDS); // micros not included
    // compute the number of days, then number of hours, then minutes...
    for ( TimeUnit timeUnit : forUnits ) {
        long numberForUnit = timeUnit.convert(restInMillies,TimeUnit.MILLISECONDS);
        map.put(timeUnit,numberForUnit);
        restInMillies = restInMillies - timeUnit.toMillis(numberForUnit);
    }
    return map;
}

それは以下で動作します:

    Map<TimeUnit,Long> map = new TreeMap<TimeUnit,Long>(Collections.reverseOrder());

しかし、私は最初に試しました

    Map<TimeUnit,Long> map = Maps.newTreeMap(Collections.reverseOrder());

私のIntelliJは何も言いませんが、私のコンパイラは次のように言います。

DateUtils.java:[302,48]互換性のないタイプ。型変数K、Vのインスタンスが存在しないため、java.util.TreeMapがjava.util.Mapに準拠します[エラー]が見つかりました:java.util.TreeMap [エラー]が必要です:java.util.Map

コンパレータがなくても正常に動作します。

   Map<TimeUnit,Long> map = Maps.newTreeMap();

しかし、私は試してみました:

Map<TimeUnit,Long> map = Maps.newTreeMap(Collections.<TimeUnit>reverseOrder());

そしてと:

Map<TimeUnit,Long> map = Maps.newTreeMap(new Comparator<TimeUnit>() {
    @Override
    public int compare(TimeUnit timeUnit, TimeUnit timeUnit1) {
        return 0; 
    }
});

そして、私は同じエラーを受け取りました。したがって、TreeMapでコンパレータを使用するたびに、型推論が機能しなくなったようです。なんで?


Guavaメソッドのシグネチャは次のとおりです。

  public static <C, K extends C, V> TreeMap<K, V> newTreeMap(Comparator<C> comparator)

期待される戻り型は型であるため、コンパレータがない場合、JavaはK=TimeUnitおよびV=Longであると推測できます。

タイプTimeUnitのコンパレータを使用すると、JavaはCがTimeUnitであることを認識します。また、期待される戻り型が型であることがわかっているため、K=TimeUnitおよびV=Longです。TimeUnitはTimeUnitを拡張するので、K extends Cは尊重されます(とにかく、間違っていると思われる場合は、オブジェクトコンパレータでも試しました...)

だから私はなぜこの場合型推論が機能しないのか疑問に思いますか?

4

1 に答える 1

7

Michael Laffargueが提案したように、これはOpenJDK6型推論のバグです。

https://bugs.openjdk.java.net/show_bug.cgi?id=100167

http://code.google.com/p/guava-libraries/issues/detail?id=635

私のIntelliJ、バージョン7のOpenJDK、バージョン6のその他のJDKで正常に動作します。


kutschkemの次の提案が機能します。

    Map<TimeUnit,Long> map = Maps.<TimeUnit,TimeUnit,Long>newTreeMap(Collections.<TimeUnit>reverseOrder());

<TimeUnit,TimeUnit,Long>型付きパラメータを明示的に強制できることに注意してください。この関連トピックを確認してください:Javaでのこのジェネリックスの使用法は何ですか?X. <Y> method()

皆さんありがとう

于 2012-06-08T09:22:14.813 に答える