【问题标题】:Can generics allow the Java compiler to check the type of keys and values in a map?泛型可以让 Java 编译器检查映射中键和值的类型吗?
【发布时间】:2009-09-24 18:39:34
【问题描述】:

我处于一种情况,我想要一个映射,其中键是接口类,对应的值是实现该接口的类。换句话说,键和值类型是相关的。

添加到地图并获取实现类实例的方法的当前实现如下所示:

// should be something like Class<T>, Class<? extends T>
static Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>> ();

public static <T> void add(Class<T> interfaceT,
     Class<? extends T> implementationT) {

  map.put(interfaceT, implementationT);
}

public static <T> T get(Class<T> interfaceT) {
  // cast caused by definition not complete.

  Class<T> implementationT = (Class<T>) map.get(interfaceT);

  // try catch stuff omitted
  T t = implementationT.newInstance();
  return t;
 }

我的问题是:

可以我定义“map”变量,这样就不需要在 get(...) 方法中进行强制转换了吗?我无法使“新的HashMap&lt;Class&lt;T&gt;, Class&lt;? extends T&gt;&gt;()”工作,所以要么是不可能的,要么我错过了一些基本的东西:)

请指教:)


编辑:原来 Class 上的 asSubclass() 方法做了我想要的:D

Class<?> rawClassFromMap = map.get(interfaceT);
Class<? extends T> implementationT = rawClassFromMap.asSubclass(interfaceT);

implementationT 是 "? extends T" 类型很好,因为我只需要返回一个 T 对象。

我喜欢泛型。让我想起了 Haskell...

【问题讨论】:

    标签: java generics


    【解决方案1】:

    看起来目标类似于 Josh Bloch 在Chapter 5 of Effective Java (item 29). 中描述的“类型安全异构容器”,在他的例子中,他将类型 (Class&lt;T&gt;) 映射到(已经实例化的)实例 (T )。

    你可以做类似的事情,使用asSubclass而不是cast

    final class Factory
    {
    
      private Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
    
      <T> void map(Class<T> type, Class<? extends T> impl)
      {
        map.put(type, impl.asSubclass(type));
      }
    
      private <T> Class<? extends T> get(Class<T> type)
      {
        Class<?> impl = map.get(type);
        if (impl == null) 
          throw new IllegalArgumentException("Unknown type: " + type);
        return impl.asSubclass(type);
      }
    
      <T> T create(Class<T> type) 
        throws Exception
      {
        Class<? extends T> impl = get(type);
        Constructor<? extends T> ctor = impl.getConstructor();
        return ctor.newInstance();
      }
    
    }
    

    【讨论】:

    • 谢谢。您的解决方案是正确的。我现在重新阅读 generics.pdf - 这是一个相当陡峭的学习曲线 :)
    【解决方案2】:

    我建议Proxy。这是Java example

    public interface Bike {
    
        public String getWheels();
    
        public int getSize();
    
    }
    
    public class MountainBike implements Bike {
    
        @Override
        public int getSize() {
            return 24;
        }
    
        @Override
        public String getWheels() {
            return "Treaded";
        }
    
        @Override
        public String toString() {
            String newLine = System.getProperty("line.separator");
            StringBuilder sb = new StringBuilder();
            sb.append("Type:   MOUNTAIN").append(newLine);
            sb.append("Wheels: ").append(getWheels()).append(newLine);
            sb.append("Size:   ").append(getSize()).append(newLine);
            return sb.toString();
        }
    
    }
    
    public class CruiserBike implements Bike {
    
        @Override
        public int getSize() {
            return 26;
        }
    
        @Override
        public String getWheels() {
            return "Smooth";
        }
    
        @Override
        public String toString() {
            String newLine = System.getProperty("line.separator");
            StringBuilder sb = new StringBuilder();
            sb.append("Type:   CRUISER").append(newLine);
            sb.append("Wheels: ").append(getWheels()).append(newLine);
            sb.append("Size:   ").append(getSize()).append(newLine);
            return sb.toString();
        }
    
    }
    
    public class BikeProxy implements InvocationHandler {
    
        private Object obj;
    
        public static Object newInstance(Object obj) 
        {
            return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
                    .getClassLoader(), obj.getClass().getInterfaces(),
                    new BikeProxy(obj));
        }
    
        public static <T> T newInstance(String className) 
        {
            try 
            {
                return (T) newInstance(Class.forName(className));
            } 
            catch (ClassNotFoundException e) 
            {
                throw new RuntimeException(e);
            }
        }
    
        public static <T> T newInstance(Class<T> bikeClass) 
        {
            try
            {
            return (T) java.lang.reflect.Proxy.newProxyInstance(Bike.class.getClassLoader(), new Class[]{Bike.class},
                    new BikeProxy(bikeClass.newInstance()));
            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }
        }
    
        private BikeProxy(Object obj) 
        {
            this.obj = obj;
        }
    
        public Object invoke(Object proxy, Method m, Object[] args)
                throws Throwable 
        {
            Object result;
            try 
            {
                result = m.invoke(obj, args);
            } 
            catch (InvocationTargetException e) 
            {
                throw e.getTargetException();
            } 
            catch (Exception e) 
            {
                throw new RuntimeException(e);
            }
            return result;
        }
    }
    
    public class ProxyTester 
    {
        public static void main(String[] args) 
        {
            Bike mountainBike = BikeProxy.newInstance(MountainBike.class);
            System.out.println(mountainBike);
    
            Bike mountainBike2 = BikeProxy.newInstance(MountainBike.class.getName());
            System.out.println(mountainBike2);
    
            Bike cruiserBike = BikeProxy.newInstance(CruiserBike.class);
            System.out.println(cruiserBike);
    
            Bike cruiserBike2 = BikeProxy.newInstance(CruiserBike.class.getName());
            System.out.println(cruiserBike2);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 1970-01-01
      • 2015-07-31
      • 2010-12-20
      相关资源
      最近更新 更多