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

标签 java oop nested-class static-class

我想知道封闭类可以创建多少个静态成员类实例。我假设只有一个,但 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/

相关文章:

java - Eclipselink实体类自动扫描发现非实体

java - 使用记事本出现 FileNotFoundException

java - 如何在我的主类中创建一个 switch 语句,当选择该情况时将在我的程序中运行另一个主类?

c# - 通过 OOP 继承,我如何在 'child' 类中保持较低的参数量

java - 将嵌套类继承到子类

java - Android提取对象数组的属性数组

java - 在 Object[] 数组上实现 Java 迭代器和可迭代接口(interface)

rest - 面向资源不是真的面向对象吗?

c++ - 为嵌套类模板重载运算符<<

java - 对于通用外部类,为什么我需要将嵌套类声明为静态的?