Java Generics: Почему явное приведение вызывает ошибку компилятора, а назначение переменных - нет

1

Этот блок правильно компилируется:

ArrayList<Baz> list = savedInstanceState.getParcelableArrayList("foo");
bar(list);

Но эти ошибки блока, в которых указано, что ArrayList<Parcelable> нельзя отнести к ArrayList<Baz>:

bar((ArrayList<Baz>)savedInstanceState.getParcelableArrayList("foo"))

Где бар имеет вид:

private void bar(ArrayList<Baz> food) {
}

И Baz - это класс, реализующий интерфейс Parcelable

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

  • 0
    Какой тип возвращает saveInstanceState.getParcelableArrayList ()?
Теги:

4 ответа

0
Лучший ответ

Какова ошибка, которую вы получаете; Я бы подумал, что вы получите предупреждение только о том, что это неконтролируемый актерский состав. Если это так, вам нужно добавить @SuppressWarnings("unchecked") в функцию, из которой вы находитесь. Если честно; вам лучше всего создать отдельную переменную, чтобы поймать возвращаемое значение, а затем отправить переменную.

Одна из проблем, которые вы увидите здесь, - это то, что стирание типа Java может навредить вам. Если T объявляется по-разному между вызывающей функцией и функцией приема, когда T удаляется, нет ничего, что помешало бы кому-либо фактически отправить вашу функцию, которая ожидает, что ArrayList будет ArrayList. Вот почему это проблема безопасности типов.

  • 0
    Как сообщает Eclipse: «Невозможно привести из ArrayList <Parcelable> к ArrayList <T>»
  • 0
    Да, хотя вы можете преобразовать ArrayList <Parcelable> в ArrayList <? расширяет Parcelable> однако ArrayList <ExtensionOfParcelable> до ArrayList <? Расширяет Parcelable> не расширяет. Это означает, что Java плохо справляется с ковариацией / контравариантностью.
Показать ещё 1 комментарий
1

У меня такая же проблема, и мое решение - создать метод для преобразования Parcelable в Baz. Например..

private ArrayList<Baz> convertParcelableToBaz(ArrayList<Parcelable> parcelableList){
    ArrayList<Baz> bazList= new ArrayList<Baz>();
    for (int i = 0 ; i < parcelableList.size(); i++){
        bazList.add((Baz)parcelableList.get(i));
    }
    return bazList;
}

так что

ArrayList<Baz> list = convertParcelableToBaz(savedInstanceState.getParcelableArrayList("foo"));

и предупреждение о непроверенной броске.

1

Чтобы использовать ссылку метода bar(ArrayList<T> food), вы должны выполнить вызов общего типа, который заменяет T на какое-то конкретное значение. T должен быть ограничен некоторым типом else, ввести подстановочные знаки, такие как bar(ArrayList<?> food).

  • 0
    Использовал T там как конкретный класс. Обновил вопрос, чтобы сделать это более понятным.
  • 0
    Для вашего обновления универсальный привязан к «Baz», пока вы отправляете ему ArrayList <Parcelable>. Компилятор считает эти ограниченные типы несовместимыми.
1

Оба этих блока одинаковы. Возьмите это как пример, который компилирует:

import java.util.ArrayList;

public class Test<T> {

    public void test(){
        ArrayList<T> list = (ArrayList<T>)foo();
        bar(list);
        bar((ArrayList<T>)foo());
    }
    private ArrayList<Integer> foo(){ return null; }    
    private void bar(ArrayList<T> food) {}  
}
  • 0
    мой ответ был основан на предыдущей версии вопроса, в которой использовалась буква T, которая, на мой взгляд, была переменной типа. тогда это было изменено на Баз.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню