Ответ 1
Созданное компилятором поле, которое связывает локальный внутренний класс с локальной переменной блока или параметром ссылочного типа.
См. Также The JavaTM Virtual Machine Specification (§4.7.6)
или Синтетический класс в Java.
Я рассматриваю некоторый дизассемблированный код, полученный из байт-кода Java. Я вижу следующее выражение:
.method static synthetic access$0()Lcom/package/Sample;
Я не могу понять, что означают synthetic
или access$0
. Может кто-то, пожалуйста, помогите мне понять эту часть?
Созданное компилятором поле, которое связывает локальный внутренний класс с локальной переменной блока или параметром ссылочного типа.
См. Также The JavaTM Virtual Machine Specification (§4.7.6)
или Синтетический класс в Java.
В языке java внутренние классы могут получить доступ к закрытым членам своего закрывающего класса. Однако, в байт-коде Java, понятие внутренних классов не существует, а частные члены недоступны. Чтобы обойти это, компилятор создает синтетические методы доступа во внешнем классе. Я считаю, что это то, что вы здесь видите. access$0
- это просто имя метода. Я не уверен, что, если что-то делает synthetic
. Он может просто скрыть метод от других компиляторов для обеспечения инкапсуляции.
assert
выражение JDK 1.8 тематическое исследование
Оператор assert
является примером конструкции, которая генерирует static synthetic
поле в Oracle JDK 1.8.0_45:
public class Assert {
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
в основном компилируется в:
public class Assert {
// This field is synthetic.
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
Это можно проверить с помощью:
javac Assert.java
javap -c -constants -private -verbose Assert.class
который содержит:
static final boolean $assertionsDisabled;
descriptor: Z
flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
Синтетическое поле генерируется так, что Java нужно вызывать Assert.class.desiredAssertionStatus()
только один раз во время загрузки, а затем кэшировать результат там.
Смотрите также: fooobar.com/info/16319/... для более подробного объяснения.
Обратите внимание, что это синтетическое поле может генерировать конфликты имен с другими полями, которые мы можем определить. Например, в Oracle JDK 1.8.0_45 не удается скомпилировать следующее:
public class Assert {
static final boolean $assertionsDisabled = false;
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
Единственное, что "мешает", это соглашение о присвоении имен, не использующее доллары в ваших идентификаторах. Смотрите также: Когда я должен использовать символ доллара ($) в имени переменной?
Бонус:
static final int $assertionsDisabled = 0;
будет работать, потому что, в отличие от Java, байт-код допускает несколько полей с одним и тем же именем, но разными типами: переменные, имеющие одно и то же имя, но различного типа