2013-04-12 2 views
6

Я столкнулся с проблемой при выполнении домашней работы для класса онлайн-алгоритмов. Кастинг Object[] к T[] где Т Сопоставимые возникает исключение времени выполненияЛистинг массива объектов в массив сопоставимых

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[]) new Object[xs.length]; 
    mergeSort(xs, aux, 0, xs.length); 
} 

Я мог бы переписать его в C#, который не имеет никаких проблем с созданием родовых массивов, но я предпочел бы узнать, как справиться с этим в Ява.

+0

Я думаю, вы должны увидеть http://stackoverflow.com/questions/1817524/generic-arrays-in-java это довольно интересно. –

ответ

12

Если вы получаете исключение во время выполнения, это означает, что объекты, которые вы пытались использовать, не имеют такого типа. Язык не имеет к этому никакого отношения. Вероятно, в вашем коде есть ошибка.

Редактировать: Похоже, вы смущены тем, как работает система типов Java. В C# дженерики фактически представляют разные типы во время выполнения. В Java общие типы не существуют во время выполнения. Они являются лишь удобством, позволяющим лучше проверять тип времени компиляции. Во время компиляции дженерики заменяются реальным типом в процессе, известном как стирание типа.

Обычно стирание родового типа Object, но поскольку вы указали верхнюю границу для T, она преобразуется в эту границу, Comparable. Поэтому после стирания ваш код выглядит следующим образом.

Comparable[] aux = (Comparable[]) new Object[xs.length]; 

В других случаях, вы создаете массив типа Object[] и немедленно пытается бросить его типа Comparable[]. Поскольку Object не реализует Comparable, типы несовместимы, поэтому вы получаете исключение во время выполнения. Вы можете исправить это, создав вместо этого массив из Comparable s.

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[]) new Comparable[xs.length]; 
    mergeSort(xs, aux, 0, xs.length); 
} 
+0

Очевидно, что есть ошибка, и, очевидно, это как-то связано с тем, как Java обрабатывает дженерики. В C# нет проблемы с созданием массивов с параметром ограниченного типа. – synapse

+0

@synapse Я отредактировал свой ответ, чтобы, надеюсь, прояснить ситуацию для вас. – Antimony

2

Массивы являются ковариантными, и это означает, что они сохраняют тип своих элементов во время выполнения. Генералов Java нет. Поэтому в основном они не смешиваются.

Смотрите также: Generic arrays in Java

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

3

Попробуйте это:

public static <T extends Comparable<? super T>> void mergeSort(T[] xs) { 
    T[] aux = (T[])java.lang.reflect.Array.newInstance(xs.getClass().getComponentType(), xs.length); 
    mergeSort(xs, aux, 0, xs.length); 
} 
+0

Спасибо. Неудивительно, что часто задаваемые вопросы Java Generics составляют сто страниц. – synapse

+0

Существует гораздо более простой способ сделать это. См. Мой ответ. – Antimony

+0

Проще, но опасно. Вы также можете просто изменить тип следующим образом: >, и он будет компилироваться и запускаться даже с исходным кодом (зависит от подписи метода mergeSort). Но, например, если T всегда является String и вы пытаетесь сделать String [] aux2 = (String []) aux, вы получите исключение. Аналогичная проблема имеет и ваш массив Comparable. Так что это проще, но может не работать все время. – jdb

Смежные вопросы