【问题标题】:Why do Guava classes provide so many factory methods instead of just one that takes varargs? [duplicate]为什么 Guava 类提供了这么多工厂方法,而不仅仅是一个采用可变参数的方法? [复制]
【发布时间】:2010-11-30 14:39:52
【问题描述】:

可能重复:
Why does Guava's ImmutableList have so many overloaded of() methods?

查看 Guava 的 ImmutableList(和其他一些类),您会发现大量重载的 of 便捷方法(“按顺序返回包含给定元素的不可变列表。”)它们采用不同数量的参数:

...
public static <E> ImmutableList<E> of(E e1, E e2, E e3) 
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) 
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) 
... 

一直到这个:

public static <E> ImmutableList<E> of(E e1,
                                      E e2,
                                      E e3,
                                      E e4,
                                      E e5,
                                      E e6,
                                      E e7,
                                      E e8,
                                      E e9,
                                      E e10,
                                      E e11,
                                      E e12,
                                      E... others) 

我的一些同事认为这很愚蠢,想知道为什么不只有一种方法:of(E... elements)。他们怀疑这是一种指导不当的性能“优化”,属于“你认为你比编译器更聪明”之类的类别。

我的预感是 Kevin Bourrillion 等人。出于真正的原因将这些方法放在那里。谁能解释(或推测)这个原因可能是什么?

【问题讨论】:

  • 如果库较旧,我怀疑这些方法是在 Java 5.0 之前编写的。原始代码可能太旧了,还没有被重构。
  • @Peter:不要介意删除它们会破坏向后兼容性(代码将与不再存在的方法链接),这是他们可能不想要的。尽管它们至少可以被弃用,但就是这样。
  • @Mark,具有讽刺意味的是,不推荐使用的是 of(E[]) 构建器。 ;)
  • @Peter: of(E[]) 已被弃用,而我相信更具有描述性的 copyOf(E[])。而且我认为 Guava 中没有任何东西使用 1.5 之前的样式。
  • “我的一些同事认为这很愚蠢……”我笑了,因为没有人比我们真正做到这一点更愚蠢。 :)

标签: java guava variadic-functions


【解决方案1】:

source 中的评论说:

// These go up to eleven. After that, you just get the varargs form, and
// whatever warnings might come along with it. :(

所以,之所以这样做,是因为 varargs 方法会产生带有泛型参数的警告。

【讨论】:

    【解决方案2】:

    我认为当E 是泛型类型时避免unchecked generic array creation 警告。

    【讨论】:

    • 我不确定这是否是原因,但这肯定是一个相关的考虑因素。这很愚蠢,但目前在 Java 中,当您使用泛型类型调用 varargs 方法时,您会收到此警告,这很荒谬,因为作为调用者,您永远无法与通过varargs 调用方法创建的数组进行交互.我相信 Java 7 或 8 都会引入更改,将警告移至方法声明。
    【解决方案3】:

    这是为了避免为最常见的用例创建可变参数数组的开销。这是根据 EnumSet.of(..) 的设计方式建模的。

    【讨论】:

    • 我不能这样,因为这些方法在内部调用相同的可变参数方法。
    • Effective Java 里面有一章讲这个,但是我好像在网上找不到。
    【解决方案4】:

    实际上编译器真的很笨,JVM 拥有大部分的智能,但它仍然不够智能,无法消除为可变参数创建数组的需要。

    保存数组是否真的值得,也许是作者不想让用户担心的事情。也就是说,他可能知道这并没有太大区别,但并非所有用户都可能在 99% 的情况下都意识到它不值得担心。

    当它是 google-collections 时,这是描述“标准集合类型的高性能不可变实现,例如 ImmutableSet”的一部分

    【讨论】:

    • 可变参数数组,所以当然不可能不为可变参数创建数组。不管怎样,ImmutableList 在内部为所有这些重载构造了可变参数数组(除了单元素列表)。
    【解决方案5】:

    我能想到的是避免被编译器混淆。

    如果我们只有,

    public static ImmutableList<E> of(E element); //Option 1
    

    public static ImmutableList<E> of(E... elements);  //Option 2
    

    在你的代码中我们有

    ImmutableList<String> list = ImmutableList.of("Value");
    

    编译器不知道是调用选项 1 还是选项 2。

    Josh Bloch、Kevin Bourrillion 和他的团队认为使用“可笑”of(...) 方法一定有正当理由。

    【讨论】:

    • 编译器将使用与调用匹配的最具体的方法...在本例中为选项 1。
    • 另外,如果只需要这些,它只需要像 of(E, E, E...) 这样的重载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 2016-03-05
    • 2012-03-16
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多