云计算百科
云计算领域专业知识百科平台

Java构造方法

1. 为什么需要构造方法

  • 代码冗余与遗漏风险:创建对象后,如果仅使用 setter 方法逐一初始化字段,需要编写多行代码,且容易遗漏调用某些 setter,导致对象状态不完整。

  • 构造方法的优势:构造方法允许在创建对象的瞬间完成所有必要字段的初始化,使代码更简洁,并强制提供完整初始状态,从而更安全。

  • 示例对比:

    • 使用 setter(易出错):Person ming = new Person();
      ming.setName("小明");
      ming.setAge(12); // 若忘记此调用,age 将保持默认值 0

    • 使用构造方法(推荐):Person ming = new Person("小明", 12); // 一行代码,强制完成初始化

    2. 什么是构造方法?

    构造方法是一种特殊方法,用来在创建对象时初始化对象字段。

    语法示例

    class Person {
    private String name;
    private int age;

    // 构造方法
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    public String getName() {
    return name;
    }

    public int getAge() {
    return age;
    }
    }

    调用

    public class Main {
    public static void main(String[] args) {
    Person p = new Person("小明", 15);
    System.out.println(p.getName()); // 小明
    System.out.println(p.getAge()); // 15
    }
    }

    3. 构造方法的特点

  • 方法名必须和类名完全相同:类叫 Person,构造方法也必须叫 Person。
  • 2.没有返回值类型
    普通方法可能写成

    public String getName()

    而构造方法不能写返回类型,例如 public Person(),不能写成 public void Person()。

    3.必须通过 new 调用
    构造方法不能像普通方法那样直接调用:

    p.Person("小明",15);//错误
    Person p = new Person("小明",15);//new调用,正确

    4.可以重载
    一个类可以有多个构造方法,参数列表不同。

    4. 默认构造方法

    如果一个类没有定义任何构造方法,编译器会自动生成一个无参构造方法。

    例如:

    class Person {
    private String name;
    private int age;
    }

    编译器会自动生成类似这样的构造方法:

    class Person {
    private String name;
    private int age;

    public Person() {
    // 空构造方法
    }
    }

    所以我们可以直接:

    Person p = new Person();

    重要规则
    一旦你自己定义了任意一个构造方法,编译器就不再自动生成默认无参构造方法。

    例如:

    class Person {
    private String name;
    private int age;

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

    这时再写:

    Person p = new Person(); // 编译错误!找不到无参构造方法

    因为编译器不再自动提供 Person()。

    如果既想要无参构造方法,又想要有参构造方法,必须手动把两个都写出来:

    class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    }

    5. 字段默认值

    如果构造方法没有给字段赋值,字段会使用默认值。

    类型 默认值
    byte / short / int / long 0
    float / double 0.0
    char '\\u0000'
    boolean false
    引用类型,例如 String null

    示例:

    public class Main {
    public static void main(String[] args) {
    Person p = new Person();
    System.out.println(p.getName());//null
    System.out.println(p.getAge());//0
    System.out.println(p.getVip());//false

    }
    }

    class Person {
    private String name;
    private int age;
    private boolean vip;

    public Person() {
    }
    public Person(String name, int age, boolean vip) {
    this.name = name;
    this.age = age;
    this.vip = vip;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public int getAge() {
    return age;
    }
    public boolean getVip() {
    return vip;
    }
    }

    6. 字段初始化器

    我们可以在声明字段时直接赋初值:

    class Person {
    private String name = "未命名";
    private int age = 10;
    }

    这样即使构造方法没有给字段赋值,字段也有默认的初始值。

    7. 构造方法重载

  • 重载:在同一个类中,允许定义多个构造方法,只要它们的参数列表不同(参数个数、类型或顺序不同)。

  • 重载的目的:提供多种创建对象的方式,让使用者可以根据实际情况灵活传参,而不必为每种情况写不同的方法名。

  • class Person {
    private String name;
    private int age;

    // 构造方法①:两个参数
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    // 构造方法②:一个参数(String)
    public Person(String name) {
    this.name = name;
    this.age = 18;
    }

    // 构造方法③:无参数
    public Person() {
    }
    }

  • 调用时,编译器会根据参数自动匹配:当你用 new 创建对象并传入实参时,编译器会根据实参的个数、类型和顺序,去匹配最合适的构造方法。
  • Person p1 = new Person("小明", 20); // 调用 Person(String, int)
    /*
    传入实参:"小明"(String)、20(int)
    匹配到构造方法① Person(String, int)
    执行:this.name = "小明",this.age = 20
    结果:p1 对象的 name = "小明",age = 20
    */

    Person p2 = new Person("小红"); // 调用 Person(String)
    Person p3 = new Person(); // 调用 Person()

  • 为什么要这样设计?
    • 提供灵活性:调用者可以只给名字(年龄自动成年),也可以给名字+年龄,甚至可以完全默认(比如用于后续 setter 赋值)。
    • 减少重复代码:如果没有重载,你可能需要写 setName()、setAge() 或者多个不同名的创建方法,而重载让 new 本身就完成了差异化初始化。
  • 8. 用 this(…) 调用其他构造方法

    一个构造方法可以调用另一个构造方法,语法是 this(参数…)。

    作用:复用初始化逻辑,避免重复代码。

    class Person {
    private String name;
    private int age;

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

    public Person(String name) {
    this(name, 18); // 调用 Person(String, int)
    }

    public Person() {
    this("未命名"); // 调用 Person(String)
    }
    }

    注意:this(…) 必须写在构造方法的第一行。

    错误写法:

    public Person() {
    System.out.println("初始化");
    this("未命名"); // 编译错误,this(…)必须放在第一行
    }

    9. 字段初始化与构造方法的执行顺序

    创建对象时,Java 按以下顺序初始化:

  • 先给字段分配默认值:例如 String name 先变成 null,int age 先变成 0。
  • 执行字段初始化器:例如:private String name = "未命名";
    private int age = 10;

    这时 name 变成 “未命名”,age 变成 10。

  • 执行构造方法体的代码:如果构造方法体中再次给字段赋值,会覆盖前面的值。
    1.先给字段分配默认值。
    例如 String name 先变成 null,int age 先变成 0。
  • 2.执行字段初始化器。
    例如:

    private String name = "未命名";
    private int age = 10;

    这时 name 变成 “未命名”,age 变成 10。

    执行构造方法体的代码。
    如果构造方法体中再次给字段赋值,会覆盖前面的值。

    示例

    class Person {
    private String name = "未命名";
    private int age = 10;

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

    执行:

    Person p = new Person("小明", 12);

    过程:

    name 初始为 null,age 初始为 0

    字段初始化器执行:name = “未命名”,age = 10

    构造方法体执行:name = “小明”,age = 12

    最终结果:

    java
    p.getName(); // 小明
    p.getAge(); // 12
    所以:字段初始化器先执行,构造方法体后执行,最终值由构造方法体决定。

    public class Main {
    public static void main(String[] args) {
    System.out.println(">>> 开始执行 new Person(\\"小明\\", 12) <<<");
    Person p = new Person("小明", 12);
    System.out.println(">>> new 操作执行完毕 <<<");
    p.show();

    }
    }

    class Person {

    // 1. 字段定义 + 字段初始化器 (带打印)
    private String name = "未命名";
    private int age = 10;

    // 2. 实例初始化块 (它在字段初始化器之后、构造方法体之前执行)
    {
    System.out.println("【步骤3】执行 实例初始化块 { } 内的代码");
    System.out.println(" 此时 name = " + name + ", age = " + age);
    // 假设这里偷偷改一下年龄,看看会不会被构造方法覆盖
    this.age = 99;
    System.out.println(" 初始化块执行完毕,age 被改为 99");
    }

    // 3. 构造方法体
    public Person(String name, int age) {
    System.out.println("【步骤4】进入 构造方法体 public Person(String name, int age)");
    System.out.println(" 执行构造方法前:this.name = " + this.name + ", this.age = " + this.age);

    this.name = name;
    this.age = age;

    System.out.println(" 执行构造方法后:this.name = " + this.name + ", this.age = " + this.age);
    }

    // 用来查看最终结果的普通方法
    public void show() {
    System.out.println("【最终对象结果】name = " + name + ", age = " + age);
    }
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Java构造方法
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!