1
private static Iterable<Object> iterable(
        final Object first, final Object second, final Object[] rest) {
    checkNotNull(rest);
    return new AbstractList<Object>() {
        @Override
        public int size() {
            return rest.length + 2;
        }

        @Override
        public Object get(int index) {
            switch (index) {
                case 0:
                    return first;
                case 1:
                    return second;
                default:
                    return rest[index - 2];
            }
        }
    };
}

What is author's purpose?

I guess he wants to make use of the array generated by compiler, rather than new an ArrayList.

But still a confusing point, why not write as below?

private static Iterable<Object> iterable(final Object[] rest) {
    checkNotNull(rest);
    return new AbstractList<Object>() {
        @Override
        public int size() {
            return rest.length;
        }

        @Override
        public Object get(int index) {
            return rest[index];
        }
    };
}
aoyuan zhu
  • 57
  • 6

1 Answers1

2

The point here is that this method is called from public methods which look like (source):

  public final String join(
      @NullableDecl Object first, @NullableDecl Object second, Object... rest) {
    return join(iterable(first, second, rest));
  }

Using signatures like this is a trick to force you to pass in at least two arguments - after all, if you've not got two arguments, there is nothing to join.

For example:

Joiner.on(':').join();  // Compiler error.
Joiner.on(':').join("A");  // Compiler error.
Joiner.on(':').join("A", "B");  // OK.
Joiner.on(':').join("A", "B", "C");  // OK.
// etc.

This iterable method just creates an Iterable without having to copy everything into a new array. Doing so would be O(n) in the number of arguments; the approach taken here is O(1).

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • What's surprising to me is that they didn't call [`Lists.asList()`](https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/Lists.html#asList-E-E-E:A-). The implementation is nearly identical. – shmosel Jan 19 '18 at 04:11
  • 2
    @shmosel it might be because `Joiner` and `Lists` are in separate packages; having `Joiner` use `Lists` would introduce a cyclical dep between the packages, that would prevent you building one without the other, necessarily increasing binary size. – Andy Turner Jan 19 '18 at 06:53
  • 3
    Yep, it's a cyclic dependencies thing. – Louis Wasserman Jan 20 '18 at 04:19