为什么番石榴的ImmutableList有很多重载的()方法?
我只是在看番石榴的ImmutableList
,我注意到, of()
方法超载了12次。
在我看来,他们所需要的只是:
static <E> ImmutableList<E> of(); static <E> ImmutableList<E> of(E element); // not even necessary static <E> ImmutableList<E> of(E... elements);
有这么多类似的变化的原因是什么?
可变参数和generics不能很好地结合在一起。 可变参数方法可能会导致带有generics参数的警告,并且重载将阻止该警告,除非极less数情况下要使用of()
将多于11个项添加到不可变列表of()
。
消息来源的评论说:
这些到十一。 之后,您只需获取可变参数表格,并随时随地发出警告。 🙁
请注意,Java 7的@SafeVarargs注释是专门添加的,以消除这种事情的需要。 用@SafeVarargs
注解的单个of(E...)
方法可以被使用,并且不会给出具有通用参数的警告。
还有一个性能原因。 每个可变参数方法的调用都会导致数组的分配和初始化。 如果你不知怎么确定,例如95%的调用是3个或更less的参数,只有5%的4个或更多,然后超载像这样
public static <E> ImmutableList<E> of(); public static <E> ImmutableList<E> of( E e ); public static <E> ImmutableList<E> of( E e1, E e2 ); 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... es );
导致95%的情况下性能提升。 不同的是,案件的平均performance上升。
除了这里的其他很好的答案之外,还有一个微妙的运行时性能优势(除了避免数组分配之外),也就是说,零参数和单参数重载返回的实现被优化用于表示空实例和单实例列表(分别)。
如果我们没有单独的方法重载,只包含一个基于可变参数的方法,那么这个方法看起来像这样:
public static <E> ImmutableList<E> of(E... es) { switch (es.length) { case 0: return emptyImmutableList(); case 1: return singletonImmutableList(es[0]); default: return defaultImmutableList(es); } }
switch case(或者if-else检查)的性能对于大多数调用来说不会有什么坏处,但是对于每次优化只能有方法重载,编译器总是知道要调用哪个超载。 客户端代码没有任何负担,所以这是一个简单的胜利。