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