2009-11-12 2 views
5

В чем разница между этими двумя способами кастинга в Java?В чем разница между этими двумя способами кастинга в Java?

  1. (CastingClass) objectToCast;

  2. CastingClass.class.cast(objectToCast);

Источник Class#cast(Object) выглядит следующим образом:

public T cast(Object obj) { 
if (obj != null && !isInstance(obj)) 
    throw new ClassCastException(); 
return (T) obj; 
} 

Итак, cast в основном родовой оболочкой операции литой, но Я до сих пор не понять, зачем вам нужен метод для этого.

+0

ОК, так что я просто понял, что вы можете использовать 'cast' бросить в обертку примитивного типа. Например. 'Integer i = int.class.cast (" 1234 ");' –

+0

@simmbot: вы можете _write_ это, но он не будет делать то, что вы, скорее всего, думаете, что оно делает. Попробуй. –

+0

Это вызовет исключение ClassCastException, поскольку String не имеет тип Integer. В этом случае вам понадобится «Integer.valueOf (« 1234 »)». –

ответ

7

Вы можете использовать только первую форму для статически связанных классов.

Во многих случаях этого недостаточно - например, вы могли получить экземпляр класса с использованием отражения или он был передан вашему методу в качестве параметра; следовательно, вторая форма.

+0

Справа. В первом виде вы «выпекаете» листинг в исходном коде. Вы не можете изменить его без перекомпиляции. Вторая форма позволяет попробовать выполнить произвольный класс. –

4

Потому что вы не можете просто написать (T)objectToCast, когда T является параметром общего типа (из-за стирания типа). Java-компилятор позволит вам это сделать, но T будет рассматриваться как Object, поэтому приведение в действие всегда будет успешным, даже если объект, который вы выполняете, на самом деле не является экземпляром T.

+0

Привет, Павел, не могли бы вы объяснить это немного больше? 'cast', похоже, делает именно это:' return (T) obj; ' –

+0

Вы можете, безусловно, написать это. Он просто выдает предупреждение компилятора. – meriton

+0

@meriton: хорошая точка, отредактированная. Я хотел сказать, что актеры все равно не будут делать то, что должно действительно делать. –

2

Это первый обычай. Для этого требуется, чтобы тип, который был введен, был известен во время компиляции. Он проверяет во время компиляции, что литой может быть, является правильным и проверяет (если тип для отливки не является общим), что литой является правильным во время выполнения.

Второй использует отражение api. Для этого требуется, чтобы класс, который был запущен, был известен во время выполнения. Во время компиляции он ничего не проверяет, но всегда проверяет правильность исполнения при выполнении.

Параметры типа известны только при компиляции, поэтому вы не можете использовать второй подход для параметра типа (выражение T.class не компилируется).

Динамически загруженные классы (например, с Class.forName (String)) известны только во время выполнения, поэтому первый подход не может быть использован.

Редактировать: Однако, как отмечает Павел, нет смысла бросать в динамически загруженный класс. Я согласен с тем, что единственная реальная полезность Class.cast(Object) заключается в том, чтобы использовать для параметра типа, для которого у вас есть объект класса.

Если тип отливки не содержит параметр типа, то первый подход лучше, так как дополнительная проверка времени компиляции может ловить ошибки, вы не теряете безопасность типа во время выполнения и получаете более короткий синтаксис для загрузки.

+2

Для динамически загружаемых классов, зачем вам вообще нужен бросок? Приведение, как правило, приводит к тому, что выражение имеет некоторый тип, но вы не знаете тип заранее в случае динамически загружаемых классов. В конце концов, если у вас есть динамически загруженный класс, вы не знаете, что 'T' находится в вызове класса .cast()', поэтому вы просто используете исходную версию, а затем возвращаемый тип будет быть 'Object' - не так много. Он будет проверять тип, но, безусловно, 'Class.isInstance()' - лучший способ сделать то же самое. В общем, мне кажется, что это предназначено только для дженериков. –

+0

Вы правы. Редактировали мой ответ соответственно. – meriton

0

Here вы можете найти пример использования, в котором используется Class#cast(). Это может дать новые идеи.

1

В первом случае у вас есть для жесткого кодирования класса литья.

(ClassToCast) objectToCast; 

Во второй литейном классе может быть параметр:

Class toCast = getClassToCast(); 

toCast.cast(objectToCast); 
Смежные вопросы