The use of “this” in Java
如果我写下面的课:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
程序会编译,但是当我运行程序时,主方法会打印出两个0。我知道为了说明我要在构造函数中初始化实例变量,我必须编写:
1 2 | this.j = j; this.k = k; |
但是,如果我不写它,那么在构造函数(左边和在表达式的手写边)中评估(或考虑)哪个变量?参数是变量还是实例变量?有什么区别吗?
还有其他必须使用
如果不在构造函数中写入"this.variable",并且有一个局部变量(包括函数参数)与构造函数中的字段变量同名,则将考虑该局部变量;局部变量隐藏字段(也称为类变量)。
"这"是唯一的出路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class OuterClass { int field; class InnerClass { int field; void modifyOuterClassField() { this.field = 10; // Modifies the field variable of"InnerClass" OuterClass.this.field = 20; // Modifies the field variable of"OuterClass", // and this weird syntax is the only way. } } } |
如果在构造函数中只说
1 | j = j; |
只需将参数
因此,为了消除歧义,可以将EDOCX1 3的前缀明确为:你是指同名的成员变量。
EDOCX1 4的另一个用法是当您需要将当前对象的引用传递给某种方法时,例如:
1 | someObject.addEventListener(this); |
在这个例子中,你需要将当前对象作为一个整体来引用(而不仅仅是对象的一个成员)。
如果不写这个,那么就将参数赋给它自己;参数变量隐藏实例变量。
另一个有用的方法(虽然很少使用)是声明方法参数最终:
以下块将不会编译,因此会立即警告您该错误:
1 2 3 4 | public Example(final int j, final int k) { j = j; k = k; } |
当您想要返回对象本身时,这很有用
1 | return this; |
这很有用,因为如果一个类具有例如method1()和method2()这样的返回值,则允许您编写如下调用
1 | object.Method1().Method2() |
同样,在方法内部,在调用期间将对象本身传递给另一个函数也是很有用的。
你所经历的是所谓的可变阴影。查看Java中不同类型变量的概述。
一般来说,Java编译器使用它可以找到的最接近的赋值变量。在一个方法中,它首先尝试找到一个局部变量,然后将搜索的焦点扩大到类和实例变量。
我个人发现的一个好习惯(其他人不喜欢)是在成员变量前面加上m_u,并对不改变其值的常量变量使用大写。使用变量阴影的代码非常(!)很难调试和使用。
在构造函数代码中,您将为自己分配变量。"j'是在构造函数的参数中指定的j。即使它是上面定义的类变量j,那么您仍然会说"j=j"…也就是说,J的评价在左边和右边不会有所不同。
1 2 3 4 | public Example(int j, int k) { this.j = j; this.k = k; } |
在示例中,将参数分配给自己。
更一般地说,如果不预先为变量准备一个作用域,则假定为当前作用域——在您的情况下,它是函数。"这个.j'告诉JRE在对象范围内使用变量j——对象的成员变量。
为了用方法来回答关于这个问题的后续问题,srikanth提到的内部类仍然是使用这个方法的有效例子:(这次用方法)
1 2 3 4 5 6 7 8 9 10 |
匿名类的情况也一样:
You can refer to the outer class’s methods by:
MyOuterClass.this.yOuterInstanceMethod() ,MyOuterClass.myOuterInstanceMethod() ,- or simply
myOuterInstanceMethod() if there is no ambiguity.
正如罗伯特·格兰特所说,"这就是你如何明确地表明你所指的是成员变量而不是局部变量。"
为了避免这种情况,使用一个IDE(如Eclipse),在这种情况下它将生成警告。
另外,除非你的领域绝对不可能是最终的。有很多原因(除了这一个)这样做。
您可能想看看
这并不能完全回答您的问题,但是如果您使用Eclipse,您可能会发现"赋值没有效果"设置很有用。我相信这也会出现在其他IDE中。