Переменные в Java

Интересно, может ли кто-нибудь сказать мне, как работает кастинг? Я понимаю, когда я должен это делать, но не так, как это работает. В примитивных типах данных я понимаю частично, но когда дело доходит до каста объектов, я не понимаю, как это работает.

Как может объект с типом Object просто быть брошен, скажем, MyType (только пример), а затем получить все методы?

Ответ 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.)

Ответ 2

Собственно, кастинг не всегда работает. Если объект не является instanceof классом, который вы его передаете, вы получите ClassCastException во время выполнения.

Ответ 3

Предположим, что вы хотите привести String к File (да, это не имеет никакого смысла), вы не можете привести его напрямую, потому что класс File не является дочерним и не является родительским для класса String ( и компилятор жалуется).

Но вы можете привести ваш String к Object, потому что String - это Object (Object - родитель). Затем вы можете привести этот объект к File, потому что файл - это Object.

Таким образом, все ваши операции являются "законными" с точки зрения ввода во время компиляции, но это не означает, что они будут работать во время выполнения!

File f = (File)(Object) "Stupid cast";

Компилятор разрешит это, даже если это не имеет смысла, но во время выполнения произойдет сбой, за исключением:

Exception in thread "main" java.lang.ClassCastException:
    java.lang.String cannot be cast to java.io.File

Ответ 4

Выполнение ссылки будет работать только в том случае, если это тип instanceof. Вы не можете использовать произвольные ссылки. Кроме того, вам нужно больше узнать о Casting Objects.

например.

String string = "String";

Object object = string; // Perfectly fine since String is an Object

String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.

Ответ 5

Правильный путь таков:

Integer i = Integer.cast(obj);

Метод cast() является гораздо более безопасной альтернативой приведению во время компиляции.