关于Android中this的用法解释

问题由来

由于很多同学在学习Android时候没有对Java有很深的了解,很多人都会对代码中各种各样的this产生疑惑。

以《第一行代码Android》P37页,P43页代码为例:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    Button button1 = (Button) findViewById(R.id.button_1);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        }
    });
}

有些同学会觉得非常奇怪,这个this是用来指代什么呢?是和class一样的意思吗?

那为什么FirstActivity要用this,而SecondActivity却要用class呢?

this的三种用法

1.表示对当前对象的引用

以以下代码为例:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button play = (Button) findViewById(R.id.play);
        Button stop = (Button) findViewById(R.id.stop);
        play.setOnClickListener(this);
        stop.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.play:
                Videoplay();
                break;
            case R.id.stop:
                Videostop();
                break;
        }
    }
}

play.setOnClickListener(this)中的this,是对当前类MainActivity的引用。
那么为什么在开始的代码中要使用FirstActivity.this来引用FirstActivity呢?

我们仔细分析上下两段代码,发现this所处的类是不一样的,上面的代码中,this存在于匿名类View.OnClickListener()中!
匿名类View.OnClickListener()是FirstActivity的内部类,如果我们在内部类中使用this,他所引用的类应该是View.OnClickListener()。
Android编译器在编译我们的代码的时候就会发现:“诶View.OnClickListener()你丫谁啊?我咋从你身上启动SecondActivity啊”。然后就快乐的报错了。
所以在内部类中,如果我们需要获得其外部类,就要使用“外部类.this”的写法。

  • 注:“.class”是因为表示其它类的写法。

2.表示用类的成员变量,而非函数参数

以以下代码为例:

public class Book {

    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

在代码中我们定义了一个Book类并生成了对应的getter和setter方法。在setter方法中我们发现了this,而且还是this.而不是.this!
仔细研究setId方法,我们发现里面的几个id所对应的东西都是不一样的。

setId(int id)中的id指的是外部调用这个方法时所赋予的参数,比如新建一个Book类变量book,book.setId(1)中的1就是参数。
this.id中的id我们显然希望他是Book类中的成员变量id,=id中的id显然应该是赋予的参数,和setId(int id)为同样的东西。
故而这个this就是为了防止编译器把三个id都认为是同样的东西,特地指明了第二个this是Book类中的成员变量id。

  • 有些同学可能会和第一个用法中的this混淆,认为this不是指向setId方法吗?这说明你混淆了类和方法之间的区别。this指向的是类而不是方法。

3.用于在构造方法中引用满足指定参数类型的构造器

这个说法可能有些复杂,因为这个主要是用在Java中的,Java中一个方法可能对应多种构造方法,如:

public class Student 
   public Student() 
   }
   public Student(String name) 
   }
   public Student(int id) 
   }
}

以方便我们减少方法的数量,那么如果我们修改上述代码变为:

public class Student 
   public Student() {
       this(“HelloWorld”);
   }
   public Student(String name) {
   }
   public Student(int id) { 
   }
}

this又出现了,这次this出现在了构造方法之中,这意味着当你不使用参数调用Student类时,编译器会自动认为你使用了“HelloWorld”参数调用了Student类中的Student(String name)的构造方法,如果改成this(1)的话那就是Student(int id)的构造方法.

  • 注:第三种用法,每个构造方法只能引用一个构造方法!而且必须位于起始位置。
public class Student 
   public Student() {
       this(“HelloWorld”);
   }
   public Student(String name) {
       this(1);
   }
   public Student(int id) {
   }
}

这是符合规范的,无论你使用Student()还是Student(“...”),都等于Student(1);

public class Student 
   public Student() {
       this(“HelloWorld”);
       this(1);
   }
   public Student(String name) {   
   }
   public Student(int id) {
   }
}

这是错误的,你使用Student()时编译器会不知道到底应该使用Student(“HelloWorld”)还是Student(1)而选择死亡。