Я использую w7, 64bit и vs.net 2010.
Я добавляю ссылку на компонент, который находится в моем диалоговом окне «Добавить ссылки». Компонент является сторонним dll.
Исторически на w7 32bit он добавил бы строку в мой web.config (внутри тега сборки), ссылающуюся на эту dll, и не скопировал бы dll в каталог bin.
Однако на 64-битном w7 dll копируется в каталог bin, а web.config вообще не обновляется.
Почему dll копируется в каталог bin? спасибо
Решение: (Обновлено) Эти сообщения дали мне подсказки, в которых я нуждался.
VS.NET скопирует dll в каталог bin, если ваша система не может найти dll в GAC. Сборки в GAC (зарегистрированные на вашей рабочей станции) и могут быть найдены, просмотрев каталог C: \ Windows \ Assembly.
Компоненты, перечисленные в vs.net «добавить ссылки диалоговое окно», могут или не могут быть в GAC. Поскольку компонент указан в диалоговом окне «Добавить ссылки», это не значит, что он зарегистрирован на локальной рабочей станции. Я переместился в каталог компонентов и перетащил нужные DLL в каталог C: \ Windows \ Assembly. Я закрыл и снова открыл vs.net, перешел к тем же файлам и нажал «Добавить ссылку».
** Это добавило ссылку на сборку в мою сеть.
Вместо передачи типа списка, который вы хотите создать, почему бы просто не передать пустую коллекцию
Кроме того, в качестве примечания, вы всегда должны программировать максимально общий интерфейс. В этом случае ваш ввод не должен быть чем-то более конкретным, чем Iterable, а ваш вывод — Collection.
Учитывая это, я бы написал метод таким образом --
public static <T, C extends Collection<T>> C typesafeAdd(Iterable<?> from, C to, Class<T> listClass) {
for (Object item: from) {
to.add(listClass.cast(item));
}
return to;
}
тогда код вызова выглядит так:
public static void main(String[] args) {
List<?> untypedStringList = LegacyApi.getStringList();
List<String> typesafeStringList = typesafeAdd(untypedStringList, new ArrayList<String>(), String.class);
}
2 комментария здесь:
Метод Class.newInstance()
выбрасывает два проверяемых исключения IllegalAccessException
и InstantiationException
. Они должны быть либо пойманы, либо объявлены в сигнатуре метода.
Для справки, эти исключения возникают в различных ситуациях; например,
Это фактически не связано с тем, что метод является общим, и связанными с этим проблемами типизации.
Чего вы хотите достичь? Такой код:
List l = new ArrayList();
l.add(new Integer(1));
List<Integer> li = l;
просто работает. Выдает предупреждение, но работает. Однако возможно, что в li
у вас будут объекты, которые не являются экземплярами Integer
. Если хочешь быть уверенным, используй google guava, как ответил ColinD.
Я не верю, что то, что вы пытаетесь сделать, возможно. Это из-за работы Generics:
Во время компиляции проверяются все входящие типы типизированного списка, и все исходящие объекты приводятся к типу списка - и с этого момента мы говорим о нетипизированном «списке». К сожалению, дженерики - это всего лишь синтаксический сахар.
Я бы использовал Guava и его метод Iterables.filter (Iterable, Class) вместе с фабричным методом из Lists
], например так:
List<?> original = ...;
List<String> typed = Lists.newArrayList(
Iterables.filter(original, String.class));
Это фактически проверит каждый объект в исходном списке, и результирующий список будет содержать только те элементы, которые являются экземплярами данного типа ( String
в данном случае) или подтипа. этого. Я действительно не думаю, что имеет смысл заставлять пользователей предоставлять Class
для результирующего типа List
и пытаться создать его экземпляр через отражение.
Опять гуава, но позволяет лучше контролировать преобразование, если оно сложнее, чем приведение типов или еще много чего.
public List<L> convert(List<T> list) {
return Lists.transform(list,new Function<T,L>() {
public Object apply(T from) {
L magic = (L)from;
/* magic here */
return magic;
}});
}
У вас проблема во время выполнения, поэтому она не должна зависеть от универсальных шаблонов. Во время выполнения все в любом случае «является объектом». Если вы не можете создать экземпляр listClass
, тогда вы действительно передаете реализацию java.util.List
, которая не предлагает (общедоступный) пустой конструктор.
Итак, решение вашей проблемы находится вне этого метода. Вызов его типа
List<String> result = typedList(untypedList, String.class, ArrayList.class);
не должен приводить к ошибке времени выполнения.
Теперь мое затмение близко. Следующий код компилируется и без предупреждений и должен соответствовать вашему требованию: преобразовать из нетипизированного списка в типизированный список.
public static <T> List<T> typedList(List<?> untypedList, Class<T> itemClass) {
List<T> list = new ArrayList<T>();
for (Object item : untypedList) {
list.add(itemClass.cast(item)); // TODO - handle ClassCastExpception
}
return list;
}
Если вы не хотите получать предупреждение и не хотите использовать google guava, вы должны реализовать что-то похожее на guava самостоятельно. Например: [
private static <T> List<T> typeList(List<?> l, Class<T> klass) {
List<T> list = new ArrayList<T>();
for(Object obj : l) {
if (klass.isAssignableFrom(obj.getClass())) {
list.add((T) obj);
}
}
return list;
}
] Эта реализация просто пропускает элементы, которые не являются экземплярами T, но вы также можете генерировать исключение или делать все, что захотите.
Пожалуйста, не используйте отражения для подобных вещей!
Я бы рассматривал это как случай трансформации. Возможно что-то вроде
public static <D, S> transform(
List<D> dst,
List<S> src,
Transformer<? extends D, ? super S> transformer
) { ... }
Используйте фабрику для Списка<>
, если хотите.