簡體   English   中英

Collections.min / max方法的簽名

[英]Signature of Collections.min/max method

在Java中,Collections類包含以下方法:

public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)

它的簽名因其對泛型的高級使用而聞名,因此在Java的Nutshell書籍和官方的Sun Generics Tutorial中都提到了它。

但是,我無法找到以下問題的令人信服的答案:

為什么Collection<? extends T>的形式參數Collection<? extends T> Collection<? extends T> ,而不是Collection<T> 還有什么好處?

類型推斷是一個棘手的話題,我承認我不太了解。 但是,請檢查此示例:

public class ScratchPad {
   private static class A implements Comparable<A> {
     public int compareTo(A o) { return 0; }
   }
   private static class B extends A {}
   private static class C extends B {}

   public static void main(String[] args)
   {
     Collection<C> coll = null;
     B b = Scratchpad.<B>min(coll);
   }

   public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)  {
     return null;
   }

   //public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
   //  return null;
   //}
}

考慮min()的第一個簽名允許調用編譯而第二個簽名不允許。 這不是一個非常實際的例子,因為我必須問為什么我會明確地將方法鍵入<B> ,但也許有一個隱式推理,其中B將是推斷類型。

一個好處是? 是它禁止添加項目Collection

我認為它實際上並沒有為這個方法提供更多的東西,但是當T是類的一部分而不僅僅是靜態方法時,它是一個很好的習慣。

他們在這里包括它,所以它可以成為新的約定,每個通用應該擴展?

一類T應遵循PECS: 什么是PECS(Producer擴展消費者超級)?

但是靜態方法不需要(至少參數,返回值應該總是)

這是為了支持Java 1.4(以及之前)中方法的遺留簽名。

在Java 5之前,這些方法的簽名是

public static Object min ( Collection c );

使用多個邊界時,擦除規則使第一個綁定方法的原始類型,因此沒有Object &簽名就可以了

public static Comparable min ( Collection c );

和遺留代碼會破裂。

這取自O'Reilly的Java Generics and Collections一書,第3.6章

根據我對馬克答案的評論,如果你有類似的話

class Play {
    class A implements Comparable<A> {
        @Override
        public int compareTo(A o) {
            return 0;
        }
    }

    class B extends A {
    }

    class C extends A {
    }

    public static <T extends Object & Comparable<? super T>> T min(
            Collection<? extends T> c) {
        Iterator<? extends T> i = c.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) < 0)
                candidate = next;
        }
        return candidate;
    }

    public static List<? extends A> getMixedList() {
        Play p = new Play();
        ArrayList<A> c = new ArrayList<A>();
        c.add(p.new C());
        c.add(p.new B());
        return c;
    }

    public static void main(String[] args) {
        ArrayList<A> c = new ArrayList<A>();
        Collection<? extends A> coll = getMixedList();
        A a = Play.min(coll);
    }
}

min更清楚的是返回A類型的對象(實際簽名是<A> A Play.min(Collection<? extends A> c) )。 如果你離開min(Collection<T>)沒有extends部分,那么Play.min(coll)將具有以下簽名<? extends A> ? extends A Play.min(Collection<? extends A> c) <? extends A> ? extends A Play.min(Collection<? extends A> c) <? extends A> ? extends A Play.min(Collection<? extends A> c) ,這個不太清楚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM