问题 为什么Guava类提供了如此多的工厂方法而不是只提供varargs的方法? [重复]


可能重复:
为什么Guava的ImmutableList有这么多重载的()方法? 

看着番石榴 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等人。把这些方法放在那里是出于真正的原因。谁能解释(或推测)这个理由可能是什么?


11942
2017-11-30 14:39


起源

如果库较旧,我会怀疑这些方法是在Java 5.0之前编写的。原始代码可能是旧的,并且没有被重构。 - Peter Lawrey
@Peter:不要介意它会破坏向后兼容性以删除它们(代码将链接到不再存在的方法),这可能是他们不想要的。虽然他们至少可以被弃用,但事实如此。 - Mark Peters
具体而言,@ Mark是不推荐使用的(E [])构建器。 ;) - Peter Lawrey
@Peter: of(E[]) 不赞成使用更具描述性的内容 copyOf(E[]) 我相信。而且我认为Guava中没有任何东西使用1.5之前的风格。 - ColinD
“我的一些同事认为这很愚蠢......”我笑了,因为没有人发现它比我们真正想要它的人更愚蠢。 :) - Kevin Bourrillion


答案:


评论中 资源 说:

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

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


10
2017-11-30 15:03





我认为这是要避免的 unchecked generic array creation 警告何时 E 是一种通用类型。


3
2017-11-30 14:48



我不确定这是不是原因,但这肯定是一个相关的考虑因素。这是愚蠢的,但是目前在Java中你会得到这个警告 呼叫 使用泛型类型的varargs方法,这是荒谬的,因为作为调用者,您永远不能与通过varargs调用方法创建的数组交互。我相信Java 7或8都会引入一个更改来将警告移到方法声明中。 - Mark Peters


这是为了避免为最常见的用例创建varargs数组的开销。这是以这种方式建模的 EnumSet.of(..) 被设计。


0
2017-11-30 14:45



我不能这样,因为这些方法在内部调用相同的vararg方法。 - axtavt
在Effective Java中有一章讨论这个问题,但我似乎无法在互联网上找到它。 - Valentin Rocher


实际上编译器非常愚蠢,JVM具有大部分智能,但它仍然不够智能,无法为vararg创建阵列。

是否真的值得保存阵列,也许是作者不希望用户担心的事情。也就是说,他可能知道它没有多大区别,但并非所有用户都会意识到99%的时间都不值得担心。

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


-1
2017-11-30 14:49



Vararg参数 是 数组,所以当然不可能不为varargs参数创建数组。无论如何, ImmutableList 在内部为所有这些重载构造varargs数组(单元素列表除外)。 - ColinD


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

如果我们只有,

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
2017-11-30 15:01



编译器将使用与调用匹配的最具体方法...在本例中,选项1。 - ColinD
另外,如果这就是所需要的,那就像过载一样 of(E, E, E...)。 - ColinD