Ложное приведение из класса генерирует ошибку, в то время как (поддельное) приведение из интерфейса - нет? - PullRequest
0 голосов
/ 06 октября 2011
    // Casting of class
    ArrayList a1 = new ArrayList<Integer>();
    Number n1 = (Number)a1; // clause 1 Error 
    AdjustmentListener c1 = (AdjustmentListener)a1; // Clause 2 No error
    EventListener c3 = (EventListener)a1; // Clause 3 No error

Исходя из вышеизложенного, пункт 1 содержит ошибку.Логический.Нет никакой связи между этими двумя классами.Для пункта 2 нет никакой связи между arrayList (классом) и интерфейсом Adjustlistener.Почему нет ошибки?

РЕДАКТИРОВАТЬ 1:

    String str1 = new String();
    AdjustmentListener c2 = (AdjustmentListener)str1; // clause 4 compiler error

Ответы [ 4 ]

1 голос
/ 06 октября 2011

Я полагаю, что в этой ситуации вы запутались, потому что a1 - это ArrayList, а l1 - это список интерфейс , использующий ArrayList в качестве реализации .Список позволяет вам делать конкретное приведение, а ArrayList - нет.В этом конкретном случае вы не можете приводить при ссылке на реализацию, но вы можете при ссылке на интерфейс.

1 голос
/ 06 октября 2011

Компилятор знает, что ArrayList никогда не может быть Number, потому что в Java вы можете наследовать только от одного суперкласса. Он не может знать, если нет типа, который реализует List и наследует от Number, т.е. вы могли бы успешно преобразовать значение следующего типа в List и Number:

class ListNumber extends Number implements List {
    ....
}
0 голосов
/ 07 октября 2011

В случае поддельного приведения из выражения с классом типом результата компилятор знает приведение никогда не может быть действительным и, таким образом, он отказываетсяскомпилировать с ошибкой во время компиляции.(Изменение того, что класс расширяет или реализует, является критическим изменением: во избежание нечетных исключений времени выполнения код должен быть заново скомпилирован с новой структурой класса.)

Однако при приведении из выражения с interface тип результата: компилятор не может (обычно) определить, что приведение никогда не будет действительным (но учитывает final типы);как таковой ошибки компиляции нет.Однако при попытке поддельного приведения произойдет исключение во время выполнения.

Представьте себе этот небольшой компилируемый пример (обратите внимание, что генерики не имеют отношения к сообщению ):

interface I {}
class A implements I {}
class B {}
// Imagine class BB is defined as such later.
//class BB extends B implements I {}
final class C {}

public class test1 {
    public static void main(String[] args) {
        A a = new A();
        // ERROR: "Cannot cast from A to B"
        // Compiler knows that B is not a super-type of A.
        B b1 = (B)(new A());
        // Valid: A implements I
        I i = (I)(new A());
        // RUNTIME EXCEPTION: Compiles, but will fail at run-time
        // as B is not a super-type of A. The compiler allows
        // this because B could have a sub-type (BB) which
        // implements the interface (I) and the cast from a
        // sub-type (BB) to a super-type (B) is valid.
        B b2 = (B)i;
        // ERROR: Cannot cast from I to C
        // Compiler knows C cannot have a sub-type which implements
        // the interface (I) and thus it can reject the program.
        // (Note that C is a final class and cannot be extended.)
        C c = (C)i;
        // Valid (when defining BB): no run-time exception as B is
        // is a super-type of BB.
        //B b3 = (B)(I)(new BB());
    }
}

Удачного кодирования.

0 голосов
/ 06 октября 2011

Для успешного приведения, должен быть некоторый возможный реализатор обоих аргументов.Возьмем, к примеру, следующие мнимые объявления классов:

<code>
5: class ComparableArrayList extends ArrayList implements Comparable
7: class NumberList extends Number implements List
8: class ComparableList implements Comparable, List
Экземпляр каждого из них позволит выполнить приведение успешно.В пункте 4 для того, чтобы приведение к работе, вам понадобится
<code>
class NumberArrayList extends ArrayList, Number
, а Java не разрешает множественное наследование.

РЕДАКТИРОВАТЬ для отредактированного вопроса:

В пункте 1 не существует возможных отношений между классами, потому что вы не можете иметь класс, расширяющий как ArrayList, так и Number.В пунктах 2 и 3 можно создать отношение, создав новый класс, расширяющий ArrayList и реализующий AdjustmentListener.Затем установите a1 для экземпляра этого класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...