Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not call function using List<SuperType> parameter with List<SubType>

I created following function in Utils class:

public class Utils{
    public static String getUserIdCSVs(List<Serializable> voList) {
            StringBuilder csv = new StringBuilder();
            if(voList != null){ 
                for(Serializable serializable :voList){
                    UserVO userVO = null;
                    if(serializable != null && serializable instanceof AdminVO){
                        userVO = ((AdminVO)serializable).getUserVO(); 
                    }
                    if(serializable != null && serializable instanceof UserVO){
                        userVO = (UserVO)serializable;
                    }
                    csv.append(userVO.getUserId()+",");
                }
            }
            return csv.toString();
        }
}

I can not call

using:

List<AdminVO> adminVoList = new ArrayList<AdminVO>
Utils.getUserIdCSVs(adminVoList);

OR using:

List<UserVO> userVoList = new ArrayList<UserVO>
Utils.getUserIdCSVs(userVoList);

The function compiles correctly.

like image 598
Learn More Avatar asked Jul 19 '26 22:07

Learn More


2 Answers

This is expected: in Java, there is no covariance for generic types based on classes from the same hierarchy.

If you think about it, this makes sense. Consider this:

List<AdminVO> adminVoList = new ArrayList<AdminVO>();
Utils.addUser(adminVoList); // assume it expects ArrayList<Serializable>

Now Utils.addUser is free to add a UserVO (or anything else that's Serializable) to the list of admins, in violation of the type of the original list:

static addUser(List<Serializable> users) {
    users.add(new UserV0("I am not an admin!"));
}

However, since users inside addUser is the same as adminVoList outside it, you end up with non-admins in the list that is supposedly composed of admins.

To work with this limitation, simply declare your adminVoList as

List<Serializable> adminVoList = new ArrayList<Serializable>();
like image 126
Sergey Kalinichenko Avatar answered Jul 22 '26 11:07

Sergey Kalinichenko


List<AdminVO> is not a subclass of List<Serializable>.

Imagine it was:

List<AdminVO> list = new LinkedList<>();
List<Serializable> myList = list;
myList.add(new SomeConcreteSerializable()); 
//list contains an element which is not of type AdminVO!
like image 33
amit Avatar answered Jul 22 '26 10:07

amit