伙计们,

有没有简单的方法可以在非通用类中添加通用类。

基本上,缓存管理器将具有通过适当的泛型实现的Cache类的映射。

但是在下面的类中,我们通过get方法返回(getCache方法)缓存,它需要在调用者处进行显式强制转换,从而避免这种情况。

例如

public class CacheManager {
    private Map<String, Cache<?,?>> cacheMap = new HashMap<String, Cache<?,?>>();
    public Cache<?,?> getCache(String cacheName) {
        return cacheMap.get(cacheName);
    }

    public void addCache(String cacheName,Cache<?,?> cache) {
        cacheMap.put(cacheName, cache);
    }
}

#1楼 票数:0

简短的回答:不(据我所知)。

这里的问题是您正在做的事情在Java中根本不是类型安全的。 看一下这个例子:

import java.util.*;

class ClassCast {
    public static void main(String[] args) {
        HashMap<String, Pair<?, ?>> map = new HashMap<>();

        map.put("test", new Pair<String, Integer>("Hello", 5));

        Pair<Double, Double> pair = (Pair<Double, Double>) map.get("test");
    }
}

class Pair<T,V> {
    T a;
    V b;

    Pair(T a, V b) {
        this.a = a;
        this.b = b;
    }
}

您可能会在这里遇到ClassCastException ,但是它可以编译并运行良好。 原因是Pair<String, Integer>Pair<Double, Double>的实际类实际上只是Pair (在类型擦除之后)。

为了获得类型安全,您必须实现“ Typesafe异构容器模式”(由Josh Bloch在Effective Java中进行了详细说明)。 简而言之,您必须将类型参数包含在地图的键中。 根据您的需要,您可以直接将类用作键,否则可能需要创建键对象。

示例实现:

public class CacheManager {
    private Map<MultiKey, Cache<?,?>> cacheMap = new HashMap<>();

    @SuppressWarnings("unchecked")
    public <T,V> Cache<T,V> get(String name, Class<T> t, Class<V> v) {
        // Type-safe since types are encoded in key(i.e. map will not
        // return something with the wrong type), and key is type-checked
        // on insertion.
        return (Cache<T,V>) cacheMap.get(new MultiKey(name, t, v));
    }

    public <T,V> void put(String name, Class<T> t, Class<V> v, Cache<T,V> cache) {
        cacheMap.put(new MultiKey(name, t, v), cache);
    }

    class MultiKey {
        Object[] keys;
        Integer hash = null;

        MultiKey(Object... keys) {
            this.keys = keys;
        }

        @Override
        public int hashCode() {
            if (hash == null) hash = Arrays.hashCode(keys);
            return hash;

        }

        @Override
        public boolean equals(Object o) {
            if (o == null || !(o instanceof MultiKey)) return false;
            return Arrays.equals(keys, ((MultiKey) o).keys);
        }
    }
}

用法示例:

CacheManager mng = new CacheManager();

mng.addCache("SI", String.class, Integer.class, new Cache<String, Integer>());

Cache<String, Integer> cache = mng.getCache("SI", String.class, Integer.class);

System.out.println(cache);

它不是很漂亮,但是实际上是类型安全的。 但是可以根据实际情况进行改进,因此您不应按原样使用此代码。 例如,如果您可以从Cache对象获取类型,则在addCache不需要Class参数。

  ask by user1927808 translate from so

未解决问题?本站智能推荐:

5回复

如何在枚举中定义通用成员变量?

我想引用一个enum方法来检索算法的类,以便我可以延迟加载算法的新实例,以便在策略设计模式中使用。 在这个例子中,我使用枚举来引用计算Fibonacci数的三个不同策略类: RecursiveFibonacciGenerator , IterativeFibonacciGenerator和M
3回复

Java中返回通用类成员的参数化方法

为什么不允许以下代码? 以及如何在维护代码的同时修复代码? 即,类成员list仅接受Something子类且myFunc()相同的对象?
2回复

Java-通用类的类成员的行为

如果在Java中将泛型类的实例声明为原始类型,则编译器是否为所有类成员方法都采用Object的参数化类型? 这是否还会扩展到那些返回某种具体参数化类型的形式(例如Collection )的方法? 我错误地声明了没有参数化类型的泛型类的实例,这导致了非常有趣的下游影响。 我提供了一个产生“
2回复

通用类中的JPAContainer?

我正在尝试创建一个通用类以在项目中自动创建jpacontainer,但无法正常工作并返回一些错误。 错误信息未设置EntityProvider。 我正在尝试这个。 } } 任何想法 ?
1回复

在通用堆栈类中创建通用堆栈

我试图自学一些Java,并且遇到了似乎很简单的问题,但是我仍然找不到解决方案。 到目前为止,我有: 接口: 类堆栈: 好了,这就是我想要做的。 我试图写一个方法equals比较两个堆栈。 我的想法是使用第三个堆栈,以便在比较它们之后将两个堆栈都恢复为原始状态。 这是我所拥
2回复

在扩展通用类的类中启动实例变量

我有一个通用类“ SimpleList”(节选): 还有另一个扩展它的类“ TrackList”(节选): 在“ TrackList”中,我指定列表将保存“ XmlTrack”类型的对象。 但是,似乎不可能从该列表中获取对象并访问其方法。 例如,这将不起作用: list.get(
1回复

在通用类中实现通用接口

我是泛型类型的新手,想知道如何在泛型类中正确实现泛型接口,因此在实例化该泛型类的对象时,类型的确定会延迟到一瞬间。 我的代码如下所示: 和实现该接口的类: 我想实例化此类的对象的时刻是在返回ProcessorResult的方法中(如下所示)(仅出于演示目的): 在这种情况下,我得
1回复

声明通用类中定义的类型的变量时,Boundmismatch错误

类定义为Header<Field<Column<Content<?>>>>{} ,变量声明为Header<Field<Column<Content<String>>>> aHeader 。 这给出了