0

I am getting error while casting Set < Supertype > to Set< Subtype >

I am getting following error :

Cannot cast from Set< AppUserRole > to Set< AppUserRoleEntity >

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

    }

}

After reading PECS I have modified my code like below

    Set< ? super AppUserRoleEntity> role;

But not on getter method of same class I am getting warning

Type safety: Unchecked cast from Set< capture#2-of ? super AppUserRoleEntity > to Set

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

Can some one tell me how to fix this problem ? Please help

T-Bag
  • 10,916
  • 3
  • 54
  • 118
  • You need co/contravariance: https://stackoverflow.com/questions/2501023/demonstrate-covariance-and-contravariance-in-java and then it will work one way (either co or contravariance) – Dennis Kuypers Dec 28 '17 at 15:48
  • 3
    "Can some one tell me how to fix this problem ?" -> Yes, deploy [PECS](https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super). TL;DR: generics are not covariant. – Turing85 Dec 28 '17 at 15:48
  • 5
    @azurefrog relevant, but it's the other way round: OP is asking why a list of animals can't be cast to a list of dogs. And of course, the answer is that a list of animals might contain cats. – Andy Turner Dec 28 '17 at 15:48
  • 1
    derp, pre-coffee reading comprehension fail :/ – azurefrog Dec 28 '17 at 15:49
  • @AndyTurner-- If you can please help – T-Bag Dec 28 '17 at 15:49
  • 2
    @PrzmyslawMoskal same comment I made above to azurefrog. OP is asking about the reverse case. – Andy Turner Dec 28 '17 at 15:50
  • @AndyTurner not really, is the same case. OP is trying to cast a `List` into a `List`. Even if he finds a way so that doesn't fail at compilation, it will fail in runtime when the `List` contains something that is not a dog. Like a cat. Or a whale. – Ray O'Kalahjan Dec 28 '17 at 16:08
  • 2
    Why do you think you need to do this cast in the first place? Why can't the `role` set just be `Set`? In your edit, you even appear to be returning the set as a `Set`. – Radiodef Dec 28 '17 at 16:09
  • @AndyTurner I deleted comment in which there was an information about that I suspect this question as duplicate. It seems that it was not the correct way of releasing the flag that I submitted, because now I have information that my flag was helpful although I reconsidered submitting it. Anyway, thank you for offering your point of view, I actually agree with your opinion now. – Przemysław Moskal Dec 28 '17 at 20:23

2 Answers2

0

My advice is to declare the generic type in the interface:

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

    }

}
-1

You can erase type and do a unchecked cast for your type, as below:

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

Also if Set is typed as accepting a capture of extends AppUser you can do the cast without erasure.

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

That is just a unsafe cast. If you pass a item type that is not AppUserRoleEntity the program will throw ClassCastException.

Besides, the best solution is to use the interface and not the implementing type.

Marcos Vasconcelos
  • 18,136
  • 30
  • 106
  • 167