Когда мне следует использовать приведение метода Java 5 класса?

Просматривая некоторый код, я наткнулся на следующий код

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));

и я хотел бы знать, имеет ли такой способ преобразования какие-либо преимущества перед

trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto);

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

см. также stackoverflow.com/questions/7900410/…

irreputable 26.10.2011 15:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
13
1
8 168
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Оба эти утверждения идентичны. Выберите тот, который вы считаете более читаемым. По моему опыту, второй метод более распространен, и я предпочитаю его.

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

Основной случай для этого (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() обходит предупреждение о «небезопасном преобразовании», которое обычно отображает компилятор. Как сказал Эриксон, используйте конструкцию языка до тех пор, пока у вас не получится. ;-)

Ken Gentle 28.10.2008 19:17

Вы можете объяснить, что СЛЕДУЕТ делать во втором случае? Я только вчера столкнулся с этим предупреждением компилятора, но проигнорировал его, потому что я ленив. Вы предлагаете что-то вроде List <Widget> .cast (raw)?

Outlaw Programmer 13.03.2009 20:02

@Outlaw - чтобы избежать второго случая, вам нужно использовать что-то вроде того, что я предоставил в методе поиска выше. То есть вам нужно перебрать List и проверить, действительно ли каждый элемент является Widget. Тогда было бы нормально проигнорировать предупреждение, которое вы получаете от "(List <Widget>) raw".

erickson 13.03.2009 20:14

Я не могу найти пример, где возможен метод приведения, а синтаксис приведения - нет. Однако, глядя на код, кажется, что в случае, если приведение невозможно, метод приведения выдает исключение 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.

Michael Myers 13.03.2009 20:22

С первой формой

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));

ты можешь сделать это:

public void dynamicCast( Class clazz, Object o ) { 
     this.x = clazz.cast( o );
}

Со вторым нельзя. Класс приведения должен быть жестко запрограммирован.

Зачем вам в первую очередь использовать переменную для приведения? Это другой вопрос. :) Первое, что приходит в голову, это то, что вы не знаете (во время компиляции) класс, в который будет выполнено приведение.

Другие вопросы по теме