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.