Подтвердить что ты не робот

Передача в нереализованные интерфейсные компиляции

Я не уверен, что понимаю код в строке 1 ниже?

interface Talkable{ }
class Device{}
class Phone extends Device implements Talkable{}


Talkable d = (Talkable) new Device(); //line 1
Talkable p = new Phone(); //line 2

Я понимаю строку2, поскольку Phone реализует Talkable, но Device and Talkable не связаны между собой, как Line1 может быть законным?

4b9b3361

Ответ 1

Собственно, в Java вполне допустимо применять один родственный тип к другому (даже если кастинг имеет мало смысла). Во время выполнения вы получите сообщение об ошибке, если типы несовместимы.

Например:

    public static void main(String[] args) {
        String s = (String) new Object();
        System.out.println(s.intern());

    }

Компилирует отлично, но дает Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String at Sample.main(Sample.java:5) во время выполнения

Ответ 2

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

Учитывая ссылочный тип времени компиляции S (источник) и тип задания времени компиляции T (target), существует преобразование каста от S до T, если ошибки времени компиляции не происходят из-за следующих правил.

Если S - тип класса:

  • Если T - тип класса, то либо | S | <: | T | или | T | <: | S |. В противном случае возникает ошибка времени компиляции.

Кроме того, если существует супертип X из T и супертип Y из S, такой, что оба X и Y являются предсказуемыми различными параметризованными типами (п. 4.5) и что стирания X и Y одинаковы, a ошибка времени компиляции.

  • Если T - тип интерфейса:

    • Если S не является окончательным классом (§8.1.1), то, если существует супертип X из T и супертип Y из S, такой, что и X, и Y доказуемо различны параметризированных типов и что стирания X и Y одинаковы, возникает ошибка времени компиляции.

      В противном случае листинг всегда является законным во время компиляции (потому что даже если S не реализует T, может быть подкласс S).

В вашем случае a java.lang.ClassCastException будет запущен во время выполнения, так как Device не может быть преобразован в Talkable. Но до тех пор, пока программа не выполнится, компилятор разрешает трансляцию, потому что может существовать подкласс Device, который реализует Talkable.

Ответ 3

Строка 1 будет генерировать исключение во время выполнения. Компилятор не проверяет время компиляции, если приведение может быть выполнено успешно. Вот почему иногда рекомендуется сначала проверить это с помощью оператора instanceof.

В общем случае вы всегда можете использовать переменную x типа A для любого интерфейса C, потому что может существовать класс B extends A implements C или класс B implements A, C

То же самое не относится к кастованию переменной x класса A для любого класса D, потому что не может существовать подкласс E extends A, D, потому что класс не может расширять несколько классов.

Ответ 4

Практически в первой строке код явно "сообщает" компилятору, что объект с правой стороны является объектом типа с левой стороны (это называется type casting). Это справедливо в отношении любых двух типов Java во время компиляции, но если типы не связаны друг с другом, возникает ошибка времени выполнения (будет отклонено Exception).

В строке 2 выполняется то, что сделано как во время компиляции, так и во время выполнения, потому что Phone имеет любой тип, который он расширяет и/или реализует, поэтому практически, Телефон является Talkable (и a Device),.