编写类 (Writing Classes) — AP Computer Science A CS A 学习指南
适合谁:AP Computer Science A 参加 AP Computer Science A 的考生。
覆盖内容:类结构(属性、构造器、方法)、静态与实例成员区别、private封装、方法重载、文档注释五大核心子主题。
前置知识:基础 Java 或任何其他过程式语言编程。
关于练习题:下文「练习题」一节的所有题目均为我们按 AP Computer Science A 风格编写的原创题目 (original problems),仅用于教学。它们不是 College Board 真题的复制,措辞、数值或语境可能不同。请把它们当作练手用;评分细则请对照 College Board 官方 mark scheme。
1. 什么是编写类?
编写类是Java面向对象编程的核心基础,类(Class)是创建对象的模板,封装了对象的属性和行为,所有Java程序的功能实现都离不开类的设计。该知识点对应AP CS A考纲Unit 5,占考试总分的10%-15%,自由问答题(FRQ)第一题几乎每年都会考察自定义类的编写,是必须掌握的核心考点。
2. 类的结构 (Class Anatomy):属性、构造器、方法
一个标准的Java类由三部分组成:
- 属性 (field):也叫实例变量,用来存储类的状态数据,一般是类的全局变量;
- 构造器 (constructor):用来初始化类的对象,名称必须和类名完全一致,没有返回值类型;
- 方法 (method):用来定义类的行为,实现具体功能。
代码范例:
// 定义学生类
public class Student {
// 属性:存储学生姓名和年龄
private String name;
private int age;
// 构造器:初始化学生对象
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 方法:定义学生的学习行为
public void study() {
System.out.println(name + " is studying for AP CS A");
}
}
3. 静态成员与实例成员 (Static vs Instance Members)
类的成员分为两类,核心区别是所属主体不同:
- 实例成员 (instance member):没有
static修饰,属于具体的对象,每个对象的实例成员独立存储,调用时必须通过对象名访问; - 静态成员 (static member):用
static修饰,属于类本身,所有该类的对象共享同一份静态成员,调用时可以直接通过类名访问。
考点提醒:静态方法中不能直接访问实例成员,因为静态成员在类加载时就已经初始化,而实例成员只有对象创建后才存在,考官经常在选择题中考察该规则的应用。
4. 用private实现封装 (Encapsulation with private)
封装 (encapsulation) 是面向对象的三大特性之一,核心逻辑是隐藏类的内部实现细节,只对外暴露必要的访问接口,避免外部随意修改内部数据导致逻辑错误。 实现封装的标准做法:
- 所有属性用
private修饰,禁止外部直接访问; - 提供
public的getter(读取属性)和setter(修改属性)方法,在方法中加入数据合法性校验。
范例:给Student类的age属性加校验,避免设置负数年龄:
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 0 && age < 120) { // 合法性校验
this.age = age;
}
}
如果直接把age设为public,外部可以直接赋值student.age = -10,会导致数据逻辑错误,考试中这种写法会直接扣分。
5. 方法重载 (Method Overloading)
方法重载是指在同一个类中,允许存在多个同名方法,只要它们的参数列表不同即可,参数列表不同指参数的个数、类型、顺序任意一项不同。 核心规则:方法重载和返回值类型无关,和参数名无关,只有参数列表的差异会被判定为合法重载。 考官常考的错误案例:
// 错误:只有返回值不同,不算重载,编译报错
public int add(int a, int b) {return a+b;}
public double add(int a, int b) {return a+b;}
// 错误:只有参数名不同,不算重载,编译报错
public int add(int x, int y) {return x+y;}
public int add(int a, int b) {return a+b;}
// 正确:参数个数不同,合法重载
public int add(int a, int b) {return a+b;}
public int add(int a, int b, int c) {return a+b+c;}
6. 文档与注释 (Documentation and comments)
Java支持三种注释写法,考纲要求掌握规范的注释写法,FRQ中注释清晰也会获得额外的分数:
- 单行注释:用
//开头,用来标注单行代码的逻辑,适合临时说明; - 多行注释:用
/* */包裹,用来标注多行代码的功能说明; - 文档注释:用
/** */包裹,用来生成Javadoc官方文档,一般写在类、构造器、方法的上方,支持@param(参数说明)、@return(返回值说明)、@author等标签。
文档注释范例:
/**
* 计算两个整数的和
* @param a 第一个加数
* @param b 第二个加数
* @return 两个数的和
*/
public int add(int a, int b) {
return a + b;
}
7. 常见陷阱 (Common Pitfalls)
- 错误做法:写了有参构造器之后,直接调用无参构造器实例化对象,编译报错。 原因:Java只会在你没有写任何构造器的时候自动提供无参构造器,一旦你写了有参构造器,默认无参构造器就会消失。 正确做法:需要用到无参构造器时手动编写。
- 错误做法:在静态方法中直接访问实例属性或调用实例方法,编译报错。 原因:静态成员加载时对象还没有创建,实例成员还不存在。 正确做法:静态方法只能访问静态成员,实例成员需要先创建对象再访问。
- 错误做法:修改方法返回值或参数名实现"重载",编译报错。 原因:方法重载只看参数列表的差异,和返回值、参数名无关。 正确做法:重载时必须修改参数的个数、类型或顺序。
- 错误做法:把属性设置为public,破坏封装。 原因:图省事不想写getter和setter,会导致外部可以随意修改属性值,出现逻辑错误。 正确做法:所有属性用private修饰,提供合法的getter和setter方法。
8. 练习题 (AP CS A 风格)
题1
题干:请找出以下Circle类中的3处错误并改正。
public class Circle {
private double radius;
public static int count = 0;
// 构造器
public void Circle(double r) {
radius = r;
count++;
}
// 静态方法获取圆的面积
public static double getArea() {
return Math.PI * radius * radius;
}
// 重载getArea方法
public int getArea(double r) {
return (int)(Math.PI * r * r);
}
}
解答:
- 构造器错误:构造器不能有返回值类型,把
public void Circle改成public Circle; - 静态方法访问实例成员错误:静态方法getArea不能直接访问实例变量radius,去掉getArea方法的static修饰符即可;
- 重载错误:两个getArea方法只有返回值和修饰符不同,参数列表相同,不是合法重载,修改第一个getArea方法的参数列表即可,或者修改第二个方法的名称。
题2
题干:编写一个Book类,满足以下要求:① 私有属性:书名title(String)、价格price(double);② 有参构造器初始化两个属性;③ 提供getter和setter方法,setPrice方法要求价格必须大于0才可以修改;④ 静态变量totalBook统计创建的Book对象总数。 解答:
public class Book {
private String title;
private double price;
public static int totalBook = 0;
public Book(String title, double price) {
this.title = title;
if(price > 0) {
this.price = price;
}
totalBook++;
}
public String getTitle() {return title;}
public void setTitle(String title) {this.title = title;}
public double getPrice() {return price;}
public void setPrice(double price) {
if(price > 0) {
this.price = price;
}
}
}
题3
题干:以下哪个是合法的方法重载?
A. public void f(int a) {} 和 public int f(int b) {}
B. public void f(int a) {} 和 public void f(double a) {}
C. public void f(int a) {} 和 public void f(int a, int b) {}
D. B和C都是
解答:正确答案是D。A选项只有参数名和返回值不同,不是合法重载;B选项参数类型不同,C选项参数个数不同,都是合法重载。
9. 速查表 (Quick Reference Cheatsheet)
| 知识点 | 核心规则 |
|---|---|
| 类结构 | 属性存状态,构造器初始化对象,方法定义行为,构造器名和类名一致且无返回值 |
| 静态vs实例成员 | 静态成员带static,属于类,所有对象共享,不能访问实例成员;实例成员属于单个对象,需通过对象调用 |
| 封装 | 属性用private修饰,提供public getter/setter,加入数据校验 |
| 方法重载 | 方法名相同,参数列表(个数/类型/顺序)不同,与返回值、参数名无关 |
| 注释 | 单行//,多行/* /,文档注释/* */配@param、@return等标签 |
| 公式 | 圆面积:,圆周长: |
10. 接下来怎么学
编写类是面向对象编程的基础,后续的继承、多态、对象数组/ArrayList存储等考点都要用到类的相关知识,FRQ第一题固定考察自定义类的编写,占10分左右,务必熟练掌握。 如果你在练习过程中遇到任何类相关的题目不会写,或者对知识点有疑问,都可以随时到小欧提问,我们会给你详细的解题思路和官方评分标准参考。