Java 为什么可以’;这个静态的内部类不调用外部类上的非静态方法吗?

Java 为什么可以’;这个静态的内部类不调用外部类上的非静态方法吗?,java,class,static,member,Java,Class,Static,Member,我目前正在阅读Joshua Bloch的《高效Java》,我喜欢它!但布洛赫在第112页(第24项)写道: 静态成员类是最简单的嵌套类。这是最好的 被认为是一个普通类,碰巧在内部声明 另一个类,并且可以访问封闭类的所有成员, 甚至那些被宣布为私人的 这让我很困惑。我宁愿说: 静态成员类是最简单的嵌套类。这是最好的 被认为是一个普通类,碰巧在内部声明 另一个类,并且可以访问封闭类的所有静态成员, 甚至那些被宣布为私人的 以下是一个片段,说明了我对该引文的理解: public class Outer

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

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

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

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

以下是一个片段,说明了我对该引文的理解:

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方法是实例方法。看起来作者建议静态成员类可以访问封闭类的非静态字段。我确信我误解了他最后一句话中的某些内容,但我不知道是什么。任何帮助都将不胜感激


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

您展示它的方式需要继承。但方法和字段可以通过以下方式进行访问:

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 {

    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。这是访问外部实例的特殊语法。但只有在不明确的情况下才需要它,例如,如果外部类和内部类具有相同名称的方法

还要注意,非静态类仍然可以做静态类可以做的事情:

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

简而言之:
public
private
总是关于访问。Bloch的观点是,内部类具有其他类所没有的访问权限。但是,任何访问权限都不允许您在不告诉编译器您要调用哪个实例的情况下调用实例方法。

在我看来,文本是绝对正确的。静态成员类可以访问封闭类的私有成员(某种类型)。让我给你举个例子:

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

的确但让我如此困惑的是“可以访问封闭类的所有成员”。在我看来,它的意思是“所有静态和非静态成员”,因为他没有指定它。此处是否暗示“静态”?@RobinDosAnjos No.“有访问权限”表示“允许”。例如,在上面的第二个示例中,不允许调用,因为它试图从独立类调用
private
方法(错误:不可见)。要调用非静态方法,它仍然需要引用
OuterClass
的实例。“有权限”不是关于这个。非常感谢!我想我现在明白了!无论如何,这是我第一次在他的书中发现如此令人困惑的东西!解释一下为什么
this.printMessage
不是一个选项会有用吗?@JollyJoker不明白为什么你要解释,既然
this.printMessage
永远都是无效的,无论
InnerClass
是否是静态的。@CiaPan虽然我应该学习阅读错误消息,你应该学会阅读人们的信息,这些信息已经用稍微多一些的外交手段指出了你所说的。