在下面的示例中,为什么我能够将返回类型List<? extends IConfigUser>作为List<ConfigUser>覆盖到getUserList()中,但不能对setUserList()的参数执行相同的操作?
在这种情况下,ConfigUser不被认为是IConfigUser的超级类型吗?
public class Test {
   public interface IConfigUser {
   }
   public interface IConfig {
      public List<? extends IConfigUser> getUserList();
      public void setUserList(List<? extends IConfigUser> list);
   }
   public class ConfigUser implements IConfigUser {
   }
   // The type Test.Config must implement the inherited abstract method
   // Test.IConfig.setUserList(List<? extends Test.IConfigUser>)
   public class Config implements IConfig {
      @Override
      public List<ConfigUser> getUserList() {
         return null;
      }
      // The method setUserList(List<ConfigUser> list) of type Test.Config
      // must override or implement a supertype method
      @Override
      public void setUserList(List<ConfigUser> list)
      {
      }
   }
}发布于 2017-11-29 11:11:26
您可以返回(“专门化”)由于协方差而返回的getUserList()类型,也就是说,如果您在IConfig引用上调用该方法,您所知道的就是您将得到一个List<? extends IConfigUser>,而List<ConfigUser>是一个List<? extends IConfigUser>,这样就满足了需求。
如果在Config引用上调用它,则信息更具体,但基本要求仍然满足。
使用setUserList(...),情况就不同了:它允许您传递List<? extends IConfigUser>的任何“子类”,这些子类可以是List<ConfigUser>,但也可以是其他的东西,例如List<SomeConfigUser>。
顺便说一句,由于您不知道list在setUserList(List<ConfigUser> list)中的具体泛型参数,编译器也只允许您从该列表中读取,永远不要添加--原因与上面相同:您不知道您得到了什么,以及是否允许添加ConfigUser,因为列表只能允许添加SomeConfigUser实例。
发布于 2017-11-29 11:09:32
可以通过向IConfig添加泛型类型参数来实现目标。
public class Test {
   public interface IConfigUser {
   }
   public interface IConfig<T extends IConfigUser> {
      public List<T> getUserList();
      public void setUserList(List<T> list);
   }
   public class ConfigUser implements IConfigUser {
   }
   public class Config implements IConfig<ConfigUser> {
      @Override
      public List<ConfigUser> getUserList() {
         return null;
      }
      @Override
      public void setUserList(List<ConfigUser> list)
      {
      }
   }
}发布于 2017-11-29 11:09:57
可以在覆盖中返回更特定的类型,但不能要求接受更特定的类型。去掉泛型,可以用返回Object的方法重写返回String的方法,但不能用接受String参数的方法覆盖接受Object参数的方法。
所有这些都是为了使呼叫者兼容。考虑:
IConfig config = new Config();    
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>();
list.add(new SomeOtherConfigUser());
config.setUserList(list);哎呀--你的Config.setUserList期望每个元素都是一个ConfigUser,而不是一个SomeOtherConfigUser。
https://stackoverflow.com/questions/47551294
复制相似问题