当前位置: 首页 > 面试题库 >

Java作用域规则和内部类

颛孙镜
2023-03-14
问题内容

所有疯狂的Java范围界定规则都使我垂头丧气,而 公共静态无效的
废话无济于事。到目前为止,我所使用的所有编程语言都是词法作用域或它的某种近似,而没有任何访问修饰符,即内部内容捕获外部内容,只要内部内容存在,就可以访问外部内容。

那么,如何理解Java内部类的作用域规则?他们是否可以访问在外部类中声明的变量,或者由于所有 公共静态私有
事物在周围徘徊,我是否有必要担心一些奇怪的情况?


问题答案:

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

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

要对内部类和访问说明符进行漂亮(非常详细)的讨论,可以阅读《
内部类说明》
。它描述了嵌套类如何访问private其外部类的成员。嵌套类教程是比较温和的读物。

除了题外话:假设您具有以下类结构:

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嵌套类。



 类似资料:
  • 作用域在所有权(ownership)、借用(borrowing)和生命周期(lifetime)中起着重要作用。也就是说,当借用有效,当资源可以释放,还有当变量被创建或销毁时,作用域都在指导编译器(原文:That is, they indicate to the compiler when borrows are valid, when resources can be freed, and whe

  • 问题内容: 有人可以帮助我了解Java中的范围规则吗?这显然是无效的: 在内声明,在外部不可用。那么呢: 我对这里的语法错误感到惊讶。在外部作用域中声明,但以后将不可用。它是否通过某些特殊的循环规则绑定到内部块作用域?还有其他可能发生这种情况的情况吗? 问题答案: 想想for循环实际上是这样表示的:

  • Rust 的变量不只是在栈中保存数据:它们也占有资源,比如 Box<T> 占有堆中的内存。Rust 强制实行 RAII(Resource Acquisition Is Initiallization,资源获取即初始化),所以任何一个对象在离开作用域时,它的析构器(destructor)都被调用以及它的资源都被释放。 这种行为避免了资源泄露(resource leak)的错误,所以你再也不用手动释放

  • 程序中一个标识符有意义的部分称为其作用域。例如,块中声明局部变量时,其只能在这个块或这个块嵌套的块中引用。一个标识符的4个作用域是函数范围(function scope)、文件范围(filescope)、块范围(block scope)和函数原型范围(function-prototype scope)。后面还要介绍第五个——类范围(class scope)。 任何函数之外声明的标识符取文件范围。这

  • 多数情况下,我们更希望访问数据本身而不需要取得它的所有权。为实现这点,Rust 使用了借用(borrowing)机制。对象可以通过引用(&T)来传递,从而取代通过值(T)来传递。 编译器静态地保证了(通过借用检查器)引用总是(always)指向有效的对象。也就是说,当存在引用指向一个对象时,该对象不能被销毁。 // 此函数拥有 box 的所有权并销毁它 fn eat_box_i32(boxed_i

  • 因为变量要负责释放它们拥有的资源,所以资源只能拥有一个所有者。这也防止了资源的重复释放。注意并非所有变量都拥有资源(例如 references)。 在进行赋值(let x = y)或通过值来传递函数参数的时候,资源的所有权(ownership)会发生转移(transfer)。按照 Rust 的说法,这种方式被称为移动(move)。 在移动资源之后,原来的所有者不能再使用,这可避免悬垂指针的产生。