Java范围规则和内部类

时间:2011-01-31 05:54:22

标签: java inner-classes scoping

所有疯狂的Java范围规则都让我头疼, public static void 废话无济于事。到目前为止,我使用的所有编程语言都是词法范围或者没有任何访问修饰符的一些近似,即内部东西捕获外部东西,并且只要内部东西存在就可以访问外部东西。

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

6 个答案:

答案 0 :(得分:17)

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

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

有关内部类和访问说明符的讨论(非常详细),您可以阅读Inner Class Specification。除其他外,它描述了嵌套类如何访问其外部类的private成员。温和的阅读是Nested Classes tutorial

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

public class O {
    public O() { ... }

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

并且您已创建O的实例:

O outer = new O();

现在假设您要创建O.I的实例。您不能只使用new O.I(),因为I的新实例需要由O的特定实例括起来。为此,Java提供以下语法:

O.I inner = outer.new O.I();

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

请注意,此“限定new运算符”语法仅用于内部类;如果Istatic嵌套类,则不必(实际上是错误)。

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

答案 1 :(得分:3)

你必须区分:

  • 静态内部类可以访问声明之外的所有静态成员。
  • 实例内部类可以访问其声明之外的所有类成员,并且可以访问声明它们的函数中的 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);
}

答案 2 :(得分:3)

我不知道它是否有帮助,但来自java tutorials

  

静态嵌套类

     

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

     

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

     

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

您应该查看the java tutorial on nested classes

答案 3 :(得分:1)

Java中内部类的规则

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

答案 4 :(得分:0)

内部类规则

  1. 内部类访问的外部课程
  2. 外部类
  3. 无法访问内部类
  4. 内部类成员仅使用方法,而类中的成员只访问已填充的信息

答案 5 :(得分:-1)

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