Java构造方法

构造方法的基本概念与作用

在Java面向对象编程中,构造方法(Constructor)是创建对象时必须调用的特殊方法,它负责对象的初始化工作。与普通方法相比,构造方法具有以下特点:

  • 构造方法的名称必须与类名完全相同
  • 构造方法没有返回值,也不能使用void声明
  • 构造方法可以重载(定义多个参数不同的构造方法)
  • 构造方法必须通过new操作符调用

为什么需要构造方法?

在没有构造方法的情况下,创建对象后需要单独调用setter方法初始化字段:

Person person = new Person();
person.setName("张三");
person.setAge(25);

这种方式存在两个问题:一是步骤繁琐,二是可能遗漏某些初始化步骤导致对象状态不正确。构造方法可以解决这些问题,在创建对象的同时完成初始化

// 使用构造方法创建并初始化对象
Person person = new Person("张三", 25);

构造方法的定义与使用

基本语法

public class 类名 {
// 字段定义
private 类型 字段1;
private 类型 字段2; // 构造方法
public 类名(参数1, 参数2, ...) {
// 初始化字段
this.字段1 = 参数1;
this.字段2 = 参数2;
// 其他初始化逻辑
}
}

示例:为Person类定义构造方法

public class Person {
private String name;
private int age; // 构造方法:初始化name和age字段
public Person(String name, int age) {
this.name = name;
this.age = age;
} // getter方法
public String getName() {
return name;
} public int getAge() {
return age;
} public static void main(String[] args) {
// 使用构造方法创建对象
Person person = new Person("张三", 25);
System.out.println("姓名:" + person.getName()); // 输出"张三"
System.out.println("年龄:" + person.getAge()); // 输出25
}
}

在这个例子中,Person类定义了一个接收nameage参数的构造方法,通过new Person("张三", 25)创建对象时,会自动调用该构造方法完成初始化。

注:虽然构造方法本身不写返回值,但 new 操作会返回对象引用。

默认构造方法

如果一个类没有显式定义任何构造方法,Java编译器会自动生成一个默认构造方法。默认构造方法没有参数,也没有任何执行语句:

public class Person {
private String name;
private int age; // 编译器自动生成的默认构造方法
public Person() {
// 空方法体
}
}

此时可以通过new Person()创建对象:

Person person = new Person(); // 调用默认构造方法

注意事项

  • 一旦显式定义了任何构造方法,编译器将不再生成默认构造方法
  • 如果需要同时支持无参数创建对象,必须显式定义无参数构造方法
public class Person {
private String name;
private int age; // 显式定义有参数构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
} // 显式定义无参数构造方法
public Person() {
// 可以在这里设置默认值
this.name = "未知姓名";
this.age = 0;
}
}

构造方法的重载

与普通方法一样,构造方法也支持重载(Overload),即一个类可以定义多个构造方法,只要它们的参数列表(参数数量、类型或顺序)不同。

示例:重载构造方法

public class Person {
private String name;
private int age; // 构造方法1:无参数
public Person() {
this.name = "未知姓名";
this.age = 0;
} // 构造方法2:仅初始化name
public Person(String name) {
this.name = name;
this.age = 0; // 默认年龄为0
} // 构造方法3:初始化name和age
public Person(String name, int age) {
this.name = name;
this.age = age;
} // getter方法省略...
}

创建对象时,编译器会根据传入的参数自动匹配对应的构造方法:

Person p1 = new Person();                  // 调用无参数构造方法
Person p2 = new Person("李四"); // 调用Person(String)构造方法
Person p3 = new Person("王五", 30); // 调用Person(String, int)构造方法

构造方法的相互调用

为了避免代码重复,一个构造方法可以通过this(参数)调用另一个构造方法,这种方式称为构造方法的链式调用

示例:构造方法间的调用

public class Person {
private String name;
private int age; // 完整参数的构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
} // 仅name参数的构造方法,调用完整参数构造方法
public Person(String name) {
this(name, 18); // 调用Person(String, int),默认年龄18
} // 无参数构造方法,调用单参数构造方法
public Person() {
this("未知姓名"); // 调用Person(String)
}
}

