что означает ключевое слово "this" в блоке инициализатора? [дубликат]
этот вопрос уже есть ответ здесь:
- в Java, в чем разница между этим.метод () и метод ()? 9 ответов
- что значит "это"? [дубликат] 6 ответов
вот мой код:
class StaticBlock {
{
println("initializer block : " + message);
}
public StaticBlock(String message) {
this.message = message;
}
private String message;
}
теперь проблема в том, что в блоке инициализатора
{
println("initializer block : " + message);
}
если я добавить this
ключевое слово перед message
, он работает, но есть ошибка при отсутствии this
ключевое слово.
и компилятор говорит:
StaticBlockDemo.java:34: illegal forward reference
println("initializer block : " + message);
^
1 error
почему они не одинаковые?
4 ответов
Я не знаю причины, но это может помочь, чтобы прочитать соответствующие разделы спецификации языка Java.
8.6. Инициализаторы Экземпляра
инициализаторы экземпляра могут ссылаться на текущий объект с помощью ключевого слова
this
(§15.8.3), чтобы использовать ключевое словоsuper
(§15.11.2, §15.12), и использовать любые переменные типа в области.использование переменных экземпляра, объявления появляются дословно После использования иногда ограничено, Даже если эти переменные находятся в области. Точные правила, регулирующие прямую ссылку на переменные экземпляра, см. в §8.3.2.3.
8.3.2.3. Ограничения на использование полей при инициализации
объявление члена должно отображаться текстуально, прежде чем оно будет использоваться, только если член является экземпляром (соответственно
static
) поле класса или интерфейсаC
и выполняются все следующие условия:
использование происходит в экземпляре (соответственно
static
) инициализатора переменнойC
или в экземпляре (соответственно статическом) инициализатораC
.использование не находится в левой части назначения.
использование через простое имя.
C
- это внутренний класс или интерфейс, заключающий использование.
вот пример из этого раздела спецификации, обрезанный, чтобы проиллюстрировать конкретный момент, о котором вы спрашиваете:
class UseBeforeDeclaration {
{
j = 200;
// ok - assignment
j = j + 1;
// error - right hand side reads before declaration
int k = j = j + 1;
// error - illegal forward reference to j
int n = j = 300;
// ok - j at left hand side of assignment
int h = j++;
// error - read before declaration
int l = this.j * 3;
// ok - not accessed via simple name
}
int j;
}
Я также должен отметить, что даже компиляционная версия вашего кода не будет делать то, что вы хотите. Если вы запустите его:
new StaticBlock("abc");
он будет печатать
initializer block : null
это потому, что инициализаторы выполняются до (большинство) тело конструктора. Вот основные моменты из спецификации:
12.5. Создание новых экземпляров класса
[...] указанный конструктор обрабатывается для инициализации нового объекта с помощью следующей процедуры:
[...]
4. Выполните инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса [...]
5. Выполните остальную часть тела этого конструктора. [...]
если я добавляю " это "ключевое слово перед "сообщением", оно работает, но ошибка при отсутствии "этого" ключевого слова. почему они не одинаковые?
this
ключевое слово указывает на текущий экземпляр класса.
public StaticBlock(String message) {
this.message = message;
}
здесь, Если вы не используете this
тогда ему будет присвоено значение message
локальная переменная, потому что область действия локальной переменной больше, чем экземпляр в блоке.
при использовании this
затем он присвоит значение переменной текущая переменная объекта.
одним из преимуществ наличия классов в Java является то, что вы можете моделировать объекты как класс, и вы можете создавать несколько экземпляров объекта (в большинстве случаев).
чтобы ссылаться на информацию, специфичную для одного класса объектов, мы можем использовать this
внутри кода объекта (класса). Он сообщает программе, что вы хотите использовать current
переменные и значения объектов. Используя this.message = message
, вы назначаете значение сообщения, которое было передано в функция и сохранение ее в переменной сообщения объекта.
в этом есть аспекты области, где message
имеет локальную область, и this.message
объем за весь объект. Вот почему, когда вы пытались вызвать сообщение в коде печати:println("initializer block : " + message);
, сообщение локальной переменной не существовало в рамках этой функции.
если существует столкновение между именем локальной переменной и именем члена экземпляра, то this
ключевое слово компилятор скажет использовать переменную объекта.