Просматривая некоторый код, я наткнулся на следующий код
trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));
и я хотел бы знать, имеет ли такой способ преобразования какие-либо преимущества перед
trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto);
Я спросил ответственного разработчика, и он сказал, что использовал его, потому что он был новым (что не кажется мне особенно веской причиной), но я заинтригован, когда я захочу использовать этот метод.




Оба эти утверждения идентичны. Выберите тот, который вы считаете более читаемым. По моему опыту, второй метод более распространен, и я предпочитаю его.
Я предпочитаю использовать метод приведения только тогда, когда работаю с отражением, и в этой ситуации он лучше читается. В остальное время я использую второй способ кастинга.
Основной случай для этого (IME) - это когда вам нужно безопасно использовать общий класс / метод. Из-за стирания типа вы не можете выполнить приведение к T, но если вам был предоставлен параметр Class<? extends T>, вы можете использовать его для приведения, и результат будет присваиваться переменной типа T.
Эти утверждения не идентичны. Метод приведения - это обычный вызов метода (инструкция invokevirtual JVM), а другой - это языковая конструкция (инструкция checkcast). В случае, показанном выше, вы должны использовать вторую форму: (TrTuDocPackTypeDto) packDto
Метод cast используется в рефлексивном программировании с помощью универсальных шаблонов, когда у вас есть экземпляр класса для некоторого типа переменной. Вы можете использовать это так:
public <T> Set<T> find(Class<T> clz, Filter criteria) {
List<?> raw = session.find(clz, criteria); /* A legacy, un-generic API. */
Set<T> safe = new HashSet<T>();
for (Object o : raw)
safe.add(clz.cast(o));
return safe;
}
Это дает вам безопасный способ избежать неправильной альтернативы простого приведения необработанного типа к универсальному типу:
/* DO NOT DO THIS! */
List raw = new ArrayList();
...
return (List<Widget>) raw;
Компилятор предупредит вас, Unchecked cast from List to List<Widget>, что означает, что в многоточии кто-то мог добавить Gadget в необработанный список, что в конечном итоге вызовет ClassCastException, когда вызывающая сторона перебирает возвращенный список (предполагаемых) экземпляров Widget.
При быстром просмотре Справочника по языку выяснилось, что class.cast() обходит предупреждение о «небезопасном преобразовании», которое обычно отображает компилятор. Как сказал Эриксон, используйте конструкцию языка до тех пор, пока у вас не получится. ;-)
Вы можете объяснить, что СЛЕДУЕТ делать во втором случае? Я только вчера столкнулся с этим предупреждением компилятора, но проигнорировал его, потому что я ленив. Вы предлагаете что-то вроде List <Widget> .cast (raw)?
@Outlaw - чтобы избежать второго случая, вам нужно использовать что-то вроде того, что я предоставил в методе поиска выше. То есть вам нужно перебрать List и проверить, действительно ли каждый элемент является Widget. Тогда было бы нормально проигнорировать предупреждение, которое вы получаете от "(List <Widget>) raw".
Я не могу найти пример, где возможен метод приведения, а синтаксис приведения - нет. Однако, глядя на код, кажется, что в случае, если приведение невозможно, метод приведения выдает исключение ClassCastException без прикрепленной информации о типе, тогда как синтаксис приведения даст вам некоторые подсказки (например, «не удалось преобразовать Snoopy в TyrannosorusRex. ") :
/**
* Casts an object to the class or interface represented
* by this <tt>Class</tt> object.
*
* @param obj the object to be cast
* @return the object after casting, or null if obj is null
*
* @throws ClassCastException if the object is not
* null and is not assignable to the type T.
*
* @since 1.5
*/
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException();
return (T) obj;
}
Class.cast () полезен, если вы еще не знаете, к какому классу приводите (например, отражение и т. д.). Как правило, сначала нужно проверить Class.isInstance (Object), чтобы убедиться, что вы не получите CCE.
С первой формой
trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));
ты можешь сделать это:
public void dynamicCast( Class clazz, Object o ) {
this.x = clazz.cast( o );
}
Со вторым нельзя. Класс приведения должен быть жестко запрограммирован.
Зачем вам в первую очередь использовать переменную для приведения? Это другой вопрос. :) Первое, что приходит в голову, это то, что вы не знаете (во время компиляции) класс, в который будет выполнено приведение.
см. также stackoverflow.com/questions/7900410/…