这种设计的好处是:

  • 减少代码重复,提高维护性
  • 确保初始化逻辑的一致性
  • 新增初始化步骤时只需修改一个构造方法

注意:this(...)必须是构造方法的第一条语句,否则会编译错误。

对象初始化顺序

当创建对象时,Java会按照特定的顺序进行初始化:

  1. 初始化字段的默认值或显式赋值(字段定义时的初始化)
  2. 执行构造方法中的代码

示例:初始化顺序演示

public class Person {
// 字段显式初始化
private String name = "初始化值";
private int age = 10; public Person(String name, int age) {
this.name = name;
this.age = age;
} public static void main(String[] args) {
Person person = new Person("张三", 25);
System.out.println(person.name); // 输出"张三"(构造方法覆盖了初始值)
System.out.println(person.age); // 输出25(构造方法覆盖了初始值)
}
}

在这个例子中:

  • 字段首先被初始化为name="初始化值"age=10
  • 然后执行构造方法,将name改为"张三",age改为25
  • 最终对象的字段值由构造方法确定

注意事项

  1. 参数验证:在构造方法中可以对参数进行合法性检查,避免创建无效对象
public Person(String name, int age) {
// 验证参数
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("姓名不能为空");
}
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄必须在0-150之间");
}
this.name = name;
this.age = age;
}
  1. 提供必要的构造方法重载:根据使用场景提供不同参数组合的构造方法,但不宜过多

  2. 使用构造方法链:通过this(...)调用减少代码重复

综合示例:构造方法的实际应用

import java.time.LocalDate;

public class Student {
private String id; // 学号(必填)
private String name; // 姓名(必填)
private int grade; // 年级(可选,默认1)
private LocalDate enrollDate; // 入学日期(可选,默认当前日期) // 完整参数构造方法
public Student(String id, String name, int grade, LocalDate enrollDate) {
// 参数验证
if (id == null || id.isBlank()) {
throw new IllegalArgumentException("学号不能为空");
}
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("姓名不能为空");
}
if (grade < 1 || grade > 12) {
throw new IllegalArgumentException("年级必须在1-12之间");
} this.id = id;
this.name = name;
this.grade = grade;
this.enrollDate = enrollDate;
} // 省略入学日期的构造方法
public Student(String id, String name, int grade) {
this(id, name, grade, LocalDate.now()); // 调用完整构造方法,默认当前日期
} // 省略年级和入学日期的构造方法
public Student(String id, String name) {
this(id, name, 1); // 调用上一个构造方法,默认1年级
} // getter方法
public String getId() { return id; }
public String getName() { return name; }
public int getGrade() { return grade; }
public LocalDate getEnrollDate() { return enrollDate; } public static void main(String[] args) {
Student s1 = new Student("S001", "张三", 3);
System.out.println(s1.getName() + "," + s1.getGrade() + "年级"); Student s2 = new Student("S002", "李四");
System.out.println(s2.getName() + "," + s2.getGrade() + "年级");
}
}

总结

  • 掌握构造方法的使用,构造方法用于在创建对象时初始化字段:

    • 名称与类名相同无返回值
    • 未显式定义构造方法时,编译器会生成默认无参数构造方法
    • 构造方法可以重载,通过参数列表区分不同的构造方法
  • 了解即可:
    • 构造方法之间可以通过this(...)相互调用,减少代码重复
    • 对象初始化顺序:先初始化字段,再执行构造方法

