简体   繁体   English

Java泛型,单例和静态方法

[英]Java generics, singletons and static methods

So I have a few 'Manager' classes, for example GroupManager. 所以我有一些'经理'类,例如GroupManager。 All these Managers are singletons. 所有这些经理都是单身人士。

Using this method for instancing: 使用此方法进行实例化:

private static GroupManager groupManager = null;

private GroupManager()
{

}

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

I'm thinking I should start to use some inheritance as they have a lot of copied methods. 我想我应该开始使用一些继承,因为他们有很多复制的方法。

The Instance() methods for each Manager is the same. 每个Manager的Instance()方法都是相同的。

So for inheritance i can do this (obviously): 所以对于继承我可以这样做(显然):

GroupManager extends Manager

Is it possible to use generics to use the same Instance method for all managers, something like: 是否可以使用泛型对所有管理器使用相同的Instance方法,例如:

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

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

}

I think that makes sense :) 我认为这是有道理的:)

So then you would do GroupManager.Instance() like normal. 那么你就像普通的那样做GroupManager.Instance()。

You don't understand how generics and statics work. 你不明白泛型和静态是如何工作的。 If you have a static field or method (such as "instance" or instance()), which can be called without instantiating the class Manager, how do you expect the JVM (and the compiler even) to know what type E is supposed to be? 如果您有一个静态字段或方法(例如“instance”或instance()),可以在不实例化类Manager的情况下调用它,那么您希望JVM(以及编译器甚至)知道E应该是什么类型是?

Here's an example, as per G_H's suggestion: 根据G_H的建议,这是一个例子:

GeneralManager and AreaManager both extend Manager GeneralManager和AreaManager都扩展了Manager

The Manager class is the only one that has the getInstance() static method: 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;
            }
        }
    }

Nope, it's not gonna work. 不,它不会起作用。 Java uses generics at compile time for type checking, but doesn't generate extra classes or retain info regarding type parameters at runtime. Java在编译时使用泛型进行类型检查,但不会在运行时生成额外的类或保留有关类型参数的信息。

When you declare Manager<E> with that type parameter E , that's something that will only play a role in an actual instance. 当您使用该类型参数E声明Manager<E>时,这只会在实际实例中发挥作用。 You could have a subclass like GroupManager extends Manager<String> or whatever, but that's not magically gonna generate a variety of the static method. 您可以拥有像GroupManager extends Manager<String>这样的子类GroupManager extends Manager<String>或者其他什么,但这并不会产生各种静态方法。

Static methods and members belong with a class, not an instance. 静态方法和成员属于类,而不是实例。 So trying to use generics there, which are intended for typing instances, isn't gonna fly. 因此,尝试在那里使用泛型,用于打字实例,是不会飞的。

 public class Manager<E>{ private static Object instance = null; public static E Instance() { if (instance == null) { instance = new E(); } return (E)instance; } } 

If you make your group manager class as follows then you can call your instance method. 如果您按照以下方式创建组管理器类,则可以调用实例方法。

public class GroupManager extends Manager<GroupManager>{}

And in your Manager class try this... 在你的经理类中试试这个......

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;  
}

Or if you know the object you want an instance for, just make the method generic 或者,如果您知道要实例的对象,只需使该方法通用即可

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;
    }

I havn't tried any of this so not sure if it will work. 我没有尝试过这些,所以不确定它是否会起作用。

Injecting the constructor in a generic context. 在通用上下文中注入构造函数。 Cash is not thread safe, but is only used in static context so its fine if you don't miss use it 现金不是线程安全的,但仅在静态环境中使用,所以如果您不错过使用它就可以了

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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM