Java讲课笔记11:构造方法与this关键字

文章目录

零、本讲学习目标

1、掌握构造方法的定义

2、掌握构造方法的重载

3、掌握this关键字

一、构造方法

(一)构造方法的作用

实例化一个类的对象后,如果要为这个对象中的属性赋值,则必须通过直接访问对象的属性或调用setXxx()方法的方式才可以。如果需要在实例化对象的同时就为这个对象的属性进行赋值,可以通过构造方法来实现。简而言之,构造方法(constructor)是在利用类这个模板创建对象时自动调用的,用于初始化对象的属性。

(二)构造方法的特点

1、构造方法名与类名相同

构造方法不能由编程人员调用,而要系统自动调用,如果构造方法名与类名不同,随便取一个名字,那么系统是无法识别出来的,因此,构造方法名必须与类名相同,初始化对象时,系统直接调用与类名相同的方法就很容易。

2、构造方法没有返回值类型声明

方法头不能有返回值类型声明,连void返回值类型也不行。方法体里不能用return返回一个值,当然可以单独写一个return语句来作为方法的结束。

3、构造方法必须是public的

如果构造方法私有化,那么就不能用new来实例化对象,必须通过其它方式来得到实例,比如提供一个获得对象实例的静态方法,后面我们会演示如何操作。

4、一个类可以不定义构造方法

如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造方法,并且这个构造方法不执行任何代码。

还记得我们第一个上Java课所创建的HelloWorld.java吧。
在这里插入图片描述
在这里插入图片描述
大家可以看到,HelloWorld这个类是没有定义构造方法的,但是编译成HelloWorld.class字节码文件之后,编译系统会自动添加一个默认的无参构造方法,如下图所示:
在这里插入图片描述

5、构造方法可以重载

一个类允许定义多个构造方法,即构造方法可以重载,提供对象不同的初始化方式,以参数的个数,类型,或排列顺序区分。

(三)构造方法的分类

1、无参构造方法

public 类名() {
	……
}

2、有参构造方法

public 类名(参数列表) {
	……
}

(四)构造方法定义案例演示

在上一讲里我们创建的Person没有显式地声明构造方法,编译系统会自动添加一个默认的无参构造方法,里面不执行任何代码,因此我们仍然可以用new Person()语句来创建Person类的实例对象。当然我们也可以显式地声明一个无参构造方法。下面我们就给上一讲我们创建的Person类添加一个无参构造方法。

1、显式声明无参构造方法

  • 给Person类添加一个无参构造方法
    在这里插入图片描述
package net.hw.lesson11;

/**
 * 功能:显示声明无参构造方法
 * 作者:华卫
 * 日期:2020年4月29日
 */

public class Person {   
    private String name;   
    private int character;

    /**
     * 无参构造方法
     */
    public Person() {
        System.out.println("无参构造方法被调用了~");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCharacter() {
        return character;
    }

    public void setCharacter(int character) {
        if (character >= 1 && character <= 10) {
            this.character = character;
        } else {
            System.err.println("温馨提示:人品值必须在[1, 10]范围内!");
        }
    }

    /**
     * 自我介绍方法
     */
    public void speak() {
        System.out.println("嗨,我叫" + name + ",人品值:" + character);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", character=" + character +
                '}';
    }
}
  • 创建Example1101类,实例化Person类
    在这里插入图片描述

2、定义有参构造方法用于初始化对象属性

  • 修改Person类,添加一个有参构造方法
    在这里插入图片描述
    说明:this.name = name; 由于构造方法参数名与属性名相同,因此要在属性名之前加一个前缀thisthis代表当前类的一个实例对象,语句this.name = name;表明是要把参数值赋给实例对象的同名属性。

  • 创建Example1102,通过有参构造方法实例化对象,调用对象方法

在这里插入图片描述

3、删除(注释)无参构造方法,保留有参构造方法

注释掉无参构造方法:
在这里插入图片描述
当一个类定义了有参构造方法,如果此时没有无参构造法,编译系统是不会自动生成一个默认的无参构造方法的,不信,我们查看Example1101,就会发现程序要报错,如下图所示:
在这里插入图片描述
如果我们恢复无参构造方法:
在这里插入图片描述
此时,Example1101就没有问题,也可以正常运行了。
在这里插入图片描述
其实,Person类现在有两个构造方法,一个无参构造方法,一个有参构造方法(对两个属性初始化),这就已经是构造方法的重载了。

(五)构造方法的重载

1、案例演示:给Person类添加重载的构造方法

  • 修改Person类,添加一个单参构造方法

构造方法可以自己写,其实可以利用集成开发环境帮我们自动生成所需的构造方法。下面我就演示如何添加一个只初始化name属性的单参构造方法。

在这里插入图片描述
利用Code | Genderate…,也可以利用组合键<Ctrl> + <Insert>,弹出Generate菜单,选择Constructure,然后选择需要构造方法初始化的字段或属性(按着Ctrl键,可以同时选中多个字段或属性),单击【OK】即可。
在这里插入图片描述

  • 再添加一个tell()方法

在这里插入图片描述

  • 创建Example1103类,测试两个有参构造方法初始化对象

在这里插入图片描述

Python构造方法没有重载的概念,但是可利用变长参数*args来实现类似于构造方法的重载。下面的Person类,在创建对象时,可以接收0、1或2个参数。对于1个参数,如果是字符串,那么作为姓名传入,否则作为人品值传入,但必须是整数。

"""
演示构造方法的重载
"""
class Person:
    def __init__(self, *args):
        if len(args) == 0:
            self.name = "null"
            self.character = 0
        elif len(args) == 1:           
            if isinstance(args[0], str):
                self.name = args[0]
                self.character = 0
            else:
                self.name = "null"
                self.character = args[0]
        else:
            self.name, self.character = args
        
