这是对 static
关键字的一种常见误解。
当你在变量中使用 static
,意味着所有这个类的对象都只有一个该变量或者类似的意思。
static Object thereWillBeOnlyOne = new Object()
然而,在内部类的上下文中,它意味着完全不同的事情。
一个静态内部类与封闭类的对象没有任何关联,而非静态内部类则有。
一个静态内部类:
public class TrieMap<K extends CharSequence, V> extends AbstractMap<K, V> implements Map<K, V> {
private static class Entry<K extends CharSequence, V> implements Map.Entry<K, V> {
我使用的TrieMap
类中使用的Map.Entry
类不需要引用创建它的对象,因此可以将其设置为static
以节省不必要的引用。
非静态内部类:
public final class StringWalker implements Iterable<Character> {
private final String s;
private final int start;
private final int step;
private final int stop;
private final class CharacterIterator implements Iterator<Character> {
private int i;
private Character next = null;
CharacterIterator() {
i = start;
}
public boolean hasNext() {
if (next == null) {
if (step > 0 ? i < stop : i > stop) {
next = s.charAt(i);
i += step;
}
}
return next != null;
}
StringWalker
对象内部的
CharacterIterator
称为
s
,它仅在
StringWalker
对象中存在一次,用于迭代的字符串。因此,我可以创建许多
StringWalker
的迭代器,它们都遍历同一个字符串。
为什么会出现这种奇怪的现象?
这种看似不合逻辑的二元性来源于在C
中使用static
关键字。
在C
中,您可以(或至少曾经可以)执行以下操作:
void doSomething () {
static int x = 1;
if ( x < 3 ) {
} else {
}
x += 1;
}
每次调用函数时,
x
的值将与上一次相同-在这种情况下递增。
这个概念是,
static
关键字表示变量在其封闭块中具有作用域,但在其父块中具有语义封闭。也就是说,上述代码大致等同于:
int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}
但在函数内部才允许引用x
。
把这个概念转移到Java
中,事情现在变得更加清晰了。一个static
内部类的行为就像它是在类外部声明一样,而非static
内部类与其封闭实例更紧密地连接-实际上可以直接引用该实例。
另外:
class Thing {
static Object thereWillBeOnlyOne = new Object()
表现得很像
Object thereWillBeOnlyOne = new Object()
class Thing {
如果它是合法的话。
课程到此结束。