#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()
Комментариев нет:
Отправить комментарий