2012-06-29 2 views
0

Следующий код не работает, потому что отмеченная строка не компилируется:Переходя класс к способу создания экземпляра универсального

MyClass { 
    //singleton stuff 
    private static MyClass instance; 
    private MyClass() {} 
    public static MyClass getInstance() { 
     if(instance==null) { 
      instance = new MyClass(); 
     } 
     return instance; 
    } 

    // method creating problems 
    public NonGenericSuperClassOfGenericClass create(Class<?> c1, Class<?> c2) { 
     return new GenericClass<c1,c2>; // DOES NOT COMPILE!!! 
    } 
} 

Я не хочу MyClass быть общим. Почему? Поскольку фактическая реализация методы создания похоже на следующее:

// method creating problems 
    public NonGenericSuperClassOfGenericClass create(Class<?>... classes) { 
     if(someCondition) 
      return new GenericClass<classes[0],classes[1]>; 
     else 
      return new OtherGenericClass<classes[0]>; 
} 

Поэтому я не могу пару MyClass к каким-либо конкретным дженерик. Есть ли способ создать экземпляр моего GenericClass с переданными параметрами? Как?

Благодаря


Спасибо за ваши ответы. Я расскажу вам всю историю.

Я использую Spring, и я планирую использовать MongoDB.

Класс GenericClass это что-то вроде:

GenericClass<PersistetType1, Long> 

или

GenericClass<PersistentType2, Long> 

где PersistentType1/2 классы, что мне нужно, наконец, хранить в БД, в то время, GenericClass является своего рода прокси для доступа к API Mongo. На самом деле это выглядит так:

public MongoTemplate getTemplate(); 
    public void save(T toInsert); 
    public List<T> select(Query selectionQuery); 
    public T selectById(ID id); 
    public WriteResult update(Query selectionQuery, Update updatedAttributes); 
    public void delete(T toRemove); 
    public void delete(Query selectionQuery); 

Теперь, что? Из контроллеров (или Entity, если вы придирчивы) Мне нужно создать экземпляр репозитория и вызвать любые методы. Это приводит к тому, что контроллеры соединяются с MongoDB, т. Е. Они явно должны создавать экземпляр такого GenericClass, который на самом деле называется MongoRepository и строго зависит от Mongo (на самом деле он является общим с ровно двумя «степенями свободы»).

Итак, я решил создать MyClass, это еще один прокси-сервер, который изолирует контроллеры. Таким образом, контроллер может получить единственный экземпляр MyClass и создать новый экземпляр соответствующего репозитория. В частности, когда «somecondition» истинно, это означает, что мы хотим использовать MongoRepository (когда это ложно, возможно, необходимо создать экземпляр Hibernate proxy, то есть HibernateRepository). Однако MongoRepository является общим, поэтому он требует некоторой формы инстанцирования, которую я надеялся передать в качестве параметра.

К сожалению, дженерики разрешены во время компиляции, поэтому они не работают для меня, я думаю.

Как это исправить?

+2

Нет смысла определять параметры типа во время выполнения из-за стирания типа. Либо пересмотреть свой дизайн, либо не указывать параметры типа. – trutheality

+0

я обобщил свой вопрос здесь: [http://stackoverflow.com/questions/11267441/spring-mongo-generics-flexibility][1] [1]: http://stackoverflow.com/questions/11267441/spring-mongo-generics-flexible – Manu

ответ

0

Путь к параметризуем родовым с другим родовым: T1>. Таким образом, я получаю муфту, в которой я нуждаюсь. Соответствующий выбор AnotherClass дает ожидаемый результат.

6

Это не имеет смысла, особенно в Java.

Весь смысл дженериков заключается в том, чтобы указать на времени компиляции, каковы типы.

Если вы не знаете, какие типы находятся во время выполнения, то дженерики Java будут бесполезны из-за стирания типа. (в C# вам понадобится отражение)

+0

Я знаю класс во время компиляции. Пожалуйста, прочитайте другие ответы и более внимательно мой вопрос. – Manu

+0

@Manu: У вас может быть экземпляр класса ', но вы не знаете конкретный тип во время компиляции. Как утверждают другие ответы, вы не можете использовать такие дженерики. – SLaks

+0

Путь заключается в параметризации общего с другим общим типом: T1 >. Таким образом, я получаю муфту, в которой я нуждаюсь. Соответствующий выбор AnotherClass дает ожидаемый результат. – Manu

2

Из-за Type Erasure первая реализация может учитывать только реализацию типов сыпучих продуктов.

// Similar to original method 
@SuppressWarnings("rawtypes") 
public Map<?, ?> create(Class<?> c1, Class<?> c2) { 
    return new HashMap(); 
} 

уборщик альтернативой было бы следующее:

// A more generic alternative 
public <S, T> Map<S, T> create2(Class<? extends S> c1, Class<? extends T> c2) { 
    return new HashMap<S, T>(); 
} 

Обе реализации делает точно то же самое во время выполнения. Второй лучше, так как его подпись зависит от его аргументов (while create возвращает a Map<?, ?>, второй может вернуть Map<String, Integer>)

+0

Да, но таким образом я фиксирую возвращаемый тип на карте , т. Е. На двух классах. Возможно, мне нужно вернуть AnotherMap или также ADifferentMap (нет общего). – Manu

1

Нет необходимости передавать объекты класса во время выполнения. Дженерики - это чисто компиляция. Поскольку (кажется,) вы возвращаете не-общий тип, и поэтому вы все равно отбрасываете общие параметры (я не знаю, почему вы это сделаете, но так как вы, я пойду с этим), это не имеет значения, что вы используете в качестве параметра. Любой параметр типа, который проходит тип проверки будет достаточно:

public NonGenericSuperClassOfGenericClass create() { 
    if(someCondition) 
     return new GenericClass<Object,Object>(); 
    else 
     return new OtherGenericClass<Object>(); 
} 
+0

На самом деле есть необходимость, потому что мне нужно точно знать, что это такое в экземпляре GenericClass, который я создаю, поэтому я должен дать указания здесь. Наверное, дело в том, что мне не нужны дженерики. – Manu

+1

@ user1490144: Но во время выполнения между вновь созданным «GenericClass » и недавно созданным «GenericClass » существует * различие *. Это просто фикция, используемая во время компиляции. Невозможно «точно знать, что в нем», потому что нет никакой разницы. – newacct

1

Одна вещь приходит на ум что-то вдоль линий:

public NonGenericSuperClassOfGenericClass create(Class<?>... classes) { 
    if(someCondition) 
     return new helper1(classes[0],classes[1]); 
    else 
     return new helper2(classes[0]); 
} 

public <R,T> GenericClass<R,T> helper1(Class<R> a, Class<T> b){ 
    return new GenericClass<R,T>(); 
} 

public <T> OtherGenericClass<T> helper2(Class<T> a){ 
    return new OtherGenericClass<T>(); 
} 
Смежные вопросы