Твоя путаница не в разыменовании, я не думаю.Я думаю, что ваше замешательство связано с закрытием .Когда вы создаете экземпляр анонимного класса, как вы сделали, вы делаете замыкание, которое выполняет магический вызов стека, чтобы получить текущее состояние локальных переменных.Давайте сначала посмотрим на ваш рабочий пример.(Я удалил некоторые биты, которые не нужны для этого объяснения)
public class MyObject {
public void runThis() {
MyOtherObject myOtherObject = new MyOtherObject();
MyCustomObjectTracker customObjectTracker = new MyCustomObjectTracker() {
@Override
public void closingMyWindows() {
myOtherObject.doClose();
}
};
}
}
Когда вы делаете new MyCustomObjectTracker() { ... }
, компилятор Java видит, что вы используете переменную myOtherObject
, поэтому он неявно закрывается вокруг этогопеременная, вспоминая это на потом.Обратите внимание, что здесь важно то, что каждый раз, когда вы вызываете runThis
, вы создаете новую локальную переменную.Может иметь то же имя, что и старое, но вы создали новую локальную переменную.Таким образом, каждый customObjectTracker
получает доступ к другой локальной переменной.Следовательно, все работает.Теперь давайте посмотрим на другой пример.
public class MyObject {
MyOtherObject myOtherObject;
public void runThis() {
myOtherObject = new MyOtherObject();
MyCustomObjectTracker customObjectTracker = new MyCustomObjectTracker() {
@Override
public void closingMyWindows() {
myOtherObject.doClose();
}
};
}
}
Здесь код проходит то же самое обоснование.Нам нужно закрыть то, что называется myOtherObject
.Но myOtherObject
не является локальной переменной;это переменная экземпляра.Так что на самом деле нам нужно закрыть объект, которому он принадлежит, что составляет this
.Обратите внимание, что есть только один this
.Вы можете позвонить runThis
несколько раз;Вы вызываете это только на одном объекте.Поэтому в этом случае вы меняете одну переменную несколько раз, а затем создаете несколько новых классов, которые все указывают на эту одну переменную.
Анонимные классы относительно легко разложить на «реальные» классы вручную.Поэтому, если замыкания сбивают вас с толку, попробуйте преобразовать каждый из ваших фрагментов кода в форму, в которой не используются анонимные классы (поэтому вместо new MyCustomObjectTracker() { ... }
создайте новый файл с class MySpecialCustomObjectTracker extends MyCustomObjectTracker
).Поступая таким образом, вы будете думать о том, какое состояние должно быть передано вашему новому объекту, что и делает компилятор автоматически при создании экземпляра анонимного класса.