Java泛型,单例和静态方法

时间:2011-11-02 14:36:48

标签: java generics inheritance static singleton

所以我有一些'经理'类,例如GroupManager。所有这些经理都是单身人士。

使用此方法进行实例化:

private static GroupManager groupManager = null;

private GroupManager()
{

}

public static GroupManager Instance()
{
    if (groupManager == null)
    {
        groupManager = new GroupManager();
    }
    return groupManager;
}

我想我应该开始使用一些继承,因为他们有很多复制的方法。

每个Manager的Instance()方法都是相同的。

因此,对于继承,我可以这样做(显然):

GroupManager extends Manager

是否可以使用泛型为所有管理器使用相同的Instance方法,例如:

public class Manager<E>
{
    private static E instance = null;

    public static E Instance()
    {
        if (instance == null)
        {
            instance = new E();
        }
        return instance;
    }

}

我认为这是有道理的:)

那么你就像普通的那样做GroupManager.Instance()。

5 个答案:

答案 0 :(得分:9)

你不明白泛型和静态是如何工作的。如果您有一个静态字段或方法(例如“instance”或instance()),可以在不实例化类Manager的情况下调用它,那么您希望JVM(以及编译器甚至)知道E应该是什么类型是

根据G_H的建议,这是一个例子:

GeneralManager和AreaManager都扩展了管理器

Manager类是唯一具有getInstance()静态方法的类:

    public class Manager {

        private static Map<Class<? extends Manager>,Manager> INSTANCES_MAP = new java.util.HashMap<Class<? extends Manager>, Manager>();

//Also, you will want to make this method synchronized if your application is multithreaded,
//otherwise you mihgt have a race condition in which multiple threads will trick it into
//creating multiple instances
        public static <E extends Manager> E getInstance(Class<E> instanceClass) throws InstantiationException, IllegalAccessException {
            if(INSTANCES_MAP.containsKey(instanceClass)) {
                return (E) INSTANCES_MAP.get(instanceClass);
            } else {
                E instance = instanceClass.newInstance();
                INSTANCES_MAP.put(instanceClass, instance);
                return instance;
            }
        }
    }

答案 1 :(得分:2)

不,这不会奏效。 Java在编译时使用泛型进行类型检查,但不会在运行时生成额外的类或保留有关类型参数的信息。

当您使用该类型参数Manager<E>声明E时,这只会在实际实例中发挥作用。你可以有一个像GroupManager extends Manager<String>或其他类似的子类,但这并不会产生各种静态方法。

静态方法和成员属于类,而不是实例。所以尝试在那里使用泛型,这些用于打字实例,是不会飞的。

答案 2 :(得分:0)

如果按照以下方式创建组管理员课程,则可以调用实例方法。

public class GroupManager extends Manager<GroupManager>{}

在你的经理课上试试这个......

public class Manager<E>
{
private static E instance = null;

public static E Instance()
{
                  try {
            return instance.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;  
}

或者如果您知道要实例的对象,只需将方法设为通用

即可
public static <T> T getInstance(Class<T> t){
             try {
            return t.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

我没有尝试过这些,所以不确定它是否会起作用。

答案 3 :(得分:0)

在通用上下文中注入构造函数。现金不是线程安全的,但仅在静态环境中使用,所以如果您不错过使用它就可以了。

public class Example {

    public static class MySingletonClass {
    }

    public interface Provider<T> {
        T get();
    }

    static final Provider<MySingletonClass> myClassInstanceProvider = new Cash<MySingletonClass>(new Provider<MySingletonClass>() {
            @Override
            public MySingletonClass get() {
                return new MySingletonClass();
            }
        }); 


    public static class Cash<T> implements Provider<T> {
        private Provider<T> provider;

        public Cash(Provider<T> provider) {
            this.provider = provider;
        }

        @Override
        public T get() {

            final T t = provider.get();
            provider = new Provider<T>() {

                @Override
                public T get() {
                    return t;
                }
            };
            return t;
        }
    }
}

答案 4 :(得分:0)

public class Manager<E>{

private static Object instance = null;

    public static E Instance() {
       if (instance == null)
       {
        instance = new E();
       }
       return (E)instance;
   }
}