2013-11-06 3 views
6
interface Printable {} 
class BlackInk {} 

public class Main { 
    public static void main(String args[]) { 
     Printable printable = null; 
     BlackInk blackInk = new BlackInk(); 
     printable = (Printable)blackInk; 
    } 
} 

Если предыдущий код скомпилирован и запущен, результатом является исключение ClassCastException по адресу printable = (Printable)blackInk;. Но, если Printable изменен на класс, он не компилируется, потому что blackInk нельзя отнести к Printable. Почему он компилируется, когда Printable является интерфейсом?Почему он компилируется при литье в несвязанный интерфейс?

ответ

15

Компилятор не знает, что это не сработает: у вас может быть подкласс BlackInk, который реализует Printable. Тогда отливка будет прекрасной.

В ситуациях, когда компилятор знает, что это не сработает, вы получите сообщение об ошибке.

Например, если вы делаете BlackInk final (чтобы не было подклассов), вы получаете сообщение об ошибке.

+0

... и поэтому Гид изобрел опасные предупреждения о предупреждении – Bohemian

1

Тип литья происходит в run time (помните полиморфизм времени выполнения). Во время компиляции компилятор не видит ничего плохого в коде и компилирует, и во время выполнения он пытается ввести листинг blackink в printable и не может это сделать, так как blackink не реализует printable, отсюда и ошибка.

9

В соответствии с java language specification section: 5.5.1 Reference Type Casting:

Для компиляции ссылочного типа S (источника) и эталонная компиляции типа типа T (целевого); В то время как литье преобразование из S в T, Если S является class Type

  • Если T является Class типа:

    1. Тогда либо T является подтипом SилиS является подтипом T. В противном случае возникает ошибка времени компиляции.
    2. , если существует супертип X из T, и супертип Y из S, такие , что оба X и Y являются доказуемо различные параметризованные типы, и что подчистки из X и Y являются то же самое, compile- ошибка времени происходит.

      class S{} 
      
      class T extends S{} 
          //// 
      
          S s = new S(); 
          T t = (T)s; // run time ClassCastException will happen but no compile time error 
      
  • Если T является Interface типа:

    1. Если S не final класс, то, если существует супертип X из T и супертипом Y от S, так что оба X и Y являются явно различающимися параметрическими типами , и что стирания X и Y совпадают, происходит ошибка времени компиляции . В противном случае, бросок всегда законный во время компиляции (, потому что даже если S не реализовать T, подкласс S могущества)
    2. Если S является конечным классом, то S должен реализовать T или compile- ошибка времени происходит.

То есть для вашего дела, даже если отливка класса обнаруживается во время компиляции, отливка интерфейса обнаруживаются в runtime.

+1

+1 для цитирования JLS. – yshavit

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