【问题标题】:Unable to case Set<Supertype> to Set<Subtype> [duplicate]无法将 Set<Supertype> 设置为 Set<Subtype> [重复]
【发布时间】:2017-12-28 15:45:57
【问题描述】:

我在将 Set 转换为 Set

时遇到错误

我收到以下错误:

无法从 Set 转换为 Set

interface AppUserRole {
    void m1();
}

class AppUserRoleEntity implements AppUserRole {

    @Override
    public void m1() {

    }

}

interface AppUser {

    void m2(Set<AppUserRole> abc);
}

class AppUserEntity implements AppUser {

    Set<AppUserRoleEntity> role;

    @Override
    public void m2(Set<AppUserRole> abc) {
        this.role = (Set<AppUserRoleEntity>) abc;// Compilation fails here

    }

}

阅读 PECS 后,我修改了我的代码,如下所示

    Set< ? super AppUserRoleEntity> role;

但不是在同一类的 getter 方法上我收到警告

类型安全:来自 Set 设置

@Override
    public Set<AppUserRole> getAppUserRoles() {
        return (Set<AppUserRole>) appUserRoles;
    }

谁能告诉我如何解决这个问题?请帮忙

【问题讨论】:

  • "有人能告诉我如何解决这个问题吗?" -> 是的,部署PECS。 TL;DR:泛型不是协变的。
  • @azurefrog 相关,但反过来说:OP 询问为什么不能将动物列表转换为狗列表。当然,答案是动物列表中可能包含猫。
  • derp,咖啡前阅读理解失败:/
  • @PrzmyslawMoskal 我在上面对 azurefrog 所做的评论相同。 OP 正在询问相反的情况。
  • 你为什么认为你首先需要做这个演员?为什么role 集合不能只是Set&lt;AppUserRole&gt;?在您的编辑中,您甚至似乎将集合返回为Set&lt;AppUserRole&gt;

标签: java generics


【解决方案1】:

我的建议是在接口中声明泛型类型:

interface AppUserRole {
    void m1();
}

class AppUserRoleEntity implements AppUserRole {

    @Override
    public void m1() {

    }

}

interface AppUser<R extends AppUserRole> {

    void m2(Set<R> abc);
}

class AppUserEntity implements AppUser<AppUserRoleEntity> {

    Set<AppUserRoleEntity> role;

    @Override
    public void m2(Set<AppUserRoleEntity> abc) {
        this.role = abc;// No cast needed

    }

}

【讨论】:

    【解决方案2】:

    您可以擦除类型并为您的类型执行未经检查的强制转换,如下所示:

    @Override
    public void m2(Set<AppUserRole> abc) {
        this.role = (Set<AppUserRoleEntity>) (Set<?>) abc;
    }
    

    此外,如果 Set 被键入为接受扩展 AppUser 的捕获,您可以在不擦除的情况下进行强制转换。

    @Override
    public void m2(Set<? extends AppUserRole> abc) {
        this.role = (Set<AppUserRoleEntity>) abc;
    }
    

    这只是一个不安全的演员表。如果您传递的项目类型不是 AppUserRoleEntity,程序将抛出 ClassCastException。

    此外,最好的解决方案是使用接口而不是实现类型。

    【讨论】:

    • abc 包含除AppUserRoleEntity 之外的其他实现时,它将在运行时严重失败
    • 显式转换也会失败
    • ...这就是为什么我们有PECS
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多