Collections.min/max方法的签名

发布于 2024-09-03 06:48:43 字数 457 浏览 3 评论 0原文

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

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

它的签名因其对泛型的高级使用而闻名, 以至于在《Java in a Nutshell》一书中提到过 以及官方的 Sun 泛型教程

但是,我找不到以下问题的令人信服的答案:

为什么形式参数是 Collection< 类型?扩展 T>,而是 比集合?有什么额外的好处?

In Java, the Collections class contains the following method:

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

Its signature is well-known for its advanced use of generics,
so much that it is mentioned in the Java in a Nutshell book
and in the official Sun Generics Tutorial.

However, I could not find a convincing answer to the following question:

Why is the formal parameter of type Collection<? extends T>, rather
than Collection<T>? What's the added benefit?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

何处潇湘 2024-09-10 06:48:43

类型推断是一个棘手的话题,我承认我对此了解不多。但是,请检查此示例:

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将是推断的类型。

Type inference is a tricky topic that I'll admit that I don't know that much about. However, examine this example:

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;
   //}
}

Consider that the first signature of min() allows the call to compile whereas the second does not. This isn't a very practical example, since one must ask why I would be explicitly typing the method to <B>, but perhaps there is an implicit inference where B would be the inferred type.

怀念你的温柔 2024-09-10 06:48:43

? 的好处之一是它禁止向 Collection 添加项目

One benefit of the ? is that it prohibits additions of items to the Collection

晨曦÷微暖 2024-09-10 06:48:43

我认为它实际上并没有为您提供此方法的更多信息,但是当 T 是类的一部分而不仅仅是静态方法时,这是一个好习惯。

他们将其包含在这里,以便它可以成为新的约定,其中每个泛型都应该扩展为 ?

T 类应该遵循 PECS:什么是 PECS(生产者扩展消费者超级)?

但静态方法不需要(至少参数,返回值应该总是)

I think it actually doesn't give you anything more for this method, however its a good habit to get into when T is part of the class and not just a static method.

They are including it here so it can become the new convention where every generic should be extended by ?

A class of T should follow PECS: What is PECS (Producer Extends Consumer Super)?

But a static method doesn't need to (at least the parameters, the return value should always)

护你周全 2024-09-10 06:48:43

这是为了支持 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 章

This is to support a legacy signature of the method in Java 1.4 ( and before ).

Prior to Java 5 the signature for these methods was

public static Object min ( Collection c );

With multiple bounds the erasure rules make the first bound the raw type of the method, so without Object & the signature would be

public static Comparable min ( Collection c );

and legacy code would break.

This is taken from O'Reilly's Java Generics and Collections book, chapter 3.6

暖树树初阳… 2024-09-10 06:48:43

根据我对 Mark 的回答的评论,如果您有类似的内容,

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 Play.min(Collection c))。如果您将 min(Collection) 保留为不带扩展部分,则 Play.min(coll) 将具有以下签名 ? extends A Play.min(Collection c) 不太清楚。

Building on the comments I put on Mark's answer, if you have something like

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

It's clearer that min returns an object of type A (the actual signature is <A> A Play.min(Collection<? extends A> c) ). If you leave min(Collection<T>) without the extends part then Play.min(coll) will have the following signature <? extends A> ? extends A Play.min(Collection<? extends A> c) which isn't as clear.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文