Java 作用域规则和内部类

发布于 2024-10-15 04:58:44 字数 261 浏览 5 评论 0原文

所有疯狂的 Java 作用域规则都让我头晕目眩,而 public static void 的废话对事情没有帮助。到目前为止,我使用的所有编程语言都使用了词法作用域或它的某种近似值,而没有任何访问修饰符,即内部内容捕获外部内容,并且只要内部内容存在就可以访问外部内容。

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

All the crazy Java scoping rules are making my head spin and the public static void nonsense isn't helping matters. So far all the programming languages I have used either lexical scoping or some approximation of it without any access modifiers, i.e. inner stuff captures outer stuff and has access to the outer stuff as long as the inner stuff exists.

So how do I make sense of the scoping rules for inner classes in Java? Do they get access to variables declared in the outer class or is there some weird edge cases I have to worry about because of all the public static private stuff floating around?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

擦肩而过的背影 2024-10-22 04:58:44

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

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

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

题外话:假设您有这样的类结构:

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

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

并且您已经创建了 O 的实例:

O outer = new O();

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

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

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

请注意,这种“限定 new 运算符”语法仅用于内部类;如果 I 是一个 static 嵌套类,则没有必要(事实上,这是一个错误)。

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

Static nested classes1 are exactly like external classes except that they have access to all members of the outer class, regardless of access qualifier. They exist apart from any instance of the outer class, so need a reference to an instance in order to access any instance variables or non-static methods of the outer class.

Non-static nested classes (called inner classes) come into existence only in the context of an instance of the outer class. When constructed, they have a second this field automatically generated, which you can access from within the inner class using the syntax Outer.this. Each instance of the inner class is enclosed by a single instance of the outer class. Again, all the access privileges of static nested classes apply to inner classes. But since they already have an instance of the outer class available, they can automatically access instance variables and methods of the outer class.

For a nice (and very detailed) discussion of inner classes and access specifiers, you can read through the Inner Class Specification. It describes, among other things, how a nested class gets access to private members of its outer class(es). A gentler read is the Nested Classes tutorial.

An off-topic aside: Suppose you have this class structure:

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

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

and you've created an instance of O:

O outer = new O();

Now suppose you want to create an instance of O.I. you can't just use new O.I() because the new instance of I needs to be enclosed by a specific instance of O. For this, Java provides the following syntax:

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

Then inner will then have its second this field set to refer to outer.

Note that this "qualified new operator" syntax is only used for inner classes; it would be unnecessary (in fact, an error) if I were a static nested class.

1 You'll often come across the phrase "static inner class" (including, embarrassingly, in an earlier version of this answer). This is incorrect terminology. In Java, "inner classes" are specifically non-static nested classes.

落花浅忆 2024-10-22 04:58:44

您必须区分:

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

You have to differenciate:

  • Static inner classes have access to all static members outside their declaration.
  • Instance inner classes have access to all class members outside their declaration, AND to final fields in the function they are declared in.

Have in mind that a non-static inner class also has a hidden variable with the instance of the outer class, to access the members there. And that all referenced final fields (therefore they must be final) are copied into the inner class in other hidden member variables when the inner class is instantiated.

Example:

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);
}
留一抹残留的笑 2024-10-22 04:58:44

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

静态嵌套类

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

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

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

您应该查看有关嵌套类的 Java 教程

I don't know if it helps, but from the java tutorials:

Static Nested Classes

As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference.
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

Inner Classes [Non-Static Nested class?]

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

You should check the java tutorial on nested classes.

冰雪梦之恋 2024-10-22 04:58:44

Java 中内部类的规则

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

Rules of the Inner classes in Java

  1. In Java it is possible to define a class inside another class such classes are called nested classes or inner class.
  2. There are 3 types of the Inner classes Instance Inner class, static inner class and anonymous inner class
  3. If the Inner class is declared as instance inner class then it can access all of the members of the outer enclosing class including private members
  4. If the Inner class is declared as static then it can only access the static members of the outer class (including the private static members). But it can NOT access the instance members
  5. Consider that there is a variable x is defined in both the outer class and the instance inner classes then general form for accessing the variable from the inner class is this.x for the inner x and OuterClassname.this.x for the outer x.
  6. You can also define an inner class inside any method or any other block
  7. The general form for instantiating the inner class from outside the outer class is
    Outer.Inner ob = new Outer.new Inner();
  8. The general form for instantiating the inner class from outside the outer class is (if the inner class is declared as static)
    Outer.Inner ob = new Outer.Inner();
  9. The Inner classes can be declared with any of the access modifier keywords
  10. If the Inner class is declared as private then it can NOT be instantiated from outside the outer class. Also in this case you can NOT access the members of the Inner class from outside the outer class even you have an object reference and even if the members of the private inner class are declared as public.
  11. If the Inner class is declared as instance inner class then it can also access the superclass members of the outer class through the general statement
    Outer.super.variable; Outer.super.method(params);
凉城 2024-10-22 04:58:44

内部类规则

  1. 内部类可以访问外部类
  2. 外部类不能访问内部类
  3. 内部类成员只使用类内的方法,成员只访问类内的方法完整的信息

Rules for inner class

  1. Outer class accessed by inner class
  2. Inner class can't be accessed by outer class
  3. The inner class members only used the methods and members within the class only access the fulled information
π浅易 2024-10-22 04:58:44

方法作用域内部类:-
只能访问外部类的final成员。

Method Scoped inner classes:-
Can only access the final members of the outer class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文