Подтвердить что ты не робот

Порядок каста Java

Скажем, у меня есть следующая настройка

class A {
    B foo();
}

class C extends B {

}

// later
A a = new A();
C theFoo = (C)a.foo();

Мы знаем, что a.foo() возвращает тип B.

Когда я делаю (C)a.foo(), это

  • Кастинг a для ввода C, затем попытка вызвать foo() на нем?
  • Вызов foo() on a и выдача результата для ввода C?

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

Это относится к ObjectInputStream.readObject(), но я не вижу, как это изменит поведение.

4b9b3361

Ответ 1

(C)a.foo() эквивалентен (C)(a.foo()), то есть # 2 в вопросе.

Чтобы получить # 1, вам нужно написать ((C)a).foo().

Спецификация языка Java не определяет приоритет оператора в хорошем, легко читаемом сводке.

Приложение A Введение в программирование на Java от Sedgewick и Wayne имеет исчерпывающую таблицу приоритетов операторов.

Приложение B Язык программирования Java имеет таблицу приоритетов операторов, но она не такая полная, как Sedgewick's.

Тщательный контроль грамматики в Спецификации языка Java может определять относительные приоритеты выражений вызова приведения и метода:

Expression:
        Expression1 [AssignmentOperator Expression1]]

Expression1:
        Expression2 [Expression1Rest]

Expression1Rest:
        ?   Expression   :   Expression1

Expression2 :
        Expression3 [Expression2Rest]

Expression2Rest:
        {InfixOp Expression3}
        Expression3 instanceof Type

Expression3:
        PrefixOp Expression3
        (   Expression | Type   )   Expression3
        Primary {Selector} {PostfixOp}

Primary:
        ParExpression
        NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | this Arguments)
        this [Arguments]
        super SuperSuffix
        Literal
        new Creator
        Identifier { . Identifier }[ IdentifierSuffix]
        BasicType {[]} .class
        void.class

Соответствующие постановки выделены жирным шрифтом. Мы можем видеть, что выражение для литья соответствует произведению Expression3 : (Expression|Type) Expression3. Вызов метода соответствует произведению Expression3 : Primary {Selector} {PostfixOp} с помощью производства Primary: Identifier {. Identifier }[IdentifierSuffix]. Объединяя это вместе, мы видим, что выражение вызова метода будет рассматриваться как единица (a Expression3), на которую будет действовать актерский состав.

Хммм, диаграмма приоритета легче следовать...;)