// Полностью общая сортировка для использования с gridview
public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
{
List<T> data_sorted = new List<T>();
if (sortDirection == "Ascending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n).ToList();
}
else if (sortDirection == "Descending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) descending
select n).ToList();
}
return data_sorted;
}
public object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}
Синтаксис такого назначения присваивания использует подстановочный знак:
List<SubClass> subs = ...;
List<? extends BaseClass> bases = subs;
Важно понимать, что List<SubClass>
не является взаимозаменяемым с List<BaseClass>
. Код, который сохраняет ссылку на List<SubClass>
, ожидает, что каждый элемент в списке будет SubClass
. Если другая часть кода относится к списку как List<BaseClass>
, компилятор не будет жаловаться, когда вставлены BaseClass
или AnotherSubClass
. Но это приведет к ClassCastException
для первого фрагмента кода, который предполагает, что все в списке является SubClass
.
Общие коллекции не ведут себя так же, как массивы в Java. Массивы ковариантны; то есть разрешено это делать:
SubClass[] subs = ...;
BaseClass[] bases = subs;
Это разрешено, потому что массив «знает» тип его элементов. Если кто-то пытается сохранить что-то, что не является экземпляром SubClass
в массиве (с помощью ссылки bases
), будет выведено исключение во время выполнения.
Общие коллекции do not «знают» свой тип компонента; эта информация «стирается» во время компиляции. Поэтому они не могут создавать исключение во время выполнения, когда происходит недопустимое хранилище. Вместо этого ClassCastException
будет поднят в некоторой далекой, трудно ассоциируемой точке в коде, когда значение будет считано из коллекции. Если вы прислушаетесь к предупреждениям компилятора о безопасности типов, вы избежите ошибок этого типа во время выполнения.
Как о литье всех элементов. Он создаст новый список, но будет ссылаться на исходные объекты из старого списка.
List<BaseClass> convertedList = listOfSubClass.map(x -> (BaseClass)x).collect(Collectors.toList());
Как пояснил @erickson, если вам действительно нужна ссылка на исходный список, убедитесь, что ни один код не добавляет ничего в этот список, если вы когда-нибудь захотите использовать его снова в своем первоначальном объявлении. Самый простой способ получить это - просто передать его в простой старый список:
List<BaseClass> baseList = (List)new ArrayList<SubClass>();
Я бы не рекомендовал это, если вы не знаете, что происходит со Списком, и предложите изменить его код нуждается в списке, чтобы принять список, который у вас есть.
List<BaseClass> convertedList = Collections.checkedList(listOfSubClass, BaseClass.class)
То, что вы пытаетесь сделать, очень полезно, и я считаю, что мне нужно делать это очень часто в коде, который я пишу. Пример использования:
Скажем, у нас есть интерфейс Foo
, и у нас есть пакет zorking
, который имеет ZorkingFooManager
, который создает и управляет экземплярами package-private ZorkingFoo implements Foo
. (Очень распространенный сценарий.)
Итак, ZorkingFooManager
должен содержать private Collection<ZorkingFoo> zorkingFoos
, но ему нужно выставить public Collection<Foo> getAllFoos()
.
Большинство java-программистов не подумали бы дважды прежде чем реализовать getAllFoos()
как выделение нового ArrayList<Foo>
, заполнив его всеми элементами из zorkingFoos
и вернув его. Мне нравится развлекать мысль о том, что около 30% всех тактовых циклов, потребляемых java-кодом, работающим на миллионах компьютеров по всей планете, ничего не делает, кроме создания таких бесполезных копий ArrayLists, которые собирают микросетки после мусора после их создания.
Решение этой проблемы - это, конечно, сбрасывание коллекции. Вот лучший способ сделать это:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Что приводит нас к функции castList()
:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
Промежуточная переменная result
необходима из-за извращение языка java:
return (List<T>)list;
создает исключение «непроверенного броска»; Все идет нормально; но затем: @SuppressWarnings( "unchecked" ) return (List<T>)list;
является незаконным использованием аннотации подавления-предупреждений. Итак, хотя это не кошерно использовать @SuppressWarnings
на return
, очевидно, что использовать его при назначении, поэтому дополнительная переменная «result» решает эту проблему. (Он должен быть оптимизирован либо компилятором, либо JIT в любом случае.)
Что-то вроде этого тоже должно работать:
public static <T> List<T> convertListWithExtendableClasses(
final List< ? extends T> originalList,
final Class<T> clazz )
{
final List<T> newList = new ArrayList<>();
for ( final T item : originalList )
{
newList.add( item );
}// for
return newList;
}
Не знаю, почему clazz нужен в Eclipse ..
erickson уже объяснил, почему вы не можете этого сделать, но здесь некоторые решения:
Если вы хотите только извлечь элементы из своего базового списка, в принципе ваш метод приема должен быть объявлен как принимающий List<? extends BaseClass>
.
Но если это не так, и вы не можете его изменить, вы можете обернуть список с помощью Collections.unmodifiableList(...)
, который позволяет возвращать список супертипа параметра аргумента. (Он избегает проблемы с типами, бросая UnsupportedOperationException при попытках вставки).
Ниже приведен полезный фрагмент, который работает. Он создает новый список массивов, но создание объекта JVM над головой является значительным.
Я видел, что другие ответы не обязательно сложны.
List<BaseClass> baselist = new ArrayList<>(sublist);