No.
The List API is identical regardless of whether a List is expandable or not, something that was deliberate.
There is also nothing in the List API that allows you to query it to determine this feature.
You can't completely reliably determine this information by reflection, because you will be depending on internal details of the implementation, and because there is an unbounded number of classes that are potentially fixed-size. For example, in addition to Arrays.asList
, there is also Arrays.asList().subList
, which happens to return a different class. There can also be wrappers around the base list like Collections.checkedList
, Collections.synchronizedList
and Collections.unmodifiableList
. There are also other fixed-size lists: Collections.emptyList
, Collections.singletonList
, and Collections.nCopies
. Outside the standard library, there are things like Guava's ImmutableList
. It's also pretty trivial to hand-roll a list for something by extending AbstractList
(for a fixed-size list you need only implement the size()
and get(int)
methods).
Even if you detect that your list is not fixed-size, the specification of List.add
allows it to refuse elements for other reasons. For example, Collections.checkedList
wrappers throw a ClassCastException
for elements of unwanted type.
And even if you know your list is expandable, and allows arbitrary elements, that doesn't mean you want to use it. Perhaps it's synchronized, or not synchronized, or isn't serializable, or it's a slow linked list, or has some other quality that you don't want.
If you want control over the type, mutability, serializability, or thread-safety of the list, or you want to be sure that no other code has kept a reference to it, the practice is that you create a new one yourself. It's not expensive to do so when unnecessary (memcopies are blazing fast), and it lets you reason more definitely about your code will actually do at runtime. If you'd really like to avoid creating unnecessary copies, try whitelisting instead of blacklisting list classes. For example:
if (list.getClass() != ArrayList.class) {
list = new ArrayList<>(list);
}
(Note: That uses getClass
instead of instanceof
, because instanceof
would also be true for any weird subclasses of ArrayList
.)