Java范围规则和内部类

所有疯狂的Java范围规则都让我头疼,而公共静态无效的废话并没有帮助。 到目前为止,我使用的所有编程语言都是词法作用域或者它的一些近似,没有任何访问修饰符,即内部东西捕获外部东西,并且只要内部东西存在就可以访问外部东西。

那么我如何理解Java中内部类的作用域规则呢? 他们是否可以访问在外部类中声明的变量,或者是否有一些奇怪的边缘情况我不得不担心因为所有公共静态私有东西浮动?

静态嵌套类1与外部类完全相同,只是它们可以访问外部类的所有成员,而不管访问限定符。 它们存在于外部类的任何实例之外,因此需要引用实例才能访问外部类的任何实例变量或非静态方法。

非静态嵌套类(称为内部类 )仅在外部类的实例的上下文中存在。 构造时,它们会自动生成第二个字段,您可以使用语法Outer.this从内部类中访问this字段。 内部类的每个实例都由外部类的单个实例包围。 同样,静态嵌套类的所有访问权限都适用于内部类。 但由于它们已经有外部类的实例,它们可以自动访问外部类的实例变量和方法。

有关内部类和访问说明符的一个很好的(非常详细的)讨论,您可以阅读内部类规范 。 除其他外,它描述了嵌套类如何访问其外部类的private成员。 更温和的阅读是嵌套类教程 。

偏离主题:假设你有这个类结构:

 public class O { public O() { ... } public class I { // an inner class public I() { ... } ... } ... } 

你已经创建了一个O的实例:

 O outer = new O(); 

现在假设您要创建OI实例。 你不能只使用new OI()因为I的新实例需要被特定的O实例包围。 为此,Java提供以下语法:

 OI inner = outer.new OI(); 

然后inner将其第二个字段设置为引用outer

请注意,此“限定new运算符”语法仅用于内部类; 如果I是一个static嵌套类,那将是不必要的(实际上是一个错误)。

1 您经常会遇到“静态内部阶级”这一短语(包括,令人尴尬的是,在此答案的早期版本中)。 这是不正确的术语。 在Java中,“内部类”特别是非static嵌套类。

你必须区别对待:

  • 静态内部类可以访问其声明之外的所有静态成员。
  • 实例内部类可以访问其声明之外的所有类成员,并且可以访问声明它们的函数中的最终字段。

请记住,非静态内部类还有一个隐藏变量和外部类的实例,以访问那里的成员。 当实例化内部类时,所有引用的final字段(因此它们必须是final)将被复制到其他隐藏成员变量的内部类中。

例:

 public void doStuff(final int a, int b) { final int c; // Can be referenced int d; // Cannot be referenced, not final executer.execute( new Runnable() { public void run() { System.out.println("a: "+a+" c: "+c); } } b++; // Not final, not referencable System.out.println(b); } 

我不知道它是否有帮助,但是从java教程 :

静态嵌套类

与类方法和变量一样,静态嵌套类与其外部类相关联。 和静态类方法一样,静态嵌套类不能直接引用其封闭类中定义的实例变量或方法 – 它只能通过对象引用来使用它们。 注意: 静态嵌套类与其外部类(和其他类)的实例成员交互,就像任何其他顶级类一样 。 实际上,静态嵌套类在行为上是一个顶级类,它已嵌套在另一个顶级类中以方便打包。

内部类 [非静态嵌套类?]

与实例方法和变量一样,内部类与其封闭类的实例相关联,并且可以直接访问该对象的方法和字段 。 此外,由于内部类与实例相关联,因此无法定义任何静态成员本身。

您应该检查嵌套类的java教程 。

Java中内部类的规则

  1. 在Java中,可以在另一个类中定义一个类,这样的类称为嵌套类或内部类。
  2. Inner类Instance Inner类,静态内部类和匿名内部类有3种类型
  3. 如果将Inner类声明为实例内部类,则它可以访问外部封闭类的所有成员,包括私有成员
  4. 如果Inner类声明为static,那么它只能访问外部类的静态成员(包括私有静态成员)。 但它无法访问实例成员
  5. 考虑在外部类和实例内部类中都定义了变量x,然后从内部类访问变量的一般forms是内部x的this.x和外部x的OuterClassname.this.x
  6. 您还可以在任何方法或任何其他块中定义内部类
  7. 从外部类外部实例化内部类的一般forms是Outer.Inner ob = new Outer.new Inner();
  8. 从外部类外部实例化内部类的一般forms是(如果内部类声明为static) Outer.Inner ob = new Outer.Inner();
  9. 可以使用任何访问修饰符关键字声明内部类
  10. 如果将Inner类声明为private,则不能从外部类外部实例化它。 同样在这种情况下,即使您有一个对象引用,即使私有内部类的成员被声明为public,也无法从外部类外部访问Inner类的成员。
  11. 如果Inner类被声明为实例内部类,那么它也可以通过通用语句Outer.super.variable;访问外部类的超类成员Outer.super.variable; Outer.super.method(params);

内部阶级规则

  1. 由内部类访问的外部类
  2. 外类不能访问内部类
  3. 内部类成员仅使用方法,而类中的成员仅访问已填充的信息

方法范围内部类: – 只能访问外部类的最终成员。