我们先来了解下 Python 中类的相关知识,在 Python 中所定义的类中即使没有显式的__init__初始化方法,实际上它也是默认带有__init__方法(一般情况下源于父类object,无任何参数),并在类实例化时进行调用。但是,如果我们需要所定义的类可以接收初始化参数,那么就必须使用__init__方法。

1. 默认构造器

Java 的构造器原理其实很类似,每个定义的类都有一个默认的隐式构造器,如果我们将这个隐式的构造器显式得定义出来,则如下所示:

  1. public class Car {
  2. public Car() {
  3. }
  4. public static void main(String[] args) {
  5. }
  6. }

2. 带参构造器

有了上面的这种结构,我们很轻松的就可以完成带参的类构造器:

  1. public class Car {
  2. String brand;
  3. String color;
  4. long price;
  5. public Car(String brand_, String color_, long price_) {
  6. brand = brand_;
  7. color = color_;
  8. price = price_;
  9. }
  10. public void run() {
  11. System.out.println(color + "-" + brand + " is running!");
  12. }
  13. public static void main(String[] args) {
  14. Car benz = new Car("Benz", "Red", 400000);
  15. benz.run();
  16. }
  17. }

回顾之前的示例,当时我们实例化一个Car类后,还需要 3 行代码来给成员变量进行赋值,如果有很多Car实例就会显得很麻烦。采用带参的构造器后,都不在需要手动赋值,这些操作在初始化的时候就完成了。

当然,与 Python 不同的是,Java 中是可以定义多个构造器的(这一点在前面介绍方法重载的时候就介绍过),如果构造了一个带参构造器的话,建议将默认的无参构造器也添加上。

  1. public class Car {
  2. String brand;
  3. String color;
  4. long price;
  5. public Car() {}
  6. public Car(String brand_, String color_, long price_) {
  7. brand = brand_;
  8. color = color_;
  9. price = price_;
  10. }
  11. public void run() {
  12. System.out.println(color + "-" + brand + " is running!");
  13. }
  14. public static void main(String[] args) {
  15. Car benz = new Car("Benz", "Red", 400000);
  16. benz.run();
  17. }
  18. }

3. this关键字

有些同学可能已经发现了,我们在定义有参构造器时,参数的名称我们使用了brand_这样的方式,为什么?如果参数名称修改为brand的话,即下面所示的构造器,那么整个构造器是无法正常工作的(即使可以成功编译),因为 JVM 会默认这个brand是构造的参数,而非成员变量brand

  1. public Car(String brand, String color, long price) {
  2. brand = brand;
  3. color = color;
  4. price = price;
  5. }

3.1 this访问成员变量

为了避免这个问题,我们引入一个新的知识点this,使用this.brand来特指类的成员变量brand

  1. public class Car {
  2. String brand;
  3. String color;
  4. long price;
  5. public Car(String brand, String color, long ) {
  6. this.brand = brand;
  7. this.color = color;
  8. this.price = price;
  9. }
  10. public void run() {
  11. System.out.println(this.color + "-" + this.brand + " is running!");
  12. }
  13. public static void main(String[] args) {
  14. Car car = new Car("Benz", "Red", 400000);
  15. car.run();
  16. }
  17. }

实际上,每个方法都会默认传入this变量,并且this变量所指向的是当前调用它的实例。

3.2 this访问方法

同样地,可以使用this.run()方式来调用方法。当然,你直接使用run()也是可以的。

  1. public Car(String brand, String color, long ) {
  2. this.brand = brand;
  3. this.color = color;
  4. this.price = price;
  5. this.run(); // run();
  6. }

3.3 this访问构造器

除此之外,this还可以访问构造器,前提条件是在无参构造器中访问其他有参构造器,这个时候this特指有参构造器,且下面高亮的代码必须放在第一行(原因很简单,只有当构造器创建好之后,才能继续执行其他内容,如果先执行其他内容再创建构造器,显然是不合理的)。

  1. public class Car {
  2. String brand;
  3. String color;
  4. long price;
  5. public Car() {
  6. this("Benz", "Red", 400000);
  7. }
  8. public Car(String brand, String color, long price) {
  9. this.brand = brand;
  10. this.color = color;
  11. this.price = price;
  12. }
  13. public void run() {
  14. System.out.println(this.color + "-" + this.brand + " is running!");
  15. }
  16. public static void main(String[] args) {
  17. Car car = new Car("Benz", "Red", 400000);
  18. car.run();
  19. Car car2 = new Car();
  20. car2.run();
  21. }
  22. }