как найти тип коллекции? - PullRequest
       8

как найти тип коллекции?

3 голосов
/ 29 августа 2011

У меня есть две переменные

Collection<Service> services = new ArrayList<Service>();
Collection<Subscription> subscriptions = new ArrayList<Subscription>();

и у меня есть следующий метод, мне было интересно, как я могу найти значение "?" в этом методе, или как я могу найти, если услуги были переданы или подписки были переданы?

myMethod(Collection<?> myCollection) {

   if (myCollection is of type Service) {
      // process service
   }
   else if (myCollection is of type Subscription) {
      // process subscription
   }
}

Спасибо.

Ответы [ 4 ]

4 голосов
/ 29 августа 2011

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

Если ваша коллекция не пуста, вы можете сделать instanceof для первого элемента или чего-то еще, конечно.

2 голосов
/ 29 августа 2011

Вы не можете (кроме , используя отражение ), так как параметр универсального типа стирается во время компиляции.

И я бы порекомендовал вам переосмыслить свой дизайн, а не пытаться решить его с помощью дженериков. Передача произвольных типов коллекций в один и тот же метод является способом решения проблем в долгосрочной перспективе.

2 голосов
/ 29 августа 2011

Использование этой конструкции if-else в обобщенном методе отрицательно сказывается на назначении обобщений.Если вам нужно знать тип того, что передается во время выполнения, оно действительно не должно быть универсальным, и вы должны написать отдельный метод для каждого типа.

1 голос
/ 29 августа 2011

Нет Java-способа сделать именно это. Тип Erasure мешает. И если вам нужно сделать это, это также, вероятно, проблема дизайна. Но если нужно, есть ужасный способ сделать это почти так:

Измените ваши переменные на

Collection<Service> services = new ArrayList<Service>(){};
Collection<Subscription> subscriptions = new ArrayList<Subscription>(){};

Обратите внимание на {} после (). Вы создаете не ArrayList, а анонимный класс, который наследуется от ArrayList. И тип стирания там не распространяется. Таким образом, вы можете определить реальный тип, выполнив что-то вроде

private static Class<?> detectType(Collection<?> col) {
    return (Class<?>) ((ParameterizedType) col.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

Этот метод вернет фактический класс. Это работает, это отвратительно. Это зависит от вас.

...