gpt4 book ai didi

java - Bloch Effective Java - 支持静态类而不是非静态类 - 有多少个实例?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:11:03 24 4
gpt4 key购买 nike

我想知道封闭类可以创建多少个静态成员类实例。我假设只有一个,但 Bloch 的以下摘录对我来说没有意义。

引用 Joshua Bloch 的 Effective Java - Item 22*:优先使用静态成员类而不是非静态成员类。

A common use of private static member classes is to represent components of the object represented by their enclosing class. For example, consider a Map instance, which associates keys with values. Many Map implementations have an internal Entry object for each key-value pair in the map. While each entry is associated with a map, the methods on an entry (getKey, getValue and setValue) do not need access to the map. Therefore, it would be wasteful to use a nonstatic member class to represent entries: a private static member class is best. If you accidentally omit the static modifier in the entry declaration, the map will still work, but each entry will contain a superfluous reference to the map, which wastes space and time.

他说map为map中的每个键值对创建一个Entry对象,即静态成员类的多个实例。

所以我的假设是错误的!也就是说我对静态成员类的理解是错误的。每个人都知道静态成员变量的行为方式,例如经典的静态最终字符串——对象只有一个实例。

这是否意味着在实例化封闭对象时实际上并未实例化静态成员类?

那么在那种情况下,Map 使用静态成员类作为 Entry 有什么意义呢?为什么不直接使用 API 上的接口(interface)?然后所有其他 Collections 类都可以提供它自己的实现。

[*] 才发现是我手头PDF版书的第18条

最佳答案

这是对 static 关键字的常见误解。

当您将 static 与变量一起使用时,这意味着此类的所有对象都只有其中一个 或类似的东西。

static Object thereWillBeOnlyOne = new Object();

然而,在内部类的上下文中,它意味着完全不同的东西。 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> {

我的 TrieMap 类使用的 Map.Entry 类不需要引用创建它的对象,因此可以将其设为静态 保存不必要的引用。


静态内部类:

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;
}

StringWalker 对象中的CharacterIterator 指的是要迭代的字符串作为s,它在StringWalker< 中只存在一次 对象。因此,我可以创建一个 StringWalker 的许多迭代器,它们都遍历相同的字符串。


为什么会这样?

这种看似不合逻辑的双重性源于 Cstatic 关键字的使用。

C 中你可以(或者至少曾经能够)做:

void doSomething () {
static int x = 1;

if ( x < 3 ) {
} else {
}
x += 1;
}

并且每次您调用该函数时,x 都会保持上次离开时​​的状态 - 在这种情况下会递增。

其概念是,static 关键字指示变量被其封闭 block 范围内封闭,但被其父 block 语义上封闭。 IE。上面的代码大致相当于:

int x = 1;
void doSomething () {
if ( x < 3 ) {
} else {
}
x += 1;
}

但是 x 只允许在函数内部被引用。

将这个概念推进到 Java 中,现在事情变得更有意义了。 static 内部类的行为与它在类外部声明的完全一样,而非 static 内部类与其封闭实例的绑定(bind)更加紧密 - 实际上它可以引用该实例直接。

还有:

class Thing {
static Object thereWillBeOnlyOne = new Object();

行为很像

Object thereWillBeOnlyOne = new Object();
class Thing {

如果它是合法的。

本课到此结束。

关于java - Bloch Effective Java - 支持静态类而不是非静态类 - 有多少个实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24953370/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com