Why do we lose type safety when using List
and not while using List<Object>
? Aren't they basically the same thing?
EDIT: I found that the following gives a compilation error
public class TestClass
{
static void func(List<Object> o, Object s){
o.add(s);
}
public static void main(String[] args){
func(new ArrayList<String>(), new Integer(1));
}
}
whereas this doesn't
public class TestClass
{
static void func(List o, Object s){
o.add(s);
}
public static void main(String[] args){
func(new ArrayList<String>(), new Integer(1));
}
}
Why?
means you can assign any type of List to it and List<Object> means you can store any type of object into it. That's the real difference between List<?> and List<Object> in Java.
The difference to List now is that List is untyped and therefore no type checks at all are performed, which ultimately leads to certain warnings and can lead to weird runtime behavior. While Java knows that List<Object> is a list that might contain anything, it doesn't know that about a List .
In category theory, an abstract branch of mathematics, and in its applications to logic and theoretical computer science, a list object is an abstract definition of a list, that is, a finite ordered sequence.
Lists are objects too. An important method for lists is append(item).
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 usingList<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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With