【问题标题】:what does "this" keyword mean in the initializer block? [duplicate]初始化程序块中的“this”关键字是什么意思? [复制]
【发布时间】:2014-03-08 06:41:24
【问题描述】:

这是我的代码:

class StaticBlock {
    {       
        println("initializer block : " + message);
    }
    public StaticBlock(String message) {
        this.message = message;
    }
    private String message;
}

现在的问题是,在初始化块中

{       
    println("initializer block : " + message);
}

如果我在message 之前添加this 关键字,它可以工作,但是缺少this 关键字时会出错。

编译器说:

StaticBlockDemo.java:34: illegal forward reference
                println("initializer block : " + message);
                                                 ^
1 error

为什么它们不一样?

【问题讨论】:

  • 'this',我的意思可能是'当前'实例,但在这里,我似乎很困惑。
  • 那些“重复”实际上不是同一个问题,如果您阅读的内容超过摘要...
  • 我同意,这些重复项实际上并不是重复项。

标签: java this


【解决方案1】:

我不知道设计原理,但阅读 Java 语言规范的相关部分可能会有所帮助。

8.6. Instance Initializers

允许实例初始化器通过关键字this(§15.8.3)引用当前对象,使用关键字super(§15.11.2,§15.12),并使用任何类型的变量范围。

使用在使用后以文本形式出现的实例变量的使用有时会受到限制,即使这些实例变量在范围内。有关管理对实例变量的前向引用的精确规则,请参阅第 8.3.2.3 节。

8.3.2.3. Restrictions on the use of Fields during Initialization

仅当成员是类或接口C 的实例(分别为static)字段并且满足以下所有条件时,成员的声明才需要在使用前以文本形式出现:

  • C 的实例(分别为static)变量初始化器或C 的实例(分别为静态)初始化器中使用。

  • 用法不在作业的左侧。

  • 用法是通过一个简单的名称。

  • C 是包含用法的最内层类或接口。

以下是规范该部分的示例,以说明您要询问的具体点:

class UseBeforeDeclaration {

    {
        j = 200;
          // ok - assignment
        j = j + 1;
          // error - right hand side reads before declaration
        int k = j = j + 1;
          // error - illegal forward reference to j
        int n = j = 300;
          // ok - j at left hand side of assignment
        int h = j++;
          // error - read before declaration
        int l = this.j * 3;
          // ok - not accessed via simple name
    }

    int j;
}

不过,我还应该指出,即使是您的代码的编译版本也无法满足您的要求。如果你运行它:

new StaticBlock("abc");

它会打印出来

initializer block : null

这是因为初始化程序在(大部分)构造函数主体之前执行。以下是规范中的要点:

12.5. Creation of New Class Instances

[...] 使用以下过程处理指示的构造函数以初始化新对象:

[...]

 4. 为这个类执行实例初始化器和实例变量初始化器[...]

5. 执行此构造函数的其余部分。 [...]

【讨论】:

  • 谢谢,事实上,你是对的,我在作用域初始化块之外定义了实例变量“消息”,除非我使用关键字“this”,否则它是无法访问的。
【解决方案2】:

如果我在 'message' 之前添加 'this' 关键字,它可以工作,但缺少 'this' 关键字时会出错。为什么它们不一样?

this 关键字指向类的当前实例。

public StaticBlock(String message) {
    this.message = message;
}

这里如果你不使用this,那么它将分配message局部变量的值,因为局部变量的作用域不仅仅是一个块中的实例。

当您使用this 时,它将分配当前对象变量的变量值。

【讨论】:

  • 在堆栈中,语句'StaticBlock(String message)'确实创建了一个变量'message',不是吗?让我困惑的是,在常见的非静态方法中,我们可以参考到实例变量,即使不使用“this”。你不认为它们不相似吗?
  • 它创建了一个名为message的局部变量,如果你不使用this,它会为同一个局部变量分配相同的值。 “让我感到困惑的是,在普通的非静态方法中,即使不使用 'this',我们也可以引用实例变量。你不认为它们不相似吗?” -- 你可以,但你必须有不同的局部变量和实例变量的名称。在这里你有两个相同的message
【解决方案3】:

在 Java 中使用类的好处之一是您可以将对象建模为一个类,并且可以创建一个对象的多个实例(在大多数情况下)。

为了引用特定于单个对象类的信息,我们可以在对象(类)代码中使用this。它告诉程序您要使用current 对象变量和值。通过使用this.message = message,您将分配已传递给函数的消息值并将其存储在对象的消息变量中。

这涉及范围方面,其中message 具有本地范围,this.message 具有整个对象的范围。这就是为什么当您尝试在打印代码中调用消息:println("initializer block : " + message); 时,此函数范围内不存在局部变量消息。

【讨论】:

  • 谢谢,事实上,你是对的,我在作用域初始化程序块之外定义了实例变量“消息”,除非我使用关键字“this”,否则它是无法访问的。
【解决方案4】:

如果局部变量名和实例成员名冲突,则this关键字将告诉编译器使用对象变量。

【讨论】:

  • '类变量'?它不应该是“实例变量”吗?我很困惑,因为在非静态方法中,无论“this”是否存在,它的工作原理都是一样的,我的意思是,它不是必需的,不是吗?
  • 嗯,是的,你是对的,属于对象的变量。我会更新它以使其清楚。
猜你喜欢
  • 1970-01-01
  • 2012-02-10
  • 2022-01-01
  • 2011-12-24
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多