掌握构造函数的使用和重载,深入理解对象初始化过程
构造函数是Java中用于初始化对象的特殊方法。当创建类的实例时,构造函数会被自动调用,用于设置对象的初始状态。构造函数具有与类名相同的名称,且没有返回类型。
public class Student {
private String name;
// 默认构造函数
public Student() {
this.name = "Unknown";
}
}
public class Student {
private String name;
private int age;
// 参数化构造函数
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Student {
private String name;
private int age;
public Student() {
this("Unknown", 0);
}
public Student(String name) {
this(name, 0);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
构造函数链式调用是指在一个构造函数中调用同一个类的另一个构造函数。这种技术可以避免代码重复,提高代码的可维护性。
public class Rectangle {
private double width;
private double height;
private String color;
// 最完整的构造函数
public Rectangle(double width, double height, String color) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Width and height must be positive");
}
this.width = width;
this.height = height;
this.color = color != null ? color : "white";
}
// 调用完整构造函数,使用默认颜色
public Rectangle(double width, double height) {
this(width, height, "white");
}
// 创建正方形,调用两参数构造函数
public Rectangle(double side) {
this(side, side);
}
// 默认构造函数,创建单位正方形
public Rectangle() {
this(1.0);
}
}
在构造函数中进行参数验证是确保对象状态有效性的重要手段。通过验证输入参数,可以防止创建无效的对象实例。
public class BankAccount {
private String accountNumber;
private String ownerName;
private double balance;
public BankAccount(String accountNumber, String ownerName, double initialBalance) {
// 验证账号
if (accountNumber == null || accountNumber.trim().isEmpty()) {
throw new IllegalArgumentException("Account number cannot be null or empty");
}
if (!accountNumber.matches("\\d{10}")) {
throw new IllegalArgumentException("Account number must be 10 digits");
}
// 验证姓名
if (ownerName == null || ownerName.trim().isEmpty()) {
throw new IllegalArgumentException("Owner name cannot be null or empty");
}
if (ownerName.length() > 50) {
throw new IllegalArgumentException("Owner name cannot exceed 50 characters");
}
// 验证余额
if (initialBalance < 0) {
throw new IllegalArgumentException("Initial balance cannot be negative");
}
// 设置属性
this.accountNumber = accountNumber;
this.ownerName = ownerName.trim();
this.balance = initialBalance;
}
}
以下是一个综合运用构造函数各种特性的完整示例,展示了构造函数的定义、重载、链式调用和参数验证。
public class Person {
private String firstName;
private String lastName;
private int age;
private String email;
// 完整参数构造函数
public Person(String firstName, String lastName, int age, String email) {
validateName(firstName, "First name");
validateName(lastName, "Last name");
validateAge(age);
validateEmail(email);
this.firstName = firstName.trim();
this.lastName = lastName.trim();
this.age = age;
this.email = email.toLowerCase().trim();
}
// 三参数构造函数(无邮箱)
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, null);
}
// 两参数构造函数(默认年龄)
public Person(String firstName, String lastName) {
this(firstName, lastName, 0, null);
}
// 私有验证方法
private void validateName(String name, String fieldName) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException(fieldName + " cannot be null or empty");
}
if (name.length() > 30) {
throw new IllegalArgumentException(fieldName + " cannot exceed 30 characters");
}
}
private void validateAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Age must be between 0 and 150");
}
}
private void validateEmail(String email) {
if (email != null && !email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
throw new IllegalArgumentException("Invalid email format");
}
}
// Getter方法
public String getFullName() {
return firstName + " " + lastName;
}
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
public int getAge() { return age; }
public String getEmail() { return email; }
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, email='%s'}",
getFullName(), age, email != null ? email : "N/A");
}
}
// 参数验证
public Student(String name, int age) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
if (age < 0 || age > 120) {
throw new IllegalArgumentException("Invalid age");
}
this.name = name.trim();
this.age = age;
}
// 使用构造函数链式调用
public Student(String name) {
this(name, 18); // 默认年龄
}
// 防御性复制
public Student(List courses) {
this.courses = new ArrayList<>(courses);
}
// 不进行参数验证
public Student(String name, int age) {
this.name = name; // 可能为null
this.age = age; // 可能为负数
}
// 在构造函数中调用可重写方法
public Student(String name) {
this.name = name;
initialize(); // 危险!
}
// 构造函数过于复杂
public Student(String name, int age) {
// 大量复杂逻辑...
// 数据库操作...
// 网络请求...
}
当构造函数参数过多时,可以考虑使用Builder模式来替代多个重载的构造函数,提供更清晰和灵活的对象创建方式。
public class Computer {
private String cpu;
private String memory;
private String storage;
private String graphics;
// 私有构造函数
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.storage = builder.storage;
this.graphics = builder.graphics;
}
public static class Builder {
private String cpu;
private String memory;
private String storage;
private String graphics;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder graphics(String graphics) {
this.graphics = graphics;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用示例
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.memory("16GB")
.storage("512GB SSD")
.graphics("RTX 3080")
.build();