Нет 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];
}
Этот метод вернет фактический класс. Это работает, это отвратительно. Это зависит от вас.