Рассмотрим следующий класс:
public class DataStructure {
// Create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
public void print(DataStructureIterator iter) {
while(iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println();
}
interface DataStructureIterator extends java.util.Iterator<Integer> { }
// Inner class implements the DataStructureIterator interface,
// which extends the Iterator<Integer> interface
private class EvenIterator implements DataStructureIterator {
// Start stepping through the array from the beginning
private int nextIndex = 0;
public boolean hasNext() {
// Check if the current element is the last in the array
return (nextIndex <= SIZE - 1);
}
public Integer next() {
// Record a value of an even index of the array
Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
// Get the next even element
nextIndex += 2;
return retValue;
}
}
public static void main(String s[]) {
// Fill the array with integer values and print out only
// values of even indices
DataStructure ds = new DataStructure();
ds.print(
new DataStructure.DataStructureIterator() {
private int nextIndex = 1;
public boolean hasNext() {
return (nextIndex <= ds.size() - 1);
}
public Integer next() {
//int retValue = arrayOfInts[nextIndex]; // this won't work:
// non-static variable arrayOfInts cannot be referenced from a static context
int retValue = ds.get(nextIndex);
nextIndex += 2;
return retValue;
}
}
);
}
}
Собрав это, я получаю:
error: non-static variable arrayOfInts cannot be referenced from a static context
Компилятор жалуется на доступ к переменной arrayOfInts из анонимного класса, находящегося в основном методе.
Мой вопрос: хорошо, я понимаю, что я не могу получить доступ к нестатической переменной из статического контекста - это полностью имеет смысл. Но в этом случае я фактически не получаю доступ к переменной из статического контекста. Скорее я передаю часть кода — анонимный класс — нестатическому методу. Нестатический метод определенно может получить доступ к нестатической переменной, так почему же это невозможно?
@user207421 user207421 Почему это должно помочь? Анонимный класс, созданный в статическом контексте, не является внутренним классом, не может иметь вмещающий экземпляр.
Итак, следующий вопрос: почему он вообще определяет итератор в основном методе? А если надо, то почему бы не продлить EvenIterator? Что *требует*` контекст ds. и предоставляет нестатический контекст, который ему нужен. В данный момент он получает доступ к вещам, которые находятся вне (нестатической) области видимости.
@ user207421 Да, я согласен, что дизайн кода довольно странный. Я бы предположил, что это всего лишь один из тех надуманных сценариев, демонстрирующих замешательство ОП.




Вы создаете анонимный класс из статического метода и пытаетесь передать нестатическое поле в реализацию, поэтому вы получаете ошибку компиляции. Принимая во внимание, что класс EvenIterator является внутренним по отношению к DataStructure, поэтому он подразумевает привязку к экземпляру класса DataStructure и может получить доступ к его нестатическим переменным.
Спецификация внутренних и вложенных классов
Как и в случае с методами и переменными экземпляра, внутренний класс связан с экземпляром окружающего его класса и имеет прямой доступ к методам и полям этого объекта.
Скорее я передаю кусок кода - анонимный класс - нестатическому методу
Java не учитывает, что вы делаете с создаваемым экземпляром, чтобы определить, можете ли вы получить доступ к нестатическому полю.
Насколько известно Java, вы можете присвоить экземпляр анонимного класса локальной переменной:
public static void main(String[] args) {
var foo = new DataStructure.DataStructureIterator() {
public boolean hasNext() {
...
}
public Integer next() {
int retValue = arrayOfInts[nextIndex]; // this won't work:
...
}
};
foo.next();
}
Что бы foo.next() сделал в этом случае? Нигде нет экземпляров DataStructure!
Тем не менее, в вашем коде есть экземпляр DataStructure — ds. Вы, вероятно, имели в виду доступ к arrayOfInts в этом случае, поэтому просто сделайте ds.arrayofInts вместо этого.
Обратите внимание, что использование arrayOfInts внутри EvenIterator допустимо, потому что EvenIterator является внутренним классом DataStructure. Обратите внимание, что DataStructureIterator, который также вложен в DataStructure, не является «внутренним интерфейсом». Нет такого понятия, как «внутренние интерфейсы». DataStructure.DataStructureIterator — это еще один обычный тип.
Чтобы создать экземпляр EvenIterator, вам сначала нужен экземпляр DataStructure. Этот экземпляр DataStructure называется объемлющим экземпляром EvenIterator.
Поскольку EvenIterator обращается к arrayOfInts окружающего его экземпляра, а не к тому экземпляру, к которому вы вызываете print, это может привести к неожиданным результатам:
DataStructure ds1 = new DataStructure();
DataStructure ds2 = new DataStructure();
EvenIterator iter = ds1.new EvenIterator(); // enclosing instance is ds1
ds2.print(iter); // prints the elements of ds1, not ds2!
Что ж, это НАСТОЛЬКО функция, которую я ненавижу, хорошо набранные игроки делают некоторые макияжи вокруг оригинальных авторов и крадут одобрения и голоса. Проверьте историю редактирования ответа
С другой стороны, @YoavKlein, почему ты принял этот ответ, а не мой? Вы друзья? Поддельный аккаунт @Sweeper? Или, может быть, мой ответ не так хорош, и не стоит даже положительного голосования, кроме как хотя бы принять?
new DataStructure.DataStructureIterator()должно бытьds.new DataStructure.DataStructureIterator()обязательно?