this的基本概念
this——当前对象。
"this.属性"的形式明确地指明要调用的是类中的属性而不是方法的参数。
在类中访问属性是不管是否有重名的变量,一定要加上this(为了避免麻烦)。
this的作用:
在成员方法中,用this引用去访问类中成员变量和调用类中成员方法。由于this本身就是隐含的,所以一般情况下,可以省略this,直接访问类中成员。特殊情况下,当成员方法中的局部变量和成员变量同名时,可以用 "this."访问 来表示访问同名成员变量,来和同名局部变量做区分。这种情况,this是不能省略的。
在成员方法中只要使用 "this."访问 一个变量,那么该变量一定是成员变量。在代码比较复杂的情况下,可以显著增加代码可读性, 可以使用this.成员变量对成员变量进行赋值。
public class Demo3 {
@Test
public void test1() {
Student student1 = new Student();
Student student2 = new Student();
// this是谁?
student2.show();
System.out.println("main student1====>" + student1);
System.out.println("main student2====>" + student2);
// 哪个对象调用的这个方法, this就是这个对象。 就是当前对象。
}
}
class Person {
public String name;
public int age;
public void setName(String name) {
// 设置值的方法。就是想将 传入的name设置到 成员变量的name上。
name = name;
this.name = name;
}
public void test1() {
// 由于this是隐含的。所以可以直接访问。
System.out.println(name);
System.out.println(this.name);
}
public void test2() {
// 当成员变量和局部变量重名的时候。 如果想访问成员变量,必须使用this
String name = "111233";
System.out.println(name);
System.out.println(this.name);
}
}
this指向当前对象的隐含传参,必须是在普通成员方法中,加static的方法中,没有该this传参。 (所以static方法不能直接访问类的成员,需要先创建对象才能访问。)
构造中this的用法
思考:创建一个教师类,有课程和年龄两个属性,行为是上课。
现在我们需要创建以下对象:
1. 20岁的Java老师对象
2. 21岁的C++老师对象
3. 22岁的Python老师对象
public class Demo1 {
public static void main(String[] args) {
Teacher teacher1 = new Teacher();
teacher1.age = 20;
teacher1.course = "Java";
Teacher teacher2 = new Teacher();
teacher2.age = 21;
teacher2.course = "C++";
Teacher teacher3 = new Teacher();
teacher3.age = 22;
teacher3.course = "Python";
}
可否简单一点呢?,现在又两个属性(age and course)
public class Demo1{
public void test1() {
Teacher teacher = new Teacher("C++");
teacher.teach();
}
}
class Teacher {
// 课程和年龄
public String course;
public int age;
public void teach() {
System.out.println(age + "岁的老师在上" + course);
}
// 构造方法的语法。
// [访问权限修饰符] 类名(形参列表){ // 方法体}
// 形参位置可以有参,也可以无参。 无参被称为无参构造方法; 有参被称为有参构造方法
public Teacher() {
}
public Teacher(String course) {
// 构造方法,其实就是为属性进行赋值的。
this.course = course;
}
// 重载: 方法名, 形参列表不同。、
// 1.数目不同
// 2.类型不同
// 3.位置不同
}
构造方法,并不是创建对象。 它只是对属性进行赋值的。 JVM在选择构造方法的时候,是根据实参的类型的类型、数目来的。
在构造方法中,可以使用this来给当前对象进行赋值。 可以使用 this(实参) 调用该类的其他构造器, 但是这行代码,只能处于第一行。 构造器也可以赋值。
public class Demo4 {
}
class Student4 {
public String name;
public String address;
public int age;
public String phone;
public Student4(String name, String address, int age, String phone) {
this(name, address, age);//调用三参构造器
this.phone = phone;
}
public Student4(String name, String address, int age) {
this(name, address);//调用双参构造器
this.age = age;
}
public Student4(String name, String address) {
this.name = name;
this.address = address;
}
}
那么代码是如何执行的呢?先看一个简单的例子,记住构造器赋值永远在最后。
ublic class Demo6 {
public static void main(String[] args) {
// 创建Person对象,成员变量的值分别是什么
Person p = new Person("张三", 30);
// 1.永远是默认初始化
// 2.显式赋值
// 3.构造器赋值。
// 构造器赋值永远在最后。
}
}
class Person {
String name;
int age = 20;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
}
复杂的例子(详细过程在下面)
public class Demo8 {
public static void main(String[] args) {
// new Student8的时候。执行流程是怎样的
Student8 stu = new Student8(18, "王冰冰");
}
}
class Student8 {
int age = 10;
String name = "张三";
double a = 100;
public Student8() {
}
public Student8(int age) {
System.out.println("Student age");
this.age = age;
}
public Student8(int age, String name) {
this(age);
System.out.println("Student age,name");
this.name = name;
}
}
执行流程如下:
1.分配内存:JVM首先在堆内存中为新的 Student8 对象分配足够的内存空间。
2.初始化成员变量:按照类定义的顺序,依次为对象的成员变量赋予默认初始值或显式初始化值。对于 Student8 类:
- age 被初始化为 10。
- name 被初始化为 "张三"
- a 被初始化为 100
3.调用构造函数:接下来,JVM会根据提供的参数列表(18, "王冰冰")找到合适的构造函数进行调用。在这个例子中,会选择带有两个参数的构造函数 public Student8(int age, String name)。
构造函数内部执行顺序:
a. 调用基构造函数:构造函数内部的 this(age) 语句调用了另一个带有一个参数的构造函数 public Student8(int age)。此时执行流程进入该构造函数:
i. 输出语句 System.out.println("Student age");
ii. 赋值语句 this.age = age; 将传入的参数 age(值为 18)赋给当前对象的 age 成员变量。b. 回到当前构造函数:完成基构造函数调用后,继续执行当前构造函数剩余的语句:
i. 输出语句 System.out.println("Student age,name");
ii. 赋值语句 this.name = name; 将传入的参数 name(值为 "王冰冰")赋给当前对象的 name 成员变量。至此,Student8 对象的构造过程完成,对象已经完全初始化,可以正常使用。最后,main 方法中的语句 Student8 stu = new Student8(18, "王冰冰"); 将新建的对象的引用赋值给局部变量 stu。
综上所述,执行顺序如下:
- 分配内存
- 初始化成员变量:age = 10, name = "张三", a = 100
- 调用构造函数 Student8(int age, String name) a. 调用基构造函数 Student8(int age) i. 输出 "Student age" ii. age = 18 b. 输出 "Student age,name" c. name = "王冰冰"
- 将新建对象的引用赋值给局部变量 stu