    def setName(self, name):
        self.name = name
    
    def getName(self):
        return self.name
        
    def setCharacter(self, character):
        self.character = character
        
    def getCharacter(self):
        return self.character
    
    def speak(self):
        print("嗨, 我叫" + self.name + ",人品值:" + str(self.character))
        
    def __str__(self):
        return "Person {name='" + self.name + "', character=" + str(self.character) + "}"    
        
    
if __name__ == '__main__':
    p1 = Person()   
    p1.speak()  
    
    p2 = Person("吴小雨")   
    p2.speak()
    
    p3 = Person(6)
    p3.speak()
    
    p4 = Person("王宏宇", 9)
    p4.speak()   

运行程序,结果如下:
在这里插入图片描述

2、课堂练习:给Dog类添加重载的构造方法

上一讲,我们创建狗类Dog:
在这里插入图片描述

  • 添加无参构造方法,调用之后会输出一句“无参构造方法被调用”
  • 添加有参构造方法,对name属性进行初始化
  • 添加有参构造方法,对name属性与age属性进行初始化
  • 创建测试类,分别利用三种构造方法初始化三个狗对象,然后调用eat()方法

(六)私有化构造方法案例演示

1、创建Manager类,私有化构造方法

在这里插入图片描述

3、创建Example1104类,测试Manager类是否能实例化

在这里插入图片描述
错误提示:‘Manager()’ has private access in ‘net.hw.lesson11.Manager’,也就是说构造方法是私有的,无法调用它来实例化对象。

一般来说,如果一个类提供了公共的构造方法,那么我们可以利用new关键字基于该类创建很多对象。现在我们既然已经私有化构造方法了,那么别人自然无法利用new来实例化对象,但是我们可以提供一个唯一的实例供外界使用,这就是大家常说的单例模式。

4、修改Manager类,提供获取实例的静态方法

在这里插入图片描述

5、修改Manager类,添加自我介绍方法speak()

在这里插入图片描述

6、修改Example1104,获取Manager实例,调用自我介绍方法

在这里插入图片描述
当然,可以重新设置对象的属性:
在这里插入图片描述

二、this关键字

1、为什么要使用this关键字

(1)假设场景

在本讲的Person类,使用变量表示姓名时,构造方法中使用的参数是a,成员变量使用的是name,虽然在语法上没有任何问题,但这样的程序可读性很差。
在这里插入图片描述

这时可以将Person类中表示姓名的变量进行统一命名,例如都声明为name,但是这样做又会导致成员变量和局部变量的名称冲突,在方法中将无法访问成员变量name。
在这里插入图片描述

(2)解决方案

为了解决这个问题,Java中提供了一个关键字this来指代当前对象,用于在方法中访问对象的其他成员。
在这里插入图片描述

2、this关键字三种常见用法

(1)通过this关键字调用成员变量,解决与局部变量名称冲突问题

public class Person {
    private String name; // 成员变量name
     
    public Person(String name) { // 局部变量name
        this.name = name; // 将局部变量name的值赋给成员变量name
    }
}

在上面的代码中,构造方法的参数被定义为name,它是一个局部变量,在类中还定义了一个成员变量,名称也是name。在构造方法中如果使用“name”,则是访问局部变量,但如果使用“this.name”则是访问成员变量。

(2)通过this关键字调用成员方法

public void tell() {                                  
    System.out.println("Hello,我叫" + name);            
}                                                     
                                                      
public void express() {                               
    this.tell();                                      
}                                                     

在express()方法代码里,使用this关键字调用了tell()方法。需要注意的是,此处的this关键字可以省略不写,也就是说上面的代码中,写成“this.tell()”和“tell()”效果是完全一样的。

(3)通过this关键字调用构造方法

在这里插入图片描述
在这里插入图片描述

package net.hw.lesson11;

/**
 * 功能:演示this调用构造方法
 * 作者:华卫
 * 日期:2020年4月30日
 */

class Student {
    private String name;
    private String gender;
    private int age;

    public Student() {
    }

    public Student(String name) {
        this();
        this.name = name;
    }

    public Student(String name, String gender) {
        this(name);
        this.gender = gender;
    }

    public Student(String name, String gender, int age) {
        this(name, gender);
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }   
    
    public void speak() {
        System.out.println("我叫" + name + "," + gender + ",今年" + age + "岁了。");
    }
}

public class Example1105 {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.speak();
        Student s2 = new Student("张三丰");
        s2.speak();
        Student s3 = new Student("张三丰", "男");
        s3.speak();
        Student s4 = new Student("张三丰", "男", 18);
        s4.speak();
    }
}

运行程序,查看结果:
在这里插入图片描述

三、课后作业

1、判断程序是否有错,如果没错,写出程序执行的结果

package net.hw.lesson11;

class Car {
    private String brand;
    private double price;

    public Car() {
    }

    public void Car(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

public class Exercise1101 {
    public static void main(String[] args) {
        Car  car1 = new Car();
        car1.setBrand("宝马");
        car1.setPrice(500000);
        System.out.println("car1 = " + car1);
        
        Car car2 = new Car("奔驰", 1000000);
        System.out.println("car2 = " + car2);
    }
}

2、给三角形类Triangle添加构造方法并测试

  • 添加无参构造方法 public Triangle() {}
  • 添加三参构造方法 public Triangle(double a, double b, double c) {}
  • 创建测试类TestTriangle,利用无参构造方法与三参构造方法创建三角形对象,设置对象属性,调用获取面积方法getArea(),输出两个三角形的面积

猜你喜欢

转载自blog.csdn.net/howard2005/article/details/105840278
今日推荐