Consider the following class:
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;
}
}
);
}
}
Compiling this, I get:
error: non-static variable arrayOfInts cannot be referenced from a static context
The compiler complains about the access to the arrayOfInts
variable from the anonymous class that's in the main method.
My question is: Ok I understand that I can't access a non-static variable from a static context - it completely makes sense. But in this case, I'm not actually accessing the variable from the static context. Rather, I'm passing a piece of code - an anonymous class - to a non-static method. The non-static method can definitely access a non-static variable, so why isn't it possible?
Rather, I'm passing a piece of code - an anonymous class - to a non-static method
Java doesn't consider what you are doing with the instance that you are creating, to determine whether you can access an non-static field.
For all Java knows, you could be assigning the instance of the anonymous class to a local variable:
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();
}
What would foo.next()
do in this case? There is no instances of DataStructure
anywhere!
That said, there is an instance of DataStructure
in your code - ds
. You probably meant to access the arrayOfInts
in that instance, so just do ds.arrayofInts
instead.
Note that the use of arrayOfInts
inside EvenIterator
is valid because EvenIterator
is a inner class of DataStructure
. Note that DataStructureIterator
, which is also nested in DataStructure
, is not an "inner interface". There is no such thing as "inner interfaces". DataStructure.DataStructureIterator
is just another regular type.
To create an instance of EvenIterator
, you need an instance of DataStructure
first. This instance of DataStructure
is called the enclosing instance of EvenIterator
.
Because EvenIterator
is accessing the arrayOfInts
of its enclosing instance, and not whatever instance you are calling print
on, this can lead to some unexpected results:
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!