List vs List<Object>

List is a list of some type you don't know. It could be a List<String>, List<Integer>, etc.
It's effectively equivalent to List<?>, or List<? extends Object>, except that it doesn't document that fact. It's only supported for backwards compatibility.

List<Object> is a list of Objects. Any object of any type can be put inside it, contrary to a List<String>, for example, which only accepts strings.

So no, they're not the same thing.


Why do we lose type safety when using List and not while using List<Object>? Aren't they basically the same thing?

No they are not the same thing.

If you are providing an API,

class API {
  static List<Object> getList() { ... }
  static void modifyList(List<Object> l) { ... }
}

and a client uses it improperly

List<Integer> list = API.getList();
API.modifyList(list);
for (Integer i : list) { ... }  // Invalid

then when your API specifies List<Object> they get a compile-time error, but they don't when API.getList() returns a List and API.modifyList(list) takes a List without generic type parameters.

EDIT:

In comments you mentioned changing

void func(List<Object> s, Object c) { s.add(c); }

to

void func(List s, Object c) { s.add(c); }

so that

func(new List<String>(), "");

would work.

That is violating type safety. The type-safe way to do this is

<T> void func(List<? super T> s, T c) { s.add(c); }

which is basically saying that func is a parameterized function that takes a List whose type can be any super class of T, and a value of type T, and adds the value to the list.


A List<Object> isn't really any more typesafe than a List. However, the Object in the code does imply intent. When someone else looks at it later, they can see that you purposefully chose Object as the type, rather than wondering if you just forgot to put a type or are storing something else and typecasting it elsewhere.

Since code gets read more than it gets written, hints at the intent of the code can be very valuable later on.

Tags:

Java

Generics