Ada*_*dam 10 java oop nested-class static-class
我想知道封闭类可以创建多少个静态成员类的实例.我只假设一个,但是Bloch的以下摘录对我来说没有意义.
引用Joshua Bloch的有效Java - 项目22*:支持非静态的静态成员类.
私有静态成员类的常见用法是表示由其封闭类表示的对象的组件.例如,考虑一个Map键,它将键与值相关联.许多Map实现都为地图中的每个键值对都有一个内部Entry对象.虽然每个条目都与一个映射关联,但条目上的方法(getKey,getValue和setValue)不需要访问映射.因此,使用非静态成员类来表示条目是浪费的:私有静态成员类是最好的.如果您不小心在条目声明中省略了静态修饰符,则地图仍然有效,但每个条目都将包含对地图的多余引用,这会浪费空间和时间.
他声明地图为地图中的每个键值对创建了一个Entry对象,即静态成员类的多个实例.
所以我的假设是错误的!这意味着我对静态成员类的理解是错误的.每个人都知道静态成员变量的行为方式,例如经典的静态最终字符串 - 只有一个对象的实例.
这是否意味着当实例化封闭对象时,实际上没有实例化静态成员类?
那么在这种情况下,使用静态成员类进行Entry的Map有什么意义呢?为什么不在API上使用接口?然后,每个其他Collections类都可以提供它自己的实现.
[*]刚才意识到它是我所拥有的PDF版本的第18项
这是对static关键字的常见误解.
当你使用static变量时,意味着这个类的所有对象或类似的东西中只有一个.
static Object thereWillBeOnlyOne = new Object();
Run Code Online (Sandbox Code Playgroud)
然而,在内部类的上下文中,它意味着完全不同的东西.甲static内部类具有与封闭类而非静态内部类做的目的没有连接.
一个static内部类:
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> {
Run Code Online (Sandbox Code Playgroud)
Map.Entry我的类使用的TrieMap类不需要引用创建它的对象,因此可以static保存不必要的引用.
非static内部阶级:
public final class StringWalker implements Iterable<Character> {
// The iteree
private final String s;
// Where to get the first character from.
private final int start;
// What to add to i (usually +/- 1).
private final int step;
// What should i be when we stop.
private final int stop;
// The Character iterator.
private final class CharacterIterator implements Iterator<Character> {
// Where I am.
private int i;
// The next character.
private Character next = null;
CharacterIterator() {
// Start at the start.
i = start;
}
public boolean hasNext() {
if (next == null) {
if (step > 0 ? i < stop : i > stop) {
next = s.charAt(i);
i += step;
}
}
return next != null;
}
Run Code Online (Sandbox Code Playgroud)
的CharacterIterator一个内部StringWalker对象指的是字符串进行迭代为s仅在存在一次StringWalker对象.因此,我可以创建一个a的迭代器,StringWalker它们都是相同的字符串.
这种看似不合逻辑的二元性来自于使用static关键字C.
在C你可以(或至少曾经能够)做:
void doSomething () {
static int x = 1;
if ( x < 3 ) {
} else {
}
x += 1;
}
Run Code Online (Sandbox Code Playgroud)
并且每次调用该函数时,x都会像上次离开时一样 - 在这种情况下递增.
概念是static关键字表明变量被其封闭块大量包围,但在语义上由其父块包围.即上面的代码大致相当于:
int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}
Run Code Online (Sandbox Code Playgroud)
但x只允许在函数内引用.
把这个概念推进到Java现在,事情变得更有意义.一个static内部类的行为完全就像是声明的类外,同时非static内债券更紧密其外围实例-事实上,它可以直接引用的实例.
也:
class Thing {
static Object thereWillBeOnlyOne = new Object();
Run Code Online (Sandbox Code Playgroud)
表现得很像
Object thereWillBeOnlyOne = new Object();
class Thing {
Run Code Online (Sandbox Code Playgroud)
如果它是合法的.
这里吸取了教训.
我认为 Java 团队搞砸了这个命名。静态内部类(严格来说,它们的正确名称是“静态嵌套类”)与普通类没有任何区别,只是它有一个奇特的名称(Something.MyClass而不是MyClass)并且可以设为私有(即不能从其他类实例化)。
就 而言Map,选择它只是因为名称Map.Entry清楚地表明与Entry相关Map。正如您所建议的,为此使用普通类是完全合理的。唯一的区别是你不用写Map.Entry。
我认为他们应该做的是对静态嵌套类使用“非静态”内部类(即仅class在封闭类中)的语法,而不是发明一个新关键字来创建“非静态”内部类,因为这些类的行为与普通类不同。也许类似的东西attached class。据我所知,选择关键字static是为了避免有太多保留关键字,但我认为这只会加剧混乱。