14

When I initialize List, I am able to do this:

List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});

But when I want to simplify it using Arrays.asList:

List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286});

It cannot compile with error:

incompatible types: inference variable T has incompatible bounds
equality constraints: java.lang.Object[]
lower bounds: java.lang.Object

Why it cannot do the type inference right and how to fix this?

2
  • related stackoverflow.com/questions/1248763/arrays-aslist-of-an-array Commented Oct 6, 2016 at 7:04
  • 2
    As a general rule of thumb, never mix generics and arrays. (You are allowed to disregard this rule once you understand why it's a good rule of thumb in the first place.) Commented Oct 6, 2016 at 7:06

7 Answers 7

14

Remember that ... is just syntactic sugar for an array parameter. You can call a method with a variadic parameter foo(Object...) either using

foo("hello", 1);

or

foo(new Object[]{"hello", 1});

since the compiler constructs the second form anyway.

Because the receiver type isn't considered when the compiler infers types, it looks at Arrays.asList(new Object[]{"bar", 286}) and thinks that you mean to create a list of Object, not a singleton list of Object[].

The easiest way with your existing syntax is just to add an explicit type parameter:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});

Adding the <Object[]> tells the compiler what T should be.

Or, if you don't need the list to be mutable:

List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});
Sign up to request clarification or add additional context in comments.

Comments

13

When you pass an array of reference types to Arrays.asList you get a List of that reference type.

Therefore Arrays.asList(new Object[]{"bar", 286}) returns a List<Object>, not a List<Object[]>.

Comments

7

If your list only has one element in it, Collections.singletonList(new Object[] {...}) is a better choice, as it avoids varargs and makes the behavior more obvious at the call site.

Comments

4

The problem is that Arrays.asList is a varargs method which technically receives an array containing the arguments and due to compatibility with pre-generics code still accepts an array instead of an argument list. When passing a single array, the call is ambiguous and will be handled like a pre-varargs method invocation.

The problem disappears when you have more than one argument:

List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}, new Object[]{"baz", 123});

If you have only one argument you can aid the compiler by inserting an explicit list element type:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});

Alternatively, you can use

List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});

to create an immutable list of size one. Note that this differs from Arrays.asList, as the latter returns a list of fixed size but still mutable via set.

Comments

2

Arrays#asList signature:

public static <T> List<T> asList(T... a)

The return type is List<T>. Now you should ask yourself what is T?

T is Object, so the return type will be List<Object>, and not List<Object[]>.

Comments

1

Your call:

Arrays.asList(new Object[]{"bar", 286});

creates a list out of the Object[]. So the data is convertet into a new List<Object>.

So Arrays.asList(new Object[]{"bar", 286}).get(0); will return "bar".

In this call:

List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});

you are creating a List<Object[]> (2Dimensional) and add one element after it: foo.add(..);. Therefore you are adding one element consisting of an Object[]. if you now call foo.get(0); you will get a Object[] consisting of: 816, "foo", 2.6

I think you wanted to do:

Object[] oa = new Object[]{""};
Object[] ob = new Object[]{""};
List<Object[]> list = Arrays.asList(oa, ob);

If you have questions, feel free to ask me :)

Comments

1

When you use List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}); you actually have a two dimensional Array and you cand resolve that problem by doing List<Object[]> bar = Arrays.asList(new Object[][]{new Object[]{"bar","asd",123}});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.