强制调用数组以解析为可变参数调用

Forcing call with array to resolve as varargs invocation

好的,所以我有一个像

这样的函数
public static UnorderedList newUnorderedList(Object... items) {
    return new UnorderedList(
        stream(items)
            .peek(e -> checkNotNull(e, "Cannot create null list item"))
            .map(e -> {
                if (e instanceof Component) return newListItem((Component) e);
                if (e instanceof String) return newListItem((String) e);
                throw new IllegalArgumentException("List item must be String or Component but is neither: " + e.getClass().getName());
            }).toArray(ListItem[]::new)
    );
}

(EDIT: 注意:这里的 UnorderedList 是 Vaadin 对 html <ul> 标签的实现,我没有尝试获得 java 列表。)

当你用一个数组调用它时,这将触发一个警告,说不清楚你是想把数组本身当作一个元素还是作为元素的容器。

不要立即看到解决此问题的优雅方法。这些我都不喜欢:

是否有注释或其他内容可以让编译器知道始终将数组解析为对注释方法的可变参数调用? (在方法声明上,而不是调用位置。)

您正在以错误的方式创建 UnorderedList。

假设它是一个集合:

    Object[] objects = new Object[]{1, "hello", "there", "george"};
    LinkedList<AtomicReference<?>> list = Arrays.stream(objects)
            .filter(Objects::nonNull)
            .map(e -> {
                if (e instanceof Integer) return new AtomicReference<>(e);
                if (e instanceof StringBuilder) return new AtomicReference<>(e);
                throw new IllegalArgumentException("PAIN");
            })
            .collect(Collectors.toCollection(LinkedList::new));

从你的问题来看,我猜你想做以下事情:

Object [] items = new Object [x];
items [0] = new Object [] {"Object1", "Object2", "Object3"};
var result = newUnorderedList( items );

这会将包含字符串的数组视为单个项目,从而导致异常,同时调用

var result = newUnorderedList( items [0] );

return 3 个元素用于 result

没有强制将单个数组作为单个项目而不是项目列表来处理的注释。享受这样的签名吧:

Object function( Object [] ... );

您可以重载方法:

public static UnorderedList newUnorderedList(Object first, Object... other) {
    return newUnorderedListImpl(Stream.concat(Stream.of(first), Arrays.stream(other)));
}
public static UnorderedList newUnorderedList(Object[] items) {
    return newUnorderedListImpl(Arrays.stream(items));
}
private static UnorderedList newUnorderedListImpl(Stream<?> items) {
    return new UnorderedList(
        items
            .peek(e -> checkNotNull(e, "Cannot create null list item"))
            .map(e -> {
                if (e instanceof Component) return newListItem((Component) e);
                if (e instanceof String) return newListItem((String) e);
                throw new IllegalArgumentException("List item must be String or Component but is neither: " + e.getClass().getName());
            }).toArray(ListItem[]::new)
    );
}

然后,使用现有数组的调用将在 newUnorderedList(Object[] items) 结束,而实际的可变参数调用将在 newUnorderedList(Object first, Object... other) 结束,即使只指定了一个参数,只要参数不是数组。由于单个参数应该是 StringComponent,这不是问题。

这两种方法失去的唯一可能性是不带参数调用方法的能力。如果这是一个问题,您需要添加另一个重载:

public static UnorderedList newUnorderedList() {
    return newUnorderedListImpl(Stream.empty());
}