为什么在构造函数和Setter中使用“this”关键字?

时间:2018-05-08 03:15:57

标签: java constructor setter getter

构造函数用于初始化一个值,并在创建类实例时将其赋值给类变量,对吗?

public class Joke{
   private String jokeSetup;
   private String jokePunchLine;

   public Joke(String jokeSetup , String jokePunchLine){
       this.jokeSetup=jokeSetup;
       this.jokePunchLine=jokePunchLine;
   }
}  

请考虑以下事项:

public Joke(String jokeSetup , String jokePunchLine) 

是否创建了另一个具有相同名称的变量?

如果是这样,为什么会将其分配给前jokeSetupjokePunchLine值?

PS:这段代码不是由我创建的。它是在我正在学习Java的视频中显示的。

4 个答案:

答案 0 :(得分:8)

构造函数的目的是初始化刚刚创建的对象,例如填充其实例字段(也称为实例变量)。构造函数中使用this来引用构造函数初始化的实例。

在示例构造函数中,您有参数实例字段。构造函数正在获取参数的值并将这些值分配给实例字段:

public Joke(String jokeSetup , String jokePunchLine)
//          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- Declares parameters this
//                                                      constructor accepts when
//                                                      called
{
//                 vvvvvvvvv------------ parameter
    this.jokeSetup=jokeSetup;
//  ^^^^^^^^^^^^^^---------------------- instance field

//                     vvvvvvvvvvvvv---- parameter
    this.jokePunchLine=jokePunchLine;
//  ^^^^^^^^^^^^^^^^^^------------------ instance field
}

构造函数可以初始化具有常量值的实例字段,或者间接使用参数值(例如,查找某些内容)等。它并不总是直接的一对一分配,因为它是在你的例子中。

在您的示例中,参数与实例字段具有相同的名称,但这不是必需的。例如,这个构造函数与您的构造函数完全相同:

public Joke(String theJokeSetup , String theJokePunchLine)
//                 ^---------------------^---------- Note the name changes
{
//                   vvvvvvvvvvvv------------ parameter
    this.jokeSetup = theJokeSetup;
//  ^^^^^^^^^^^^^^--------------------------- instance field

//                       vvvvvvvvvvvvvvvv---- parameter
    this.jokePunchLine = theJokePunchLine;
//  ^^^^^^^^^^^^^^^^^^----------------------- instance field
}

Java允许您在引用实例字段时不使用this.部分,只需单独使用字段名称(例如jokeSetup而不是this.jokeSetup)。但是,除非重命名参数,否则不能在构造函数中执行此操作,因为它们与实例字段具有相同的名称,因此构造函数中的jokeSetup是参数,而不是字段。当出现类似的冲突时,最本地标识符优先(在构造函数中,参数是最本地的)。

如果没有冲突,无论您是否使用this.部分,都是一种风格问题。 (我总是使用this.,我发现它更清楚。)例如,这里是该构造函数的另一个版本,与原版完全相同:

public Joke(String theJokeSetup , String theJokePunchLine)
//                 ^---------------------^---------- Note the name changes
{
//              vvvvvvvvvvvv------------ parameter
    jokeSetup = theJokeSetup;
//  ^^^^^^^^^--------------------------- instance field

//                  vvvvvvvvvvvvvvvv---- parameter
    jokePunchLine = theJokePunchLine;
//  ^^^^^^^^^^^^^----------------------- instance field
}

我之所以提到这一点是因为,当没有冲突时,这只是一种风格问题,你有时会看到这种风格。

答案 1 :(得分:2)

该类有一个名为jokeSetup的字段。 该方法具有与该字段 shadow 同名的参数。

所以本质上有两个同名的变量。

使用这个可以再次区分两个同名的不同用法,因为 this.whatever 总是表示相应的字段。

你钉了它:阴影实际上不是一个好主意。但这种“模式”在Java中实际上很常见。您可以通过为参数指定一个不同的名称来避免它,例如_jokeSetup,但偏离常规做法也是不好的做法。

答案 2 :(得分:2)

参数化构造函数可用于在创建变量时将值初始化为变量。当参数和变量名称相同时,在这种情况下要区分两者,我们使用 this 关键字。 keyworord始终引用方法或类的局部变量。

答案 3 :(得分:1)

Java对符号名称有隐含的上下文;非静态上下文的类实例(即this)和静态的类(例如Joke)。

这使您可以在符号名称没有冲突时省略上下文。例如

public String getJokeSetup() {
    return jokeSetup; // no "this." required, it's implied
}

如果名称存在冲突,例如名称与字段相同的方法参数的情况,则需要明确定义上下文,例如

public void setJokeSetup(final String jokeSetup) {
    // you must prefix the field with "this." to differentiate it from the argument
    this.jokeSetup = jokeSetup; 
}

最后,这是一个避免符号名称冲突的例子

public void setJokeSetup(final String js) {
    jokeSetup = js;
}

将参数命名为与它们对应的字段相同是相当典型的,但您肯定不会受到这种约定的限制。