java static class Singleton with generic

时间:2013-06-07 04:21:41

标签: java

我正在努力制作像下面这样的单身人士,但我一直在收到警告。如果可能的话,我不想要压制警告。有办法吗?

目前,我不想考虑线程安全性。我只想传递这个警告。

    public interface Storage<K, V> {
        public void put(K key, V value);
        public V get(K key);
    }


    public static class DefaultStorage<K, V> implements Storage<K, V> {

        private Map<Object, Object> map = new ConcurrentHashMap<Object, Object>();

        private static DefaultStorage<K, V> defaultStorage;

        private DefaultStorage() {
            //
        }

        public static DefaultStorage<?, ?> getInstance() {
            if (defaultStorage== null) {
                defaultStorage= new DefaultStorage();
            }
            return defaultStorage;
        }
     }

感谢。

3 个答案:

答案 0 :(得分:1)

我会使用枚举并指定类型。

public interface Storage<K, V> {
    public void put(K key, V value);
    public V get(K key);
}

public enum DefaultStorage implements Storage<String, Object> {
    INSTANCE;

    private final Map<Object, Object> map = new ConcurrentHashMap<>();

    public Object get(String key) { return map.get(key); }
    public void put(String key, Object value) { map.put(key, value); }

}

答案 1 :(得分:0)

defaultStorage中的变量DefaultStorage仅在DefaultStorage组合的每个实例中存在一次。在运行时,只有一个实际类和一个静态变量。因此,变量将同时为DefaultStorage<K1, V1>DefaultStorage<K2, V2>DefaultStorage<K3, V3>,依此类推。因此,一个类将Strings存储在其中,另一个类将存储BigDecimals,另一个将存储X501Principals。这颠覆了类型安全。

警告是您将原始类型new DefaultStorage()的实例存储在声明为DefaultStorage<K, V>的变量中。

来自Angelika Langer's Generics FAQ

  

泛型类型可以有静态成员吗​​?

     

     

泛型类型可以包含静态成员,包括静态字段,静态方法和静态嵌套类型。这些静态成员中的每一个对于每个封闭类型存在一次,即,与封闭类型的对象的数量无关,并且不管可以在程序中某处使用的泛型类型的实例化的数量。静态成员的名称(通常用于静态成员)包括作用域(包和封闭类型)和成员的名称。如果封闭类型是通用的,那么范围限定中的类型必须是原始类型,而不是参数化类型。

答案 2 :(得分:0)

你怎么能像这样创建对参数化内部类的引用?

private static DefaultStorage<K, V> defaultStorage;

根据Static method in a generic class?中的解释:

  

类的类型参数仅适用于其实例变量,而不适用于静态字段和方法。静态字段和方法在类的所有实例之间共享,甚至在各种类型参数的实例之间共享。“

因此,您无法为类DefaultStorage创建静态引用,并将其限制为仅K,V类型。这应该没问题。

private static DefaultStorage<?,?> defaultStorage;

但正如你所提到的,我无法在没有压制它的情况下摆脱警告。像这样创建对象

 defaultStorage= new DefaultStorage(); 
显然会引发编译错误。