编程自学指南:java程序设计开发,Java 构造方法
一、课程信息
学习目标
- 理解构造方法的核心作用:对象初始化
- 掌握无参 / 有参构造方法的定义与使用
- 学会使用构造方法重载实现灵活初始化
- 理解构造方法执行顺序,避免常见错误
二、课程导入:对象的 "出生证明"
🌰 生活类比
- 对象创建:new 关键字相当于 "生产对象",构造方法相当于 "初始化生产线"
- 案例:创建一个 Student 对象时,构造方法负责给 name、age 等属性赋初始值
三、构造方法基础
🔨 1. 构造方法的定义
语法:
修饰符 类名(参数列表) {
// 初始化代码
}
特点:
✅ 名称必须与类名完全相同
✅ 没有返回值(连 void 都不能写)
✅ 主要用于初始化对象属性
🔍 2. 无参构造方法
作用:创建对象时执行默认初始化
案例:
📌 3. 默认构造方法
规则:
- 若类中没有显式定义任何构造方法,编译器会自动生成无参构造
- 若类中定义了有参构造,编译器不再自动生成无参构造
错误案例:
class Student {
public Student(String name) { // 定义有参构造
this.name = name;
}
}
// 错误:无法调用无参构造
Student stu = new Student(); // ❌ 编译错误
四、构造方法重载
🔧 1. 重载规则
- 参数列表不同(类型、顺序、数量)
- 与返回值、修饰符无关
案例:
class Book {
String title;
String author;
double price;
// 无参构造
public Book() {
title = "未命名";
author = "佚名";
price = 0.0;
}
// 有参构造(书名+作者)
public Book(String title, String author) {
this.title = title;
this.author = author;
price = 39.9; // 默认价格
}
// 全参构造
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
}
🔍 2. 构造方法间的调用(this ())
规则:
- 只能在构造方法中使用
this(参数列表)
- 必须位于构造方法的第一行
- 不能形成递归调用
案例:
class Employee {
String name;
int age;
double salary;
public Employee(String name, int age) {
this(name, age, 5000.0); // 调用全参构造
}
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
}
五、构造方法执行顺序
🔭 1. 单类构造顺序
执行顺序:
- 成员变量默认初始化(0/null/false)
- 显式初始化(声明时赋值)
- 构造方法中的初始化
案例:
class Test {
int num = 10; // 显式初始化
public Test() {
num = 20; // 构造方法初始化
}
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.num); // 输出20
}
}
🔗 2. 继承中的构造顺序
执行顺序:
- 父类静态变量 / 静态代码块(类加载时执行一次)
- 子类静态变量 / 静态代码块
- 父类成员变量初始化 + 父类构造方法
- 子类成员变量初始化 + 子类构造方法
案例:
class Parent {
{ System.out.println("父类普通代码块"); } // 普通代码块
static { System.out.println("父类静态代码块"); } // 静态代码块
public Parent() {
System.out.println("父类构造方法");
}
}
class Child extends Parent {
{ System.out.println("子类普通代码块"); }
static { System.out.println("子类静态代码块"); }
public Child() {
super(); // 隐式调用父类构造(第一行)
System.out.println("子类构造方法");
}
}
// 输出顺序:
// 父类静态代码块 → 子类静态代码块 → 父类普通代码块 →
// 父类构造方法 → 子类普通代码块 → 子类构造方法
六、构造方法最佳实践
✅ 1. 初始化逻辑集中
反模式:
class User {
String username;
int age;
public User() {
username = "user"; // 初始化代码
}
public User(String username) {
this.username = username; // 重复代码
}
}
优化:
public User() {
this("user"); // 调用有参构造
}
public User(String username) {
this.username = username;
age = 18; // 统一初始化age
}
⚠️ 2. 避免在构造方法中调用可重写方法
风险:子类重写的方法可能在父类构造时被调用,导致逻辑错误
案例:
class Animal {
public Animal() {
eat(); // 调用子类重写的方法
}
public void eat() {
System.out.println("动物进食");
}
}
class Cat extends Animal {
private String food = "鱼";
@Override
public void eat() {
System.out.println("猫吃" + food); // food此时为null
}
}
// 输出:猫吃null(因为food未初始化)
七、课堂练习
练习 1:完善学生类
需求:
- 包含 name、age、score 属性
- 提供无参构造(默认 name="张三",age=18,score=0)
- 提供有参构造(name+age),score 默认 60
- 提供全参构造
参考实现:
class Student {
String name;
int age;
int score;
public Student() {
this("张三", 18); // 调用双参构造
}
public Student(String name, int age) {
this(name, age, 60); // 调用全参构造
}
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
}
练习 2:修复构造方法错误
错误代码:
class Circle {
double radius;
final double PI = 3.14;
public Circle() {
radius = 1.0;
calculateArea(); // 调用方法
}
public double calculateArea() {
return PI * radius * radius; // radius可能未初始化
}
}
八、课程总结
知识图谱:
构造方法
↳ 作用:对象初始化,new关键字必调
↳ 分类:无参/有参,默认构造器规则
↳ 重载:参数列表不同,this()调用
↳ 顺序:父类→子类,静态→普通
口诀记忆:
“构造方法类同名,没有返回值类型,
无参有参可重载,this 调用放首行,
继承先调父构造,初始化顺序要记牢!”
九、课后作业
必做 1:实现员工工资计算
需求:
Employee
类包含 name、baseSalary(基本工资)、bonus(奖金)- 无参构造:name="员工",baseSalary=5000,bonus=0
- 有参构造:传入 name 和 baseSalary,bonus 默认 1000
- 提供
getTotalSalary()
方法计算总收入
必做 2:分析构造方法执行顺序
代码:
class A {
static { System.out.println("A静态块"); }
{ System.out.println("A普通块"); }
public A() { System.out.println("A构造"); }
}
class B extends A {
static { System.out.println("B静态块"); }
{ System.out.println("B普通块"); }
public B() {
super();
System.out.println("B构造");
}
}
// 问题:创建B对象时的输出顺序?