There is No doubt that Generics is one of the most confusing topics in Java, and
you can easily forget concepts and rules, especially if you don't code Java every day. For example, both List<?> and List<Object> looks similar
there is a subtle difference between them, the List<?> is basically a list
of any type, you can assign a list of String like List<String> or list of
Integer i.e. List<Integer> to it. You see the point; it uses the unbounded wildcard <?>, which means any type. It provides it the much needed
Polymorphism requires while writing Generic methods.
Basically, if your method has a type List<?> which means you can pass
any type of List to it, but remember the type is unknown until you assign it
like:
List<?> myList = new List<String>().
Similarly, inside the method, when you try to read values, both List<?> and List<Object> will work, but when you try to add objects, the List<?> will give an error because the type is unknown.
Now, coming back to List<Object>, it's no different than a
List<String> it just that it will only accept Objects instead of
String. Now, since every class in Java extends Object, they are essentially objects, which means you can store any type of Object in this list.
Read
carefully, the List<?> 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.
That's the real difference between List<?> and List<Object> in Java. Now, let's see an example to understand this difference better. If you think Generics is going top of your head, then don't worry, you can always check out my earlier post about The Ultimate Guide of Java Generics for Beginners, where I have covered Generics from scratch and shared many useful points and examples to quickly master key Generics concepts.
That's the real difference between List<?> and List<Object> in Java. Now, let's see an example to understand this difference better. If you think Generics is going top of your head, then don't worry, you can always check out my earlier post about The Ultimate Guide of Java Generics for Beginners, where I have covered Generics from scratch and shared many useful points and examples to quickly master key Generics concepts.
Difference between List<?> vs List<Object> in Java
No concept is complete until we validate our assumption by running some
code. Since I have said that List<?> means you can assign any type of
List to it, it should not throw a compile-time error when we assign
List<String> or List<Integer>, but you cannot do the same with
List<Object>.
Similarly, you can store String, Integer, Float, or
whatever you want into List<Object> but you can't do that with
List<?> because type is unknown. Let's see if these concepts are true or not.
You can see from the above code that you can pass ArrayList<String> and ArrayList<Integer> to the printElements() method but not to printObjects() method because of their different arguments. The first one accepts because it uses List<?> as a method argument which can accept any type of List.
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
printElements(new ArrayList<String>()); // OK
printElements(new ArrayList<Integer>()); // OK
printObjects(new ArrayList<String>());
// NOT OK compile time error
printObjects(new ArrayList<Integer>());
// NOT OK compile time error
}
public static void printElements(List<?> listOfUnknownType) {
listOfUnknownType.add("abc"); // compile time error
for (Object o : listOfUnknownType) {
System.out.println(o); // OK
}
}
public static void printObjects(List<Object> listOfObjects) {
listOfObjects.add("abc"); // OK
listOfObjects.add(101); // OK
for (Object o : listOfObjects) {
System.out.println(o); // OK
}
}
}
You can see from the above code that you can pass ArrayList<String> and ArrayList<Integer> to the printElements() method but not to printObjects() method because of their different arguments. The first one accepts because it uses List<?> as a method argument which can accept any type of List.
The printObjects(List<Object>
listOfObject) throws an error because it can only accept a list of objects and nothing else. This also means you should prefer bounded wildcards while writing API, e.g., method arguments and return types.
Similarly, inside the method, when you try to read values, both List<?> and List<Object> will work, but when you try to add objects, the List<?> will give an error because the type is unknown.
The compiler doesn't know
what types are valid for that List hence it cannot provide type safety
guarantee, hence it throws an error, but this is not the case with
List<Object>. Here compiler does know that it is a list of Object and
since every class, simplicity extends java.lang.Object, you can store anything
in this list like String, Integer, Float etc.
So, the real differnece between List<?> and List<Object> comes depending upon what you are trying to do with them. If you are just reading objects, I mean printing elmeents from a list using enhanced for loop then both are ok, but if you want to add elements then you should use List<Object>.
So, the real differnece between List<?> and List<Object> comes depending upon what you are trying to do with them. If you are just reading objects, I mean printing elmeents from a list using enhanced for loop then both are ok, but if you want to add elements then you should use List<Object>.
Similarly, if you are writing a generic method that should work with any type of list then you should be using wildcards like List<?> as method
arguments. If you still have any doubt then let me know.
No comments:
Post a Comment
Feel free to comment, ask questions if you have any doubt.