🎯 本章你会学到:字段、构造器、this、封装,以及 static 与实例成员的区别。建议边读边敲,每节练习先自己做,再展开答案对照。
Java 里一切都是对象(除了基本类型),而且对象**一定在堆上**,由垃圾回收负责回收——所以你永远不会写 delete,也不会遇到悬垂指针。
定义并使用一个类
类、构造器与封装
public class Main {
static class Student {
private final String name; // final:赋值后不能改
private int score;
Student(String name, int score) { // 构造器:名字与类名相同,没有返回类型
this.name = name; // this 区分同名的字段与参数
this.score = score;
}
String getName() { return name; }
int getScore() { return score; }
void addBonus(int delta) { this.score += delta; }
@Override
public String toString() { return name + ":" + score; }
}
public static void main(String[] args) {
Student s = new Student("Ann", 90);
s.addBonus(5);
System.out.println(s); // 自动调用 toString()
System.out.println(s.getName() + " " + s.getScore());
}
}运行结果
Ann:95
Ann 95
- 字段设为
private,通过方法访问:这样以后改内部实现不会影响调用方。 final修饰的字段只能在构造器里赋值一次,用来表达“创建后不再变”。- 重写
toString()之后,println(对象)才有可读输出,调试时非常有用。
static:属于类,而不是属于对象
static 计数
public class Main {
static class Counter {
static int created = 0; // 所有对象共用一份
Counter() {
created++;
}
}
public static void main(String[] args) {
new Counter();
new Counter();
new Counter();
System.out.println("created=" + Counter.created);
System.out.println("created=" + new Counter().created); // 也能通过对象访问,但不推荐
}
}运行结果
created=3
created=4
⚠️ 易错点 字段有默认值(int 是 0、boolean 是 false、对象是 null),但**局部变量必须显式初始化**,否则编译不过——这一点比 C 安全。
⚠️ 易错点 用
== 比较两个对象是在比较引用(是不是同一个对象)。要比较内容,要么用 equals,要么自己写 equals 与 hashCode。✍️ 本节练习
4.1必做矩形类
写一个 Rectangle 类(宽、高),提供 area() 和 perimeter() 方法;读入两个数输出面积与周长(2 位小数)。
输入 一行两个实数:宽 高。
输出 两行:area=、perimeter=(2 位小数)。
样例输入
3 4样例输出
area=12.00
perimeter=14.00💡 提示 构造器接收两个 double 存进字段;两个方法返回计算结果。
✅ 查看参考答案与解析
import java.util.Scanner;
public class Main {
static class Rectangle {
private final double width;
private final double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
double area() { return width * height; }
double perimeter() { return 2 * (width + height); }
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Rectangle r = new Rectangle(sc.nextDouble(), sc.nextDouble());
System.out.printf("area=%.2f%n", r.area());
System.out.printf("perimeter=%.2f%n", r.perimeter());
}
}解析 把数据(宽高)和行为(面积、周长)放在同一个类里,就是面向对象最基本的组织形式。
4.2挑战学生名单统计
定义 Student(姓名 + 分数),读入 n 个学生,输出平均分(2 位小数)和最高分学生的姓名。
输入 第一行 n;接下来 n 行「姓名 分数」。
输出 两行:avg=、top=。
样例输入
3
Ann 90
Bob 95
Cid 88样例输出
avg=91.00
top=Bob💡 提示 用对象数组存学生;一边读一边维护最高分(记住整个对象,最后取名字)。
✅ 查看参考答案与解析
import java.util.Scanner;
public class Main {
static class Student {
final String name;
final int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Student[] list = new Student[n];
long sum = 0;
Student top = null;
for (int i = 0; i < n; i++) {
list[i] = new Student(sc.next(), sc.nextInt());
sum += list[i].score;
if (top == null || list[i].score > top.score) {
top = list[i];
}
}
System.out.printf("avg=%.2f%n", sum / (double) n);
System.out.println("top=" + top.name);
}
}解析 Student[] list = new Student[n] 只是给引用开好位置,元素默认是 null,必须逐个 new。
📚 本文概念都在知识大全:
JVM 与字节码 · JDK · String 与 StringBuilder · 集合框架 · 泛型 · 受检异常 · 继承与接口 · record · Stream API