1

If I take out the @SuppressWarnings("unchecked") from this code, I get:

Unchecked cast: 'java.lang.Class<capture<?>>' to 'java.lang.Class<? extends com.megacorp.security.User>'

See how the constructor I grab a reference to is used later in the code. Can I refactor it or do I just have to live with it?

private final Constructor<? extends User> constructor;

public LdapUserDetailsMapper(String userClassName)
        throws ClassNotFoundException, NoSuchMethodException {
    @SuppressWarnings("unchecked") 
    Class<? extends User> userClass =
            (Class<? extends User>) Class.forName(userClassName);
    constructor = userClass.getConstructor(String.class, Collection.class);
    if (constructor == null) {
        throw new IllegalArgumentException(String.format(
                "Couldn't find user constructor for [%s]", userClassName));
    }
}

@Override
public UserDetails mapUserFromContext(String login,
        Collection<? extends GrantedAuthority> authorities) {
    //Extract basic user info
    User user;
    try {
        user = constructor.newInstance(login, mergedAuthorities);
        return user;
    } catch (IllegalAccessException
            | InstantiationException
            | InvocationTargetException e) {
        throw new RuntimeException(
                String.format("Cannot instantiate new User [%s]", login),
                e);
    }
}
Adam
  • 5,215
  • 5
  • 51
  • 90
  • 1
    I don't think there is much you can do - the compiler can't prove that `Class.forName(userClassName)` is a subclass of User. See also https://stackoverflow.com/a/2892891/829571 – assylias Mar 07 '19 at 11:33
  • 1
    Well getting the `Constructor` object confuses the issue, but this is a duplicate as marked and the answer there is to use `Class.forName(userClassName).asSubclass(User.class)` and the warning disappears. – Adam Mar 07 '19 at 11:42
  • Of course you can and should dynamically check whether User.class.isAssignableFrom(`Class> userClass)` or do @Adam's thing. – Joop Eggen Mar 07 '19 at 11:42
  • @JoopEggen so how do you code that? – Adam Mar 07 '19 at 11:43
  • `Class> userClass = Class.forName(...); if (!User.class.isAssignableFrom(userClass)) throw new IllegalArgumentException("...");` And cast the instantiated object safely to User. – Joop Eggen Mar 07 '19 at 11:44
  • Ah OK, I thought you'd just transfer the warning to the invocation of the constructor but it appears not. I prefer this to the `asSubclass()` method since I can now give a more descriptive exception message. – Adam Mar 07 '19 at 11:57

0 Answers0