繁体   English   中英

为什么这个静态内部类不能在其外部类上调用非静态方法?

[英]Why can’t this static inner class call a non-static method on its outer class?

我目前正在阅读Joshua Bloch的Effective Java ,我喜欢它! 但在第112页(第24项)布洛赫写道:

静态成员类是最简单的嵌套类。 最好将其视为普通类,恰好在另一个类中声明,并且可以访问所有封闭类的成员,甚至是那些声明为private的成员。

这真让我困惑。 我宁愿说:

静态成员类是最简单的嵌套类。 它最好被认为是一个普通的类,碰巧在另一个类中声明,并且可以访问所有封闭类的静态成员,甚至是那些声明为private的成员。

这是一个片段,说明了我对引用的理解:

public class OuterClass {

    public void printMessage(String message) {
        System.out.println(message);
    }

    private static class InnerClass {

        public void sayHello() {
            printMessage("Hello world!"); //error: Cannot make a static reference to the non-static method printMessage(String)
        }

    }
}

您可以看到InnerClass的sayHello方法无法访问OuterClass的printMessage方法,因为它在静态内部类中声明,而printMessage方法是实例方法。 看起来作者似乎建议静态成员类可以访问封闭类的非静态字段。 我确信我在他的最后一句话中误解了一些内容,但我无法弄清楚是什么。 任何帮助将不胜感激!

编辑:我改变了两种方法的可见性,因为它与我的问题无关。 我对静态成员感兴趣,而不是私人成员。

仅仅因为InnerClassstatic ,但这并不意味着它不能获得对实例的引用OuterClass通过其他方式,最常见的参数,例如:

public class OuterClass {

    private void printMessage(String message) {
        System.out.println(message);
    }

    private static class InnerClass {

        private void sayHello(OuterClass outer) {
            outer.printMessage("Hello world!"); // allowed
        }

    }
}

如果InnerClass没有被嵌套OuterClass ,它不会有访问private方法。

public class OuterClass {

    private void printMessage(String message) {
        System.out.println(message);
    }

}

class InnerClass {

    private void sayHello(OuterClass outer) {
        outer.printMessage("Hello world!"); // ERROR: The method printMessage(String) from the type OuterClass is not visible
    }

}

请注意错误消息。 这并不是说你没有访问权限 它说这个方法无法调用 实例方法并不意味着没有实例来调用它们。 错误消息告诉您的是您没有该实例。

Bloch告诉你的是, 如果存在该实例,内部类中的代码可以在其上调用私有实例方法。

假设我们有以下课程:

public class OuterClass {
  public void publicInstanceMethod() {}
  public static void publicClassMethod() {}
  private void privateInstanceMethod() {}
  private static void privateClassMethod() {}
}

如果我们尝试从一些随机类调用这些私有方法,我们不能:

class SomeOtherClass {
  void doTheThing() {
    OuterClass.publicClassMethod();
    OuterClass.privateClassMethod(); // Error: privateClassMethod() has private access in OuterClass
  }
  void doTheThingWithTheThing(OuterClass oc) {
    oc.publicInstanceMethod();
    oc.privateInstanceMethod();      // Error: privateInstanceMethod() has private access in OuterClass
  }
}

请注意,这些错误消息表示私有访问

如果我们向OuterClass本身添加一个方法,我们可以调用这些方法:

public class OuterClass {
  // ...declarations etc.
  private void doAThing() {
    publicInstanceMethod();  // OK; same as this.publicInstanceMethod();
    privateInstanceMethod(); // OK; same as this.privateInstanceMethod();
    publicClassMethod();
    privateClassMethod();
  }
}

或者如果我们添加一个静态内部类:

public class OuterClass {
  // ...declarations etc.
  private static class StaticInnerClass {
    private void doTheThingWithTheThing(OuterClass oc) {
      publicClassMethod();  // OK
      privateClassMethod(); // OK, because we're "inside"
      oc.publicInstanceMethod();  // OK, because we have an instance
      oc.privateInstanceMethod(); // OK, because we have an instance
      publicInstanceMethod();  // no instance -> Error: non-static method publicInstanceMethod() cannot be referenced from a static context
      privateInstanceMethod(); // no instance -> Error: java: non-static method privateInstanceMethod() cannot be referenced from a static context
    }
  }
}

如果我们添加一个非静态内部类,看起来我们可以做魔术:

public class OuterClass {
  // ...declarations etc.
  private class NonStaticInnerClass {
    private void doTheThing() {
      publicClassMethod();     // OK
      privateClassMethod();    // OK
      publicInstanceMethod();  // OK
      privateInstanceMethod(); // OK
    }
  }
}

然而,这里有一些技巧: 非静态内部类总是与外部类的实例相关联,而您真正关注的是:

  private class NonStaticInnerClass {
    private void doTheThing() {
      publicClassMethod();     // OK
      privateClassMethod();    // OK
      OuterClass.this.publicInstanceMethod();  // still OK
      OuterClass.this.privateInstanceMethod(); // still OK
    }
  }

这里, OuterClass.this是访问该外部实例的特殊语法。 但是如果它不明确,你只需要它,例如,如果外部类和内部类具有相同名称的方法。

另请注意,非静态类仍然可以执行静态类可以执行的操作:

  private class NonStaticInnerClass {
    private void doTheThingWithTheThing(OuterClass oc) {
      // 'oc' does *not* have to be the same instance as 'OuterClass.this'
      oc.publicInstanceMethod();
      oc.privateInstanceMethod();
    }
  }

简而言之: publicprivate总是关于访问 Bloch的观点是内部类具有其他类不具备的访问权限。 但是没有任何访问权限允许您调用实例方法而不告诉编译器您要调用它的实例。

你展示它的方式需要继承。 但方法和字段可以通过这种方式访问​​:

public class OuterClass {

  private void printMessage(String message) {
    System.out.println(message);
  }

  private static class InnerClass {

    private void sayHello() {
        OuterClass outer = new OuterClass();
        outer.printMessage("Hello world!"); 
    }

  }
}

但是,静态内部类无法访问printMessage函数,这与内部类无关,但它是静态的,不能调用非静态方法。 我认为你提出的“静态”一词的使用隐含在第一句中。 他指出或者选择强调的只是内部类仍然可以访问其父类的私有方法。 他可能只是在同一个句子中进行静态/非静态区分是不必要的或混乱的。

我看到它的方式,文本是绝对正确的。 静态成员类可以访问封闭类的私有成员(排序)。 让我举个例子:

public class OuterClass {
    String _name;
    int _age;
    public OuterClass(String name) {
        _name = name;
    }
    public static OuterClass CreateOuterClass(String name, int age) {
        OuterClass instance = new OuterClass(name);
        instance._age = age; // Notice that the private field "_age" of the enclosing class is visible/accessible inside this static method (as it would also be inside of a static member class).
        return instance;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM