Friday, October 22, 2021

What is difference between ArrayList and ArrayList<?> in Java?- Raw Type vs Wildcard Example Tutorial

One of my readers asked me about the difference between ArrayList vs ArrayList< in Java?>, which was actually asked to him in a recent Java development interview. The key difference between them is that ArrayList is not using Generics while ArrayList is a generic ArrayList but they look very similar. If a method accepts ArrayList or ArrayList<?> as a parameter then it can accept any type of ArrayList like ArrayList of String, Integer, Date, or Object, but if you look closely you will find that one is raw type while the other is using an unbounded wildcard. What difference that could make? Well, that makes a significant difference because ArrayList with raw type is not type-safe but ArrayList<?> with the unbounded wildcard is type-safe.

You can add objects of any type into raw ArrayList but you cannot do that with a generic ArrayList with unbounded wildcard i.e. ArrayList, it will be a compile-time error, as we'll see by a code example in this article.

This is one of the very interesting Java Interview questions from Generics and Collection, but unfortunately, I didn't have that one in my list of Java Generics Interview questions but will add it soon.

I really love it whenever I got this kind of interesting question which is both thoughts provoking and really test your knowledge of Java fundamentals. So, if you have such questions, please share them with us too.




Difference between Raw Type vs Unbounded Wildcard ArrayList

Now, let's see a Java program to understand the point I make in the above paragraph. I said, that when you use a raw type ArrayList or ArrayList with an unbounded wildcard as method arguments you can accept any type of ArrayList i.e. your client can pass ArrayList of String, ArrayList of Integer, or ArrayList of Date object, but if you try to add new objects to that list then the raw type will allow but generics list with unbounded wildcard will not allow.

It will throw a compile-time error because it doesn't know which type of ArrayList it has received and be being type-safe it throws an error every time you try to add a new element. You cannot even add a java.lang.Object into a list of unbounded wildcards. 

That's why Effective Java recommends using bounded wildcard and PECS patterns while creating API using generics. They make your API more flexible.

In this program, I have two methods, printWildcardList and printRawTypeList former accepts an ArrayList while later accepts a raw type ArrayList as an argument. Both methods, first print all elements of the given ArrayList by using Java 1.5 enhanced for loop and then try to add new elements to the list. 

You can see that only raw type ArrayList allows that because it is not type-safe. The same operation is prohibited on ArrayList of unbounded wildcards and you will see a compile-time error there.

I know, Generic sometimes can be really confusing, especially if you have a half-knowledge and that's why the interviewer wants to know during an interview. If you can explain the fact that ArrayList is a raw type and not type-safe and ArrayList is type-safe but not flexible and how you can make it flexible e.g. by using bounded wildcards like ArrayList then you will score good marks.

If you are keen to learn Generics, especially core concepts like this then there is no better book than Java Generics and Collection by Maurice Naftalin. I strongly suggest every experienced Java developer read that book not once but twice to get a good knowledge of this key feature.





Java Program to show the difference between ArrayList and ArrayList

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;


/**
 * Java Program to demonstrate difference between ArrayList and ArrayList>
 * 
 * @author WINDOWS 8
 */

public class Test {

    public static void main(String args[]) {
        
        ArrayList<String> names = new ArrayList<String>();
        names.add("Java");
        
        // you can pass any type of ArrayList of to both methods
        printRawTypeList(names);
        printWildcardList(names);
    }
        
    
    /*
     * Java method which takes an ArrayList of raw types
     * and print elements on console
     */
    public static void printRawTypeList(ArrayList rawType){
        for(Object obj : rawType){
            System.out.println(obj);
        }
        
        rawType.add(101); // OK
        rawType.add("101");  // OK
        rawType.add(121.00);  // OK
    }
    
    
    
    /*
     * Java method which prints ArrayList of unbounded wildcard
     */
    public static void printWildcardList(ArrayList<?> unbounded){
        
        // since ? doesn't specify any type, you can simply use object
        for(Object obj : unbounded){
            System.out.println(obj);
        }
        
        unbounded.add(101); // NOT OK
        unbounded.add("101");  //  NOT OK
        unbounded.add(121.00);  // NOT OK

    }
   

}

When you try to run this program in your favorite IDE or command-line you will see a lot of compile-time errors on the places where I have mentioned NOT OK because you cannot add new elements into an ArrayList of unknown type.

Once again, if you are keen to improve your knowledge about Generics, I strongly suggest you read the following items from Effective Java which are related to Generics and Collections:



That's all on the difference between ArrayList and ArrayList in Java. Remember raw type is not type safe but ArrayList with the unbounded wildcard is type safe because you can add any type (String, Integer, Object into ArrayList of raw type, but you cannot add any element on ArrayList of unknown type.


Other Java Generics tutorials you may like to explore
  • How Generics works internally in Java? (tutorial)
  • How to create parameterized classes and methods in Java? (example)
  • 12 Advanced Java Programming Books for Experienced Programmers (books)
  • 10 Tips to become a better Java Programmer (tips)
  • How to prepare for Spring Certification? (guide)
  • 15 Spring Data JPA Interview Questions (spring data jpa questions)
  • 3 Best Practices Java Developers Can learn from Spring (article)
  • Difference between @Autowired and @Injection annotations in Spring? (answer)
  • 5 Spring and Hibernate online courses for Java developers (list)
  • What is the difference between bounded and unbounded wildcards in Generics? (answer)
  • How to implement a single linked list using Generics in Java? (tutorial)
  • 5 Spring Boot courses for Java developers (courses)
  • 5 courses to learn Microservices with Spring Boot and Spring Cloud (courses)
  • 20+ Spring Boot Testing Questions (spring boot testing questions)

Thanks for reading this article. If you like this interview question then please share it with your friends and colleagues. If you have any feedback, suggestion, or interview question which you like to share with us, please drop a comment.

P.S. - Remember, the unbounded wildcard in method argument is inflexible and not recommended and I have only used here for demonstration purpose. You should always follow suggestions given in Effective Java regarding designing a generic API e.g. using bounded wildcards for method arguments.

No comments:

Post a Comment