8

如果我写以下课程:

public class Example {

      int j;
      int k;

      public Example(int j, int k) {
           j = j;
           k = k;
      }

      public static void main(String[] args) {
           Example exm = new Example(1,2);
           System.out.println(exm.j);
           System.out.println(exm.k);
      }

}

程序可以编译,但是当我运行程序时,main方法会打印出两个0。我知道,为了说我想在构造函数中初始化实例变量,我必须写:

this.j = j;
this.k = k;

但是如果我不写它,那么在构造函数中(在表达式的左侧和写手侧)评估(或考虑)哪个变量?是参数还是实例变量?这有什么不同吗?

是否还有其他this必须使用的情况?

4

13 回答 13

32

如果你的构造函数中没有写“this.variable”,并且如果你的构造函数中有一个与你的字段变量同名的局部变量(包括函数参数),那么会考虑局部变量;局部变量遮蔽了字段(又名类变量)。

一个地方,“这个”是唯一的出路:

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.
    }
  }
}
于 2009-02-05T15:17:05.187 回答
10

如果您只j在构造函数中说,那么编译器会认为您在这两种情况下都指的是参数。所以

j = j;

只需将参数的值分配给j参数j(这是一个非常没有意义但仍然有效的语句)。

因此,为了消除歧义,您可以添加前缀this.以明确表示您的意思是具有相同名称的成员变量。

的另一个用途this是当您需要将对当前对象的引用传递给某个方法时,例如:

someObject.addEventListener(this);

在此示例中,您需要将当前对象作为一个整体来引用(而不仅仅是对象的一个​​成员)。

于 2009-02-05T15:18:30.380 回答
6

如果你不写这个,那么你将参数分配给它自己;参数变量隐藏实例变量。

于 2009-02-05T15:16:15.657 回答
5

当您想要返回对象本身时,这很有用

return this;

这很有用,因为如果一个类具有例如 Method1() 和 Method2(),两者都返回 this,则允许您编写如下调用

object.Method1().Method2()

同样在方法内部,在调用期间将对象本身传递给另一个函数也很有用。

于 2009-02-05T15:17:08.243 回答
5

另一种有用的方法(虽然很少使用)是声明方法参数 final:

以下块将不会编译,因此会立即提醒您注意错误:

  public Example(final int j, final int k) {
       j = j;
       k = k;
  }
于 2009-02-05T15:30:44.690 回答
3

在您的构造函数代码中,您正在为自己分配变量。'j' 是在构造函数的参数中指定的 j。即使它是上面定义的类变量 j,那么您仍然在说“j = j”......即 j 不会在左侧和右侧进行不同的评估。

  public Example(int j, int k) {
       this.j = j;
       this.k = k;
  }
于 2009-02-05T15:17:16.683 回答
3

您所遇到的称为变量阴影。查看此概述,了解Java 中不同类型的变量

一般来说:Java 编译器使用它可以找到的最近的变量进行赋值。在一个方法中,它会首先尝试找到一个局部变量,然后将搜索的焦点扩大到类和实例变量。

我个人认为好的(其他人不喜欢它)的一个习惯是在成员变量前面加上 m_ 并为不改变其值的 CONSTANT_VARIABLES 使用大写。故意使用变量阴影的代码非常(!)难以调试和使用。

于 2009-02-05T15:21:12.417 回答
2

您在示例中将参数分配给自身。

更一般地说:如果您没有为变量添加范围,则假定当前范围 - 这是您的情况下的函数。'this.j' 告诉 jre 在对象范围内使用变量 j - 对象的成员变量。

于 2009-02-05T15:18:37.803 回答
1

就像罗伯特格兰特所说的那样,'this' 是您明确表示您指的是成员变量而不是局部变量的方式。

于 2009-02-05T15:19:21.563 回答
1

使用方法回答您关于此的后续问题,Srikanth 提到的内部类仍然是使用此方法的有效示例:(这次使用方法)

public class OuterClass
{
    void f() {System.out.println("Outer f()");};
    class InnerClass {
        void f() {
            System.out.println("Inner f()");
            OuterClass.this.f();
        }
    }
}

匿名类也有同样的情况:

您可以通过以下方式引用外部类的方法:

  • MyOuterClass.this.yOuterInstanceMethod(),
  • MyOuterClass.myOuterInstanceMethod(),
  • 或者只是myOuterInstanceMethod() 如果没有歧义
于 2009-02-06T07:01:29.350 回答
0

为避免这种情况,请使用 IDE(如 Eclipse),它会在这种情况下生成警告。

另外,除非绝对不可能,否则请使您的字段成为最终字段。这样做的原因有很多(除了这个)。

于 2009-07-03T12:14:37.380 回答
0

这并不能完全回答您的问题,但如果您使用 Eclipse,您可能会发现“分配无效”设置很有用。我相信这也会出现在其他 IDE 中。

于 2009-02-06T07:29:20.077 回答
0

您可能想看看强制显式指针有什么好处?this/self
尽管this正如您所注意到的,在 Java 中使用不是强制性的,但我相信它也会对this在 Java 中使用的主题有所启发。

于 2009-07-03T11:02:11.360 回答