为什么 Java 不允许我添加子类实例?

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

我在 Java 项目中遇到问题。 错误产生的代码如下:

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));
           }
       }

当我尝试在每个 hashmap 列表中添加新元素时出现错误,当我创建实例时,intellij 告诉我:
所需类型:捕获 ?扩展用户
提供:客户(或员工或管理员)

但是为什么,如果 CustomerEmployeeA​​dministrator 都是 User[ 的子类=28=]?
我应该改变什么?我的意图是拥有一个包含所有注册用户的 HashMap(我将它们保存在一个 .properties 文件中,因为我看到了,所以被更正为红色),其中键是用户的角色(管理员、员工和客户),以及值每个键都是具有该角色的每个用户的链表。 我还尝试使用 super 而不是 extends,但在那种情况下我解决了这个错误,但是在使用 Map.of()(因为 Administrator、Customer 和 Employee 不是 User 的超类)。 如果我有 3 个直接用 3 个角色对象声明的不同列表,代码就可以工作,但我想要哈希图,因为我想 return 整个注册用户除以他们的角色。
谢谢大家,希望我解释清楚了。

@Thomas 的评论中已涵盖编译器错误的原因:对于编译器,signedUpUsers.get("Administrator") 是一个 LinkedList<? extends User>,不知道在 "Administrator" 键下,您存储了a LinkedList<Administrator>(而不是 LinkedList<Employee>,因此编译器不允许添加 Administrator

您的 signedUpUsers 变量显示了一些重要的泛型过度设计。你声明

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

我建议将其更改为

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

您可能会问“但是现在我没有类型安全,我只能在 "Administrator" 键下存储 Administrator 个实例。”但是第一个版本也不可能实现类型安全(在 运行 时,LinkedList<Administrator> 只是一个 LinkedList 并且会很乐意接受任何 Object,并且在编译时 LinkedList<? extends User> 将不允许添加任何内容)。

如果你想要列表的类型安全,扔掉 Map 方法,并创建一个 class UserList:

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

这将轻松提供所需的类型安全性。