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

Как работает оператор трансляции Java?

Я пытаюсь отладить проблему с использованием ClassCastException в Java. В интересах решения проблемы мне нужно знать, что происходит, когда я отбрасываю объект из определенного типа. Может ли кто-нибудь объяснить мне, как работает оператор трансляции Java на уровне Java и уровне JVM?

4b9b3361

Ответ 1

Достаточно ли JLS?

Преобразование кастинга применяется к операнду оператора трансляции (§15.16): тип выражения операнда должен быть преобразован в тип, явно названный оператором литья. Контексты каста позволяют использовать:

  • преобразование идентичности (§5.1.1)
  • расширение примитивного преобразования (§5.1.2)
  • сужение примитивного преобразования (§5.1.3)
  • расширение ссылочного преобразования (п. 5.1.5), необязательно сопровождаемое непроверенным преобразованием (§5.1.9)
  • сужение ссылочного преобразования (§5.1.6), необязательно сопровождаемое непроверенным преобразованием
  • преобразование бокса (§5.1.7)
  • преобразование распаковки (§5.1.8).

Собственно, возможно эта часть более актуальна:

Подробные правила законности компиляции времени преобразования кастинга значения ссылочного типа времени компиляции S для ссылочного типа времени компиляции T следующие::

  • Если S - тип класса:
    • Если Tтип класса, то либо | S | <: | T |, или | T | & Л;: | <Я > S |; в противном случае время компиляции возникает ошибка. Кроме того, если существует супертип X of T, а супертип Y S, что обе X и Y доказуемо различны параметризованные типы (п. 4.5), и что стирания X и Y совпадают, время компиляции возникает ошибка.
    • Если T - тип интерфейса:
      • Если S не является finalкласса (§8.1.1), то, если существует супертип X of T, а супертип Y of S, так что оба X и Y доказуемо различные параметризованные типы, и что стирания X и Yсовпадают, ошибка времени компиляции имеет место. В противном случае, литье всегда во время компиляции (потому что даже если S не реализует T, подкласс S может).
      • Если S является final (§8.1.1), то S должен реализовать T, или возникает ошибка времени компиляции.

    • Если Tявляется переменной типа, то это алгоритм применяется рекурсивно, используя верхнюю оценку T в место T.
    • Если Tтип массива, то S должен быть класс Object, или ошибка компиляции.
  • Если Sтип интерфейса:
    • Если Tтип массива, то T должен реализовать S или время компиляции возникает ошибка.
    • Если T - тип, который не является final (§8.1.1), то, если существует супертип X of T, а супертип Y of S, так что оба X и Y доказуемо различные параметризованные типы, и что стирания X и Yсовпадают, ошибка времени компиляции имеет место. В противном случае, литье всегда во время компиляции (потому что даже если T не реализует S, подкласс T может).
    • Если Tтип final, затем:
      • Если S не является параметризованным тип или необработанный тип, тогда T должен реализовать S, а литой статически известны как правильные, или ошибка компиляции.
      • В противном случае, S является либо параметризованным тип, который является вызовом некоторых объявление типового типа G или необработанный тип, соответствующий общему type G. То есть должен существовать супертип X of T, что X является вызов G, или ошибка компиляции. Более того, если S и Xявляются явно различимыми параметризованными типы, то ошибка времени компиляции имеет место.
  • Если Sпеременная типа, то этот алгоритм применяется рекурсивно, используя верхняя грань S вместо <Я > S.
  • Если S - тип массива SC [], т.е. массив компонентов type SC:
    • Если T является class type, то если T не является Object, то a ошибка времени компиляции (потому что Object - единственный класс тип, которому могут быть назначены массивы).
    • Если Tявляется типом интерфейса, тогда ошибка компиляции <Я > Tэто тип java.io.Serializable или тип Cloneable, только интерфейсы, реализованные с помощью массивов.
    • Если Tявляется переменной типа, тогда:
      • Если верхняя граница T является Object или тип java.io.Serializable или тип Cloneable, или тип S может юридически поддаваться рекурсивно применяя эти правила, тогда актерский состав юридический (хотя и неконтролируемый).
      • Если верхний граница T - это тип массива TC [], то ошибка времени компиляции происходит, если тип SC [] не может быть отброшенным на TC [] рекурсивным применение этих времени компиляции правила литья.
      • В противном случае, ошибка компиляции.
    • Если Tтип массива TC [], т.е. массив компонентов типа TC, то возникает ошибка времени компиляции если не выполнено одно из следующих утверждений:
    • TC и SC - это такой же примитивный тип.
    • TC и SC являются ссылочными типами и типами SC может быть отличен до TCрекурсивное применение этих правила компиляции для кастинга.

Совершенно ясно, не так ли?: D

Другими словами, это лучшее, что я могу сделать, не зная подробностей о вашей проблеме.

Ответ 2

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

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

Подобные проблемы нередко встречаются в средах приложений в стиле сервера приложений, где код приложения и код подструктуры умышленно изолированы - например, если системные классы случайно включены в JAR-приложения, вы можете иметь две копии "того же" класса в JVM и жизнь запутывается

Ответ 4

Кастинг утверждает, что тип среды выполнения совместим с данным статическим типом и, таким образом, позволяет вам вызывать методы этого типа на объекте.

Здесь obj - объект Integer, но доступен только с ссылкой на Object:

Object obj = new Integer(1);

Кастинг позволяет снова рассматривать его как целое (или некоторый суперкласс из Integer):

System.out.println(((Integer) obj).intValue());

ClassCastException происходит, когда заданный статический тип не соответствует типу времени выполнения объекта:

System.out.println(((Float) obj).intValue()); // runtime error

Вы можете найти тип выполнения любого объекта с помощью getClass() и различных методов класса:

System.out.println(obj.getClass()); // prints "class java.lang.Integer"