简体   繁体   中英

Why Java doesn't allow me to add subclass istances?

I have a problem in a Java project. The code where error born is the following:

HashMap<String, LinkedList<? extends User>> signedUpUsers =
               new HashMap<>(Map.of(
                       "Administrator", new LinkedList<Administrator>(),
                       "Employee", new LinkedList<Employee>(),
                       "Customer", new LinkedList<Customer>()));
       for (String userName : userNameList)
       {
           userPropertyValue = usersProperties.getProperty(userName).split(",");
           String password = userPropertyValue[0].replaceAll("\\s", "");
           String role = userPropertyValue[1].replaceAll("\\s", "");
           if (role.equals("Administrator"))
           {
               signedUpUsers.get("Administrator").add(new Administrator(userName, password));
           }
           else if (role.equals("Customer"))
           {
               signedUpUsers.get("Customer").add(new Customer(userName, password));
           }
           else
           {
               signedUpUsers.get("Employee").add(new Employee(userName, password));
           }
       }

It gives me an error when I try to add new elements in each list of hashmap, when I create instances, intellij tells me:
Required type: capture of ? extends User
Provided: Customer (or Employee or Administrator)
But why, if Customer , Employee and Administrator are all subclasses of User ?
What I should change? My intention is to have an HashMap which contains all signed up users (I saved them in a .properties file which is corrected red because I saw that), where keys are roles of users (Administrators, Employees and Customers), and the value of each key is a LinkedList of each user with that role. I also tried to use super instead of extends , but in that case I solve this error, but a new error appear in creating the hashmap with Map.of() (because Administrator, Customer and Employee aren't superclass of User). The code works if I have 3 different lists declared directly with 3 roles objects, but I wanted the hashmap because I want to return the whole signed up users divided by their role.
Thanks to all, I hope I was clear in explaining.

The reason for the compiler error has been covered in @Thomas's comment: To the compiler, signedUpUsers.get("Administrator") is a LinkedList<? extends User> LinkedList<? extends User> , not knowing that under the "Administrator" key, you stored a LinkedList<Administrator> (and not eg a LinkedList<Employee> , so the compiler does not allow adding an Administrator .

Your signedUpUsers variable shows some significant generics over-engineering. You declare

HashMap<String, LinkedList<? extends User>> signedUpUsers =
           new HashMap<>(Map.of(
                   "Administrator", new LinkedList<Administrator>(),
                   "Employee", new LinkedList<Employee>(),
                   "Customer", new LinkedList<Customer>()));

I suggest to change that to

HashMap<String, LinkedList<User>> signedUpUsers =
           new HashMap<>(Map.of(
                   "Administrator", new LinkedList<User>(),
                   "Employee", new LinkedList<User>(),
                   "Customer", new LinkedList<User>()));

You might ask "But now I don't have the type safety that I can only store Administrator instances under the "Administrator" key." But that type safety also wasn't possible with the first version (at run-time, the LinkedList<Administrator> is just a LinkedList and will happily accept any Object , and at compile-time LinkedList<? extends User> will not allow adding anything).

If you want type safety for the lists, throw away the Map approach, and create a class UserList :

public class UserList {
    private List<Administrator> administrators;
    private List<Employee> employees;
    private List<Customer> customers;
    // add constructor, getters, adders etc. here
}

This will easily give the desired type safety.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM