【问题标题】:Easiest way to create a MutableGuiceKeyToInstanceMap?创建 MutableGuiceKeyToInstanceMap 的最简单方法?
【发布时间】:2011-05-09 18:35:31
【问题描述】:

我想找到或实现一个 MutableGuiceKeyToInstanceMap,其工作方式与 Guava 中的 com.google.common.collect.MutableClassToInstanceMap 类似,但使用 Guice 中的 com.google.inject.Key<T> 代替 Class<T>

我在 Guice 中找不到它,也无法像 MutableClassToInstanceMap 那样实现它,因为它的超类 ConstrainedMap 是包私有的。我也不能使用MapConstraint.constrainedMap,因为我没有机会添加getInstanceputInstance 方法(没有它们,这一切都毫无意义)。

制作自己的 ConstrainedMap 类副本会迫使我复制很多额外的类,所以这不是要走的路。通过MapConstraint.constrainedMap 制作助手地图并制作将所有内容委托给助手的MutableGuiceKeyToInstanceMap extends ForwardingMap 可以工作,但仍然很麻烦。有更好的主意吗?

你认为将ConstrainedMap公开是个好主意吗?

【问题讨论】:

    标签: java map guice guava


    【解决方案1】:

    一些想法:

    1. 我很好奇你为什么要这样做。
    2. ForwardingMap 对此似乎很好。有什么麻烦?
    3. 公开ConstrainedMap 不是一个好主意。

    【讨论】:

    • 1.用于实现自定义范围。好的,它实际上并不需要,因为没有人可以在其中提出任何错误。 2. 这样我定义了两个几乎相同的类 - 其中一个只是为了有一些东西可以转发。但这并没有我想象的那么糟糕。 3. 为什么不呢?
    • 1.我实际上只需要getInstanceputInstance 这两种方法,不需要任何Map 方法。但是,我想制作一个地图(不知道如何调用缺少所有 Map 方法的“地图”)。 2. 其实很简单。 3. 我看到为了保持约束,它必须是包私有的,或者所有的变异和变异暴露方法(如entrySet())必须是最终的。
    【解决方案2】:

    我不明白你为什么不喜欢ForwardingMapMapConstraint.constrainedMap 的组合。代码非常简单,看起来几乎与直接扩展 ConstrainedMap 所得到的完全一样:

    import com.google.common.collect.ForwardingMap;
    import com.google.common.collect.MapConstraint;
    import com.google.common.collect.MapConstraints;
    import com.google.inject.Key;
    import org.apache.commons.lang.NotImplementedException;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public final class MutableGuiceKeyToInstanceMap<B>
            extends ForwardingMap<Key<? extends B>, B> {
    
        /**
         * Returns a new {@code MutableGuiceKeyToInstanceMap} instance backed by a {@link
         * java.util.HashMap} using the default initial capacity and load factor.
         */
        public static <B> MutableGuiceKeyToInstanceMap<B> create() {
            return new MutableGuiceKeyToInstanceMap<B>(new HashMap<Key<? extends B>, B>());
        }
    
        /**
         * Returns a new {@code MutableGuiceKeyToInstanceMap} instance backed by a given
         * empty {@code backingMap}. The caller surrenders control of the backing map,
         * and thus should not allow any direct references to it to remain accessible.
         */
        public static <B> MutableGuiceKeyToInstanceMap<B> create(Map<Key<? extends B>, B> backingMap) {
            return new MutableGuiceKeyToInstanceMap<B>(backingMap);
        }
    
    
        private final Map<Key<? extends B>, B> delegate;
    
        private MutableGuiceKeyToInstanceMap(Map<Key<? extends B>, B> delegate) {
            this.delegate = MapConstraints.constrainedMap(delegate, VALUE_MATCHES_GUICE_KEY);
        }
    
        @Override
        protected Map<Key<? extends B>, B> delegate() {
            return delegate;
        }
    
        private static final MapConstraint<Key<?>, Object> VALUE_MATCHES_GUICE_KEY = new MapConstraint<Key<?>, Object>() {
            @Override
            public void checkKeyValue(Key<?> key, Object value) {
                matchesGuiceKey(key, value);
            }
        };
    
        public <T extends B> T putInstance(Key<T> key, T value) {
            return matchesGuiceKey(key, put(key, value));
        }
    
        public <T extends B> T getInstance(Key<T> key) {
            return matchesGuiceKey(key, get(key));
        }
    
        private static <B, T extends B> T matchesGuiceKey(Key<T> key, B value) {
            throw new NotImplementedException("TODO");
        }
    
        private static final long serialVersionUID = 0;
    }
    

    代码与MutableClassToInstanceMap非常相似,无需扩展ForwardingMap...当然,您需要添加delegate()方法及其随附字段,但其余部分相同。

    我省略了matchesGuiceKey() 实现作为读者练习。祝你好运!你mightneedit

    【讨论】:

    • 不错的答案,真的没那么糟糕。 matchesGuiceKey 方法可能是一个有趣的练习,也感谢链接。
    • @eneveu:我不认为我的练习正确,因为我在那里使用@SuppressWarnings("unchecked") final Class&lt;T&gt; rawClass = (Class&lt;T&gt;) key.getTypeLiteral().getRawType();。它似乎有效,但有更好的主意吗?
    • 其实实现matchesGuiceKey方法并不容易。我的回答很讽刺。您的问题集中在无法扩展ConstrainedMap,我回答了这部分问题。但matchesGuiceKey 的东西实际上更难。我尝试实现该方法,但现在是凌晨 1 点,我无法让它工作。我可能会在今天晚些时候再试一次,但泛型不会让这变得容易 ;) 甚至不要让我从整个 TypeLiteral 蠕虫罐开始...除非我们找到泛型专家?
    • @eneveu:我已经实现了它here。这可能是错误的,但我不这么认为。方法 TypeLiteral.getRawType() 的结果需要未经检查的强制转换,但恕我直言,因为它返回类似于原始 Map 的类型文字,如 Map&lt;K, ? extends E super S&gt; 并且无法在 Java 泛型系统中表达它们的关系。跨度>
    • @eneveu:只剩下一个问题:像m.put(stringListKey, integerList); 这样的事情应该是不可能的,但是——因为擦除——它是,而且没有办法绕过它,除了禁止所有其他的 mutators然后putInstance.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 2018-03-07
    • 2014-01-28
    • 1970-01-01
    相关资源
    最近更新 更多