有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java抽象泛型方法,使用具体类型实现通配符

在java中,是否可以使用通配符定义抽象方法,但在实现中使用具体类型

例如:

在这样的抽象类中定义抽象方法

public abstract class AbstractAuthorizer {
    abstract protected <T extends User> void authorize( T user );
}

实现如下抽象方法,其中CorporateServer扩展用户:

public class CorporateAuthorizer extends AbstractAuthorizer {

    @Override
    protected <CorporateUser> void authorize(CorporateUser user){
    }
}

共 (2) 个答案

  1. # 1 楼答案

    抽象类正在声明一个方法,该方法将授权任何<T extends User>。您的分机不符合此合同

    一些选择:

    1. 泛化抽象类

      abstract class AbstractAuthorizer<T extends User> {
          protected abstract void authorize(T user);
      }
      
      class CorporateAuthorizer extends AbstractAuthorizer<CorporateUser> {
          protected void authorize(final CorporateUser user) {
              // Do authorization.
          }
      }
      
    2. 让分机执行必要的检查。类似于(定义为AbstractAuthorizer)的内容:

      class CorporateAuthorizer extends AbstractAuthorizer {
          protected <T extends User> void authorize(final T user) {
              if (!(user instanceof CorporateUser)) {
                  throw new UnsupportedOperationException("CorporateAuthorizer can only authorize 'CorporateUser' users");
              }
              // Do authorization.
          }
      }
      

    如果您选择后者,我强烈建议您使用另外一个abstract boolean supports(User user);进行上述instanceof检查,以便将其用作:

    boolean checkAuth(final User user) {
        boolean authorized = false;
        for (final AbstractAuthorizer authorizer : authorizers) {
            if (authorizer.supports(user)) {
                authorizer.authorize(user);
                authorised = true;
                // break; if only a single authorizer's check is required.
            }
        }
        return authorised;
    }
    

    我还将注意到,在后者中使用<T extends User>的方法与简单地使用User相比没有任何好处,除非您在获得授权的情况下要使用return{}。即

    abstract class AbstractAuthorizer {
        abstract boolean supports(User user);
    
        abstract <T extends User> T authorize(T user);
    }
    
  2. # 2 楼答案

    不,你不能直接做你要求的事。但是,您可以获得相同的效果

    当您将某些内容设置为泛型时,您是在向用户承诺:这将适用于满足泛型边界的任何类型。因此,通过在子类中选择特定类型,您就违反了该规则。但是,如果您正确定义了超类,那么您可以在满足类型检查器的同时获得所需的行为。不要将函数设置为泛型,而是将类设置为泛型,然后当您将其子类化时,您可以选择它使用的类型

    public abstract class AbstractAuthorizer<T extends User> {
        abstract protected void authorize( T user );
    }
    
    public class CorporateAuthorizer extends AbstractAuthorizer<CorporateUser> {
        @Override
        protected void authorize(CorporateUser user) {}
    }