泛型:如何在不进行强制转换的情况下获取Map的值

时间:2017-07-26 05:32:05

标签: java generics collections casting hashmap

我有一个名为BaseCode的抽象类和2个名为LocationDepartment的具体类:

public abstract class BaseCode {
   private Integer id;
   ...
   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   ...
}

public class Location extends BaseCode {
   ...
}

public class Department extends BaseCode {
   ...
}

我有一个名为BaseCodeCache的抽象类和2个名为LocationCacheDepartmentCache的具体类。 LocationCacheDepartmentCache将使用Singleton

public abstract class BaseCodeCache {
   ...
}

public class LocationCache extends BaseCodeCache {
   ...
}

public class DepartmentCache extends BaseCodeCache {
   ...
}
  1. BaseCodeCache中,我想要一个java.util.Map的值 是任何类型的BaseCode,即Location个对象或Department 对象。
    LocationCache中,我希望java.util.Map存储Location个对象。
    DepartmentCache中,我希望java.util.Map存储Department个对象。
  2. 为实现这一目标,我将此代码放在BaseCodeCache

    private Map<Integer, BaseCode> idMap = new HashMap<Integer, BaseCode>();
    
    1. 我想要一个方法来存储一个值 java.util.Map
    2. 为实现这一目标,我将此代码放在BaseCodeCache

      public void add(BaseCode baseCode) {
         if (baseCode != null) {
            idMap.put(baseCode.getId(), baseCode);
         }
      }
      

      这就是我将它用于Location

      的方法
      Location location = new Location(); ...
      LocationCache.getInstance().add(location);
      

      这就是我将它用于Department

      的方法
      Department department = new Department(); ...
      DepartmentCache.getInstance().add(department);
      
      1. 我想要一个方法来获取java.util.Map中的所有值 一个java.util.List
        LocationCache中,此方法应返回List<Location>
        DepartmentCache中,此方法应返回List<Department>
      2. 这就是我被困的地方。我想在BaseCodeCache中创建此方法,但是当通过LocationCache调用此方法时,它会返回List<Location>这个方法通过DepartmentCache调用,然后返回List<Department>有可能吗?

        我将此代码放在BaseCodeCache

        public List<BaseCode> getList() {
           return new ArrayList<BaseCode>(idMap.values());
        }
        

        但上面的代码返回List<BaseCode>。当我这样称呼它时:

        List<Location> allLocations = LocationCache.getInstance().getList();
        

        然后java将不允许它编译并给出此错误消息:

          

        类型不匹配:无法从List<BaseCode>转换为List<Location>

        我可以通过获取List<BaseCode>然后通过循环将其转换为List<Location>来解决此问题,但这看起来并不合适。

        可以吗?

1 个答案:

答案 0 :(得分:4)

使用泛型实现如下:

public abstract class BaseCodeCache<T extends BaseCode> {
    private Map<Integer, T> idMap = new HashMap<>();

    public void add(T baseCode) {
        if (baseCode != null) {
            idMap.put(baseCode.getId(), baseCode);
        }
    }

    public List<T> getList() {
        return new ArrayList<>(idMap.values());
    }
}

public class LocationCache extends BaseCodeCache<Location> {}

public class DepartmentCache extends BaseCodeCache<Department> {}

这将使您能够执行以下而不任何编译错误:

LocationCache locationCache = new LocationCache();
locationCache.add(new Location());

List<Location> locations = locationCache.getList();

更好的是,如果您尝试添加或检索错误类型的对象, 会出现编译错误:

locationCache.add(new Department()); // won't compile
List<Department> departments = locationCache.getList(); // won't compile