Ответ 1
Кастинг в Java не является волшебным, и вы говорите компилятору, что объект типа A на самом деле имеет более специфический тип B и, таким образом, получает доступ ко всем методам на B, которых вы не имели бы в противном случае. Вы не выполняете какой-либо магии или конверсии при выполнении кастинга, вы, по сути, говорите компилятору: "Поверьте мне, я знаю, что я делаю, и я могу гарантировать, что этот объект в этой строке на самом деле является < Insert тип литья здесь > ." Например:
Object o = "str";
String str = (String)o;
Это хорошо, а не волшебство и все хорошо. Объект, хранящийся в o, на самом деле является строкой, и поэтому мы можем без проблем накладывать на строку.
Там два пути могут пойти не так. Во-первых, если вы перебрасываете два типа в совершенно разных иерархиях наследования, тогда компилятор будет знать, что вы глупы, и остановите вас:
String o = "str";
Integer str = (Integer)o; //Compilation fails here
Во-вторых, если они находятся в одной иерархии, но все еще недействительны, тогда во время выполнения будет выбрано ClassCastException
:
Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here
Это означает, что вы нарушили доверие к компилятору. Вы сказали, что можете гарантировать, что объект имеет определенный тип, и это не так.
Зачем вам кастинг? Ну, для начала вам нужно только это, когда переходите от более общего типа к более конкретному типу. Например, Integer
наследует от Number
, поэтому, если вы хотите сохранить Integer
как Number
, тогда это нормально (поскольку все целые числа - это числа). Однако, если вы хотите пойти наоборот нужен листинг - не все числа являются целыми (как и Integer, мы имеем Double
, Float
, Byte
, Long
и т.д.). И даже если в вашем проекте или JDK есть только один подкласс может легко создать другое и распространить его, поэтому у вас нет гарантии, даже если вы считаете это одним, очевидным выбором!
Что касается использования для кастинга, вы по-прежнему видите необходимость в нем в некоторых библиотеках. Предварительная Java-5 использовалась в коллекциях и других классах, поскольку все коллекции работали над добавлением объектов, а затем выдавали результат, который вы получили из коллекции. Однако с появлением дженериков большая часть использования для кастинга ушла - его заменили дженерики, которые обеспечивают гораздо более безопасную альтернативу, не имея возможности для ClassCastExceptions (на самом деле, если вы используете дженерики чисто и компилируются без предупреждений, у вас есть гарантия, что вы никогда не получите исключение ClassCastException.)