Java面向对象基础——2.构造方法的更多相关文章

  1. 085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用

    085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用 本文知识点:构造方法调用 说明:因为时间紧张,本人写博客过程中只是 ...

  2. 084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字

    084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字 本文知识点:构造方法-this关键字 说明:因为时间紧 ...

  3. 083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法

    083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法 本文知识点:构造方法-带参构造方法 说明:因为时间紧张, ...

  4. 082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法

    082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法 本文知识点:构造方法-无参构造方法 说明:因为时间紧张, ...

  5. 【重走Android之路】【Java面向对象基础(三)】面向对象思想

    [重走Android之路][基础篇(三)][Java面向对象基础]面向对象思想   1 面向对象的WWH   1.1 What--什么是面向对象         首先,要理解“对象”.在Thinkin ...

  6. 【重走Android之路】【Java面向对象基础(一)】数据类型与运算符

    [重走Android之路][基础篇(一)][Java面向对象基础]数据类型与运算符   1.数据类型介绍 在Java中,数据类型分为两种:基本数据类型和引用类型. 基本数据类型共8种,见下表: 基本数 ...

  7. 086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结

    086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结 本文知识点:面向对象基础(类和对象)总结 说明 ...

  8. 【重走Android之路】【Java面向对象基础(二)】细说String、StringBuffer和StringBuilder

    [重走Android之路][基础篇(二)][Java面向对象基础]细说String.StringBuffer和StringBuilder   1.String String是Java中的一个final ...

  9. 081 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 06 new关键字

    081 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 06 new关键字 本文知识点:new关键字 说明:因为时间紧张,本人写博客过程中只是 ...

  10. 080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则

    080 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 05 单一职责原则 本文知识点:单一职责原则 说明:因为时间紧张,本人写博客过程中只是 ...

随机推荐

  1. Redis实战-缓存穿透、缓存雪崩、缓存击穿和缓存并发的区别和解决方案

    正常处理流程   客户端请求正常的时候,先读缓存,如果数据命中,则返回缓存的值:否则,把从存储层中读取出来的数据缓存至缓存,同时返回客户端.但是,为了保证系统高可用和高性能,设计一个缓存系统时必须考虑 ...

  2. IIS设置发布公告页面

    IIS原有站点停用 IIS新增里新增一个站点,端口及域名和原有站点一致 新增公告提示页面,如:index.html 新增web.config文件,并设置web.config 1 <system. ...

  3. Astah Community安装教程及使用说明(包括括菜单命令解释、操作向导说明、快捷命令说明)

    一.安装教程: 1.双击下载好的文件,允许安装(现在官网已经停刊免费的社区版了,如果想要下载社区版需要从其他地方寻找资源) 2.选择安装的语言,English,点击OK 3.next,接受协议,nex ...

  4. .net入行第4年

    没错 我在2024-06-28发布了我的三年.net感想 时隔一年,我又来分享了 这一年的时间真的没有经过逛博客园 ,每天都在忙 首先,恭喜一下自己 -- 我现在也算是一个小老板了(虽然主业还是程序员 ...

  5. 直击运维痛点,大数据计算引擎 EasyMR 的监控告警设计优化之路

    当企业的业务发展到一定的阶段时,在系统中引入监控告警系统来对系统/业务进行监控是必备的流程.没有监控或者没有一个好的监控,会导致开发人员无法快速判断系统是否健康:告警的实质则是"把人当服务用 ...

  6. 袋鼠云数栈基于CBO在Spark SQL优化上的探索

    原文链接:袋鼠云数栈基于CBO在Spark SQL优化上的探索 一.Spark SQL CBO选型背景 Spark SQL的优化器有两种优化方式:一种是基于规则的优化方式(Rule-Based Opt ...

  7. kubernetes源码解析

    下载并且编译 git clone https://github.com/kubernetes/kubernetes.git cd kubernetes make cd _output 查看编译产物

  8. C#.Net筑基-泛型T & 协变逆变

    01.什么是泛型? 泛型(Generics)是C#中的一种强大的强类型扩展机制,在申明时用"占位符"类型参数"T"定义一个"模板类型",比较 ...

  9. JavaScript中如何遍历对象?

    JavaScript中如何遍历对象? 今天来点稍微轻松的话题,如何在JavaScript中遍历对象,在平常的工作中,遍历对象是很常见的操作,javascript提供了多种方法来遍历对象的属性.这些方法 ...

  10. java--xml约束、tomcat服务器

    xml约束 XML语法: 规范的xml文件的基本编写规则.(由w3c组织制定的) XML约束: 规范XML文件数据内容格式的编写规则.(由开发者自行定义) DTD约束 DTD约束:语法相对简单,功能也 ...