Приведение переменных в Java - PullRequest
77 голосов
/ 13 марта 2011

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

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

Ответы [ 4 ]

171 голосов
/ 13 марта 2011

Приведение в 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.)

7 голосов
/ 13 марта 2011

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

5 голосов
/ 13 марта 2011

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

Но вы можете привести свой 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
2 голосов
/ 13 марта 2011

Приведение ссылки будет работать, только если это 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...