Страницы

Поиск по вопросам

среда, 11 декабря 2019 г.

Абстрактный класс-Singleton на java

#java


Некоторое время назад писал на юнити. Использовал на шарпе такой класс:

public abstract class MySingleton
{
    private static T _instance;

    public static T Instance
    {
        get
        {
            if (_instance == null)
                _instance = (T)Activator.CreateInstance(typeof(T));

            return _instance;
        }
    }

    public static void ForgetInstance()
    {
        _instance = default(T);
    }

    protected MySingleton()
    {

    }


Можно ли как-то извернуться, чтобы написать похоже на java?

В лоб то, говорит: "Cannot make a static reference to the non-static type T"


    


Ответы

Ответ 1



Как я понимаю, хочется хранить по одному объекту для каждого запрошенного класса, созданному с помощью конструктора по умолчанию. Для этой цели можно завести ConcurrentHashMap, Object>: import java.util.concurrent.ConcurrentHashMap; public class MySingleton { private static ConcurrentHashMap, Object> map = new ConcurrentHashMap<>(); @SuppressWarnings("unchecked") public static T getInstance(Class clazz) { T object = (T) map.get(clazz); if(object == null) { try { object = clazz.newInstance(); } catch (IllegalAccessException | InstantiationException | SecurityException ex) { throw new RuntimeException(ex); } T oldObject = (T) map.putIfAbsent(clazz, object); if(oldObject != null) // ой, другой поток вперёд успел return oldObject; } return object; } public static void forgetInstance(Class clazz) { map.remove(clazz); } } Соответственно использовать как-то так: public static void main(String[] args) { String str = MySingleton.getInstance(String.class); String str2 = MySingleton.getInstance(String.class); System.out.println(str == str2); // true MySingleton.forgetInstance(String.class); }

Ответ 2



Статическую generic-переменную создать не получится. Если переменная должна быть статичной, чтобы конкретизировать строго одну переменную на класс, то можно попробовать создать статичный экземпляр класса и оперировать уже с ним. Инициировать такой экземпляр класса можно через конструктор. // T-переменная нестатична private T _instance; /* Tclass = T.class * запоминаем для упрощения, инициируем в конструкторе */ private static Class Tclass; /* Статический элемент класса MySingleton * класс непараметризован, чтобы остаться статическим */ private static MySingleton mysingleton; // Конструктор создает экземпляр синглтон-класса protected MySingleton(){ mysingleton = new MySingleton(){}; Tclass = ((Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]); } Вернуть из статического метода generic-переменную, опять-таки, не получится. Тут есть два возможных выхода: 1) Создать экземпляр класса через уже имеющийся конструктор и обращаться впредь к нестатичному методу 2) Если T является подклассом Object, то статический класс может возвращать Object Дефолтное же значение Т-переменной можно получить, например, через конструктор: Tclass.getConstructor().newInstance()

Комментариев нет:

Отправить комментарий