Приведение в Java не волшебство, это вы говорите компилятору, что объект типа A на самом деле имеет более конкретный тип B, и, таким образом, получаете доступ ко всем методам в B, которых у вас не было бы иначе. Вы не выполняете никакой магии или преобразования при выполнении приведения, вы по сути говорите компилятору: «Поверьте мне, я знаю, что я делаю, и я могу гарантировать вам, что этот Объект в этой строке на самом деле является <Вставить приведение». введите здесь>. " Например:
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
, тогда все в порядке (поскольку все целые числа являются числами). Однако, если вы хотите обойти вас по-другому нужен приведение - не все числа являются целыми числами (как и целые числа у нас Double
, Float
, Byte
, Long
и т. д.) И даже если в вашем проекте или JDK есть только один подкласс, кто-то может легко создать другое и распространить его, так что у вас нет гарантии, даже если вы думаете, что это единственный очевидный выбор!
Что касается использования для приведения, вы все еще видите необходимость в этом в некоторых библиотеках. До Java-5 он активно использовался в коллекциях и различных других классах, поскольку все коллекции работали над добавлением объектов и последующим приведением результата, который вы получили из коллекции. Тем не менее, с появлением обобщений большая часть использования для приведения прекратилась - его заменили обобщения, которые предоставляют гораздо более безопасную альтернативу, без возможности для ClassCastExceptions (на самом деле, если вы используете обобщенно чисто, и он компилируется без предупреждений, у вас есть гарантия, что вы никогда не получите ClassCastException.)