2010-10-22 2 views
3

Почему выполняется компиляция следующего кода?
Почему разрешено приводить общий список к его параметру типа, если параметр является интерфейсом , но не супер-интерфейсом общего?Почему общий список может быть передан его параметру типа

Что это значит?

//Connection can be substituted by any interface 
List<Connection> list = null; 
Connection c = (Connection) list; 

ответ

12

Это не имеет никакого отношения к параметру типа. Это работает так:

List<String> list = null; 
Connection c = (Connection) list; 

Это возможно потому, что List является тип интерфейса. Ссылка на список может содержать объект, который реализует интерфейс List, и также также a Connection (что бы это ни было, класс или интерфейс), и для чего оно действует.

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

JComponent c = null; 
    ArrayList l = (ArrayList) c; 

Вы можете посмотреть точные правила для того, что виды забросов законны во время компиляции в Java Language Specification - это о 30 линий гуманной языковой адвокации.

+1

+1 - Но ... * «Это будет только отклонять броски, которые теоретически невозможны ...» *, основанные исключительно на объявленных типах. Например, если список был инициализирован окончательным классом «List», который не реализовал или не расширил «Connection», компилятор * still * должен разрешить это. –

0

Он компилируется, но он не работает во время выполнения.

Статическое литье - это один из способов, чтобы разработчик мог рассказать компилятору. Я знаю, что я здесь делаю - я сам обработаю типизацию этих переменных. Компилятор не остановит вас от выполнения чего-то, что вызовет исключение во время выполнения.

+2

Но во время компиляции ясно, что приказ не будет выполняться во время выполнения, не так ли? Компилятор также останавливает меня при попытке сделать String bla = (String) BigDecimal.ZERO; так почему бы и нет? – MRalwasser

+0

Более точно это вызовет java.lang.ClassCastException. – Dave

+4

-1: Вообще-то это будет * не * сбой во время выполнения, потому что null совместим со всеми типами. И компиляция * будет * отклонять отбрасывания, которые являются беспроблемными. –

0

То же самое, как с другим приведением типов. Вам разрешено использовать любой объект для любого другого. Компиляторы не допускают самого идиотского typecasting (например, List to String), но все же - вам решать, как выглядеть. Как правило, используйте

if(a instanceof bClass){ 
    ((bClass)a).doSomething(...); 
} 
+0

Что именно делает какой-то идиотский стиль? Вот в чем вопрос? – Ishtar

+0

@Ishtar: в случае с List to String он не может работать, потому что String не реализует List и является окончательным. JLS задает этот тип вещей (смотря сейчас). –

+0

@ Мичел - Да, это то, что я тоже понял.Я просто имел в виду с комментарием, что этот ответ не отвечает на вопрос: «Почему разрешено приводить общий список к его параметру типа, если параметр является интерфейсом, но не супер-интерфейсом общего?» – Ishtar

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