日期:2026-07-21
项目:c260721
作者:WanJL
文件:Demo01.java
在面向对象编程中,我们创建对象后通常通过 setter 方法为属性赋值。但有些属性(如性别 gender)是在对象创建时就已确定的,如果先创建对象再通过 setter 设置,虽然代码没有错误,但不符合现实逻辑。
// 传统方式:先造人,再取名、设性别
Person p = new Person();
p.setName("张三"); // 人出生后取名,符合逻辑
p.setGender("男"); // 人出生后再设置性别,代码没问题但不合常理
// 需求:在创建人的时候,就要给性别和年龄等属性赋值
结论:需要在创建对象的同时,为某些属性赋予初始值——这就用到了 构造方法(构造器)。
文件:Demo01.java
构造方法是一种特殊的方法,具有以下特点:
| 特点 | 说明 |
|---|---|
| 方法名 | 与类名完全一致(大小写也相同) |
| 返回值类型 | 没有返回值类型,连 void 都没有 |
| 返回值 | 不能使用 return 带回结果,因为直接返回新构造的对象 |
| 调用方式 | 创建对象时自动调用,不能手动调用 |
public class Person {
private String name;
private int age;
private String gender;
// 构造方法格式:访问权限修饰符 类名() { }
public Person() {
// 构造方法体
}
}
文件:Demo01.java
默认构造方法的访问权限修饰符与类的修饰符相同(类用 public,构造方法也是 public)
// 类默认自带的无参构造方法(隐藏):
// public Person() { }
注意:如果类的构造方法被设置为
private,外部就无法创建该类的对象了。
文件:Person.java
我们可以在无参构造方法中编写代码,在创建对象时自动执行。
public class Person {
private String name;
private int age;
private String gender;
// 无参构造方法:创建对象时自动执行
public Person() {
System.out.println("这是一个构造方法....我开始造人啦");
// 可以在构造方法中直接给属性赋固定值
this.gender = "男";
}
// getter/setter 省略...
}
测试类(PersonTest.java):
public class PersonTest {
public static void main(String[] args) {
// 创建对象时,自动调用并执行对应的构造方法
Person p = new Person(); // 输出:这是一个构造方法....我开始造人啦
System.out.println(p.getGender()); // 输出:男
}
}
文件:Person.java
构造方法可以像普通方法一样定义参数,多个同名构造方法只要参数列表不同(参数类型不同或参数个数不同),就称为 构造方法重载。
注意:如果参数类型相同、个数相同,仅参数名不同,不算重载。
public class Person {
private String name;
private int age;
private String gender;
// ① 无参构造方法
public Person() {
System.out.println("这是一个构造方法....我开始造人啦");
this.gender = "男";
}
// ② 单参数构造方法:仅设置性别
public Person(String gender) {
this.gender = gender;
}
// ③ 双参数构造方法:设置姓名和性别
public Person(String name, String gender) {
this.name = name;
this.gender = gender;
}
// ④ 三参数构造方法:设置姓名、年龄、性别
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
文件:PersonTest.java, StudentTest.java
创建对象时,根据传入的参数列表自动匹配对应的构造方法。
public class PersonTest {
public static void main(String[] args) {
// 调用无参构造方法
Person p = new Person();
System.out.println(p.getGender()); // 输出:男(在无参构造中写死的)
// 直接输出对象,得到地址
System.out.println(p); // course.Person@地址
System.out.println(new Person()); // course.Person@地址
// 调用有参构造方法:传入性别
Person p1 = new Person("女");
System.out.println(p1.getGender()); // 输出:女
}
}
public class StudentTest {
public static void main(String[] args) {
// 调用三参构造方法创建 Student 对象
Student s = new Student("张三", 25, "男");
}
}
| 序号 | 要点 | 说明 |
|---|---|---|
| 1 | 方法名必须与类名一致 | 大小写也必须相同 |
| 2 | 没有返回值类型 | 连 void 都不写 |
| 3 | 不能 return 返回值 |
直接返回新创建的对象 |
| 4 | 创建对象时自动调用 | 每创建一个对象,执行一次构造方法 |
| 5 | 不能手动调用 | 构造方法只能通过 new 关键字自动触发 |
| 6 | 默认构造方法 | 每个类默认有一个隐藏的无参构造方法 |
| 7 | 定义后覆盖默认 | 显式定义构造方法后,默认的会被覆盖 |
| 8 | 可重载 | 参数列表不同即可定义多个构造方法 |
| 9 | 权限修饰符与类一致 | 默认构造方法的权限与类的修饰符相同 |
| 10 | private 构造方法 |
可阻止外部创建对象 |
文件:Person.java
完整的 Person 类包含 3 个私有属性和 4 个重载的构造方法:
package course;
public class Person {
private String name;
private int age;
private String gender;
// 构造方法 —— 4 种重载形式
public Person() { // 无参
System.out.println("这是一个构造方法....我开始造人啦");
this.gender = "男";
}
public Person(String gender) { // 1 参:性别
this.gender = gender;
}
public Person(String name, String gender) { // 2 参:姓名 + 性别
this.name = name;
this.gender = gender;
}
public Person(String name, int age, String gender) { // 3 参:姓名 + 年龄 + 性别
this.name = name;
this.age = age;
this.gender = gender;
}
// getter / setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
}
文件:Student.java
如果将构造方法用 private 修饰,外部就无法创建该类的对象。这在设计模式中的 单例模式 中会用到。
public class Student {
// 私有构造方法:外部无法使用 new Student() 来创建对象
/*
private Student() {
System.out.println("构造学生对象....");
}
*/
private String name;
private int age;
private String gender;
// 公开的无参构造方法(注释掉私有构造后使用)
public Student() {
}
// 有参构造方法
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
文件:homework/c260717/Demo_08.java
使用 Fisher-Yates 洗牌算法 实现数组元素的随机打乱。核心思路:从后往前遍历,每次将当前元素与随机位置的元素交换。
package homework.c260717;
import java.util.Arrays;
import java.util.Random;
public class Demo_08 {
public static void shuffleArray(int[] arr) {
Random ran = new Random();
// Fisher-Yates 洗牌:从后往前遍历
for (int i = arr.length - 1; i > 1; i--) {
int j = ran.nextInt(i + 1); // 生成 [0, i] 的随机索引
int t = arr[i];
arr[i] = arr[j];
arr[j] = t; // 交换 arr[i] 和 arr[j]
}
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7};
System.out.println("打乱前:" + Arrays.toString(arr));
shuffleArray(arr);
System.out.println("打乱后:" + Arrays.toString(arr));
}
}
知识点:
Random.nextInt(n)生成[0, n)范围的随机整数;Fisher-Yates 算法确保每个排列等概率出现。
文件:homework/c260720/Emp.java
package homework.c260720;
public class Emp {
private String id;
private String name;
private double salary;
// getter/setter —— salary 的 setter 加入校验
public void setSalary(double salary) {
if (salary < 0) {
System.out.println("薪资不能为负数");
} else {
this.salary = salary;
}
}
public void work() {
System.out.println("工号" + id + "的员工" + name + "正在工作......");
}
}
测试类(EmpTest.java):
public class EmpTest {
public static void main(String[] args) {
Emp emp = new Emp();
emp.setId("a1001");
emp.setName("张三");
emp.setSalary(-10000); // 输出:薪资不能为负数
emp.work(); // 输出:工号a1001的员工张三正在工作......
}
}
文件:homework/c260720/MathTools.java
回文数判断算法:通过循环逐位取余、反序拼接,最后比较反序结果与原数是否相等。
public class MathTools {
/**
* 判断一个整数是否为回文数(正着读反着读一样)
*/
public boolean isPalindrome(int num) {
int a = num; // 保留原始值
int sum = 0;
while (num > 0) {
int b = num % 10; // 获取最后一位
sum = sum * 10 + b; // 拼接到反序结果
num /= 10; // 缩小 10 倍
}
return sum == a; // 比较反序结果与原值
}
}
测试用例:
12321→true(回文),12345→false,1221→true
文件:homework/c260720/Student.java
public class Student {
private String name;
private int age;
private String className;
// getter/setter 省略...
public void showInfo() {
System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
System.out.println("班级:" + this.className);
}
public void study(String course) {
System.out.println(this.name + "正在学习" + course);
}
}
测试类(StudentTest.java):
public class StudentTest {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三");
s.setAge(25);
s.setClassName("J260713");
s.showInfo();
s.study("Java");
}
}
以下练习基于本日所学构造方法知识点,请在
Demo01.java、Person.java等参考代码基础上完成。
基于已有的 Person 类,添加以下构造方法:
int age),将年龄赋值给成员变量参照 Student.java 中的 private 构造方法示例:
Dog 类,将无参构造设为 privatenew Dog(),观察编译错误public 的有参构造方法,测试是否能正常创建对象创建 Book 类,包含:
title,私有)、作者(author,私有)、价格(price,私有)showInfo() 输出图书信息创建 Calculator 类:
num1)、操作数2(num2)add() 返回两数之和、show() 输出两个操作数补全 MathTools 类中未实现的方法:
printPrime():输出 1~100 之间的所有质数,每行 5 个printSum(int n, int m):计算并输出 n~m 之间所有整数的累加和getLuckyNumber():使用 Random 生成 1~100 之间的幸运数字并返回补全 SortUtils 类中的 bubbleSort(int[] arr) 方法,实现冒泡排序算法。
| 序号 | 知识点 | 说明 | 对应文件 |
|---|---|---|---|
| 1 | 构造方法概念 | 创建对象时自动调用的特殊方法,用于初始化属性 | Demo01.java |
| 2 | 构造方法格式 | 方法名=类名,无返回值类型(无 void),无 return | Demo01.java |
| 3 | 默认构造方法 | 每个类默认有一个隐藏的无参构造方法,权限与类一致 | Demo01.java |
| 4 | 构造方法覆盖 | 显式定义构造方法后,默认构造方法被覆盖 | Demo01.java |
| 5 | 无参构造方法 | 无参数的构造方法,可执行初始化代码 | Person.java |
| 6 | 有参构造方法 | 可带参数的构造方法,通过参数为属性赋值 | Person.java |
| 7 | 构造方法重载 | 参数列表不同的多个同名构造方法 | Person.java |
| 8 | this 在构造方法中 |
区分同名的参数和成员变量 | Person.java |
| 9 | 构造方法调用 | 通过 new 类名(参数) 自动匹配并调用 |
PersonTest.java, StudentTest.java |
| 10 | private 构造方法 |
私有构造方法阻止外部创建对象 | Student.java |
| 11 | 输出对象地址 | 直接输出对象引用得到 包名.类名@哈希码 |
PersonTest.java |
| 12 | Fisher-Yates 洗牌 | 数组随机打乱算法(从后往前遍历 + 随机交换) | homework/c260717/Demo_08.java |
| 13 | setter 参数校验 | 在 setter 方法中加入业务规则校验 | homework/c260720/Emp.java |
| 14 | 回文数判断 | 逐位取余反序后与原数比较 | homework/c260720/MathTools.java |
this() 构造方法间调用:在一个构造方法中使用 this(参数) 调用另一个构造方法,必须写在第一行super() 与父类构造方法:子类构造方法中默认调用父类无参构造 super(),后续在继承中会深入学习