文章目录[隐藏]
老师,你能预测题么?APCSA 考前一周复习要点(半成品)
我不能预测到原题,但是我可以预测到知识点。
必考点
基本算法
MCQ
FRQ
重要知识点
方法
方法的参数
按值传递
按引用传递
变量
静态变量
局部变量
实例变量
方法的重载
继承
默认构造方法
子类调用父类的构造方法
如何判断方法是否可以执行
二维数组
ArrayList
set 和 remove 的返回值
TIPS必考点
以下能力是必考的:
能够通过阅读方法头理解并正确使用方法的作用
在 FRQ 中往往提供了若干 help method,大家在做题的时候一定要认真阅读题干中的代码,注释不要跳过,尤其是 precondition 和 postcondition
大家要能够组合不同的方法,解决任务,这个就是计算思维了
原始类型和引用类型的区别(必考)
如果引用变量指向了新的地址则不能修改原来的地址
原始类型按照值(的副本)传递
引用类型按照地址的值(的副本)传递
static 变量
二维数组的遍历
结合 foreach 循环考察
数组索引越界的问题
for each 循环
for each 循环不能修改原始类型数组中的元素
for each 可以修改对象数组中的对象
toString
私有属性从 another class 或者 client class 是无法方法的
子类无法继承父类的 private 属性和构造方法
继承的选择题
必然考察用父类类型的引用变量指向子类类型的对象,然后问你哪个方法是可以执行的或者不可以执行的
ArrayList 的 set 和 remove 方法会返回被修改的值,这个是需要注意的
向 ArrayList 中插入元素的方法,按照数字的顺序或者按照自字符串的字典顺序
字符串的字典顺序用的是 compareTo 方法比较
字符串的比较用 equals 比较内容,== 比较的是对象的地址
注意 Array、2DArray、ArrayList 和 String 在长度访问元素、长度上的区别
递归的题目是必考的,注意用树状图来追踪循环的过程
先执行后递归
先递归后执行
注意比较一个变量是不是 null 必须用 == 或者 != ,不要用其他的符号
变量的区别及其作用范围
静态变量 static variable
局部变量 local variable
实例变量 instance variable
形式参数 parameter variable
for statement 中的变量这个题目答案是 E,变量 i 在for 循环结束后无法访问
基本算法
MCQ
MCQ 中会考察数组的 linear search、二分查找、统计元素的个数、求和、排序、最大或者最小值等算法。
排序会重点考察选择排序、冒泡排序和插入排序,考生必须对这些排序非常的熟悉。好在这三种排序算法基本上只在选择题中出现,因为 FRQ 主要考察对于面向编程的理解,对于算法不会考察。
如果大家对于这些代码非常的熟悉,在考试的时候就能够加快阅读代码的速度。
其余的可能会出现考察查找二维数组中最大或者最小元素的行索引或者列索引的选择题。
FRQ
FRQ 一般涉及到 count、查找、按照条件删除 ArrayList 中的元素、从 ArrayList 中删除元素,并且添加到新的列表中、检查某个元素在数组中是否存在。虽然不涉及到排序,但是要掌握按照顺序向 ArrayList 中插入元素。
注意第二问中 newRowIndex 的考察方式。
对于字符串的考察,难度最大的就是字符串的匹配算法,就是在一个字符串中查找另外一个字符串出现的次数。
重要知识点
方法
面向对象的核心是对象。不同的对象有不同的方法,不同的对象之间通过调用方法合作共同完成任务。
对象调用的基本语法是对象名.方法名称()。
要能够区分方法的返回类型(void 和不是 void 的方法);方法的形式参数(form parameter);调用方法的时候提供的实际参数。不然在 FRQ 中,告诉你需要什么参数,或者说某个方法需要 specific value 的时候,大概率其实就是参数来。
方法在选择题中是必考的,而且往往会考察参数的传递方式:按照值传递或者引用传递。
方法的参数
方法的参数是定义方法的时候,在方法名称后面括号中声明的变量。调用方法的时候,实际参数的值回传递给形式参数 form paremter。
按值传递
传递的是值的副本,就好比我给你发一份 PDF,你在 PDF 上的修改不会影响到我。
按引用传递
好像我给你发了共享文档的地址,你修改这个共享文档会影响到我。
)
changeIt() 方法的形式参数 arr 在方法中指向了新的数组,所以无法修改原来的数组;
value 是 primitive type 按照值传递,val 无法修改 value 的值;
String 类型的对象,可以理解为不可修改,因为 substring()方法总是返回全新的对象。
foreach 和引用传值
- foreach 中的循环变量 k,其实有点坑。k 依次指向 studetns 列表中的对象,所以可以直接调用方法,获取专业,major 是私有属性不可以直接方法 A C 都犯了这个错误
- D 把 K 当作了索引,数组、列表、字符串的索引都只能是证书
- E 选项,k 是调用方法的对象,不应该作为getAge()方法的参数
变量
静态变量
静态变量是在声明类的时候已经创建的变量。
在对象创建之前静态变量已经存在
对象初始化的时候不会重新初始化静态变量
静态变量对于所有对象来说都是相同的
静态方法也是在声明(定义)类的时候就创建了
静态方法的创建早于对象
静态方法不能调用 instance variable
静态方法不能调用 instance method
局部变量
参数变量和局部变量的作用范围仅限于方法内部,方法执行结束之后,局部变量和形式参数的值无法访问。
一般会在类中考察,在一个方法中使用了另外一个方法的形式参数或者局部变量,从而导致错误;或者问你方法执行后,方法局部变量的值,这个时候往往是不能访问的。
public void add(int a) { int c = a + 2;
} public void start() { int a = 3;
add(a); // value of c? }
上面的代码中,到第 9 行的位置,a 的值仍然是 3;c 的值因为add()方法执行结束后,局部变量 c 已经不存在了,所以在地第 9 行的位置无法访问变量 c 的值。
实例变量
实例变量在整个类的内部都可以访问。
在大题中,尤其是单独编写类的题目,往往会给你代码的实例,告诉你这个类怎么使用,调用的时候需要什么参数,返回什么类型的值。如果计算过程中需要用的值,不是构造方法的参数,也不是调用的方法的参数,大概率是需要声明为实例变量的。
比如 StepTracker 题目。
方法的重载
方法和构造方法的重载
方法形式参数的数量不同
String substring(int start, int end)和String substring(int from)
形式参数的数量相同,但是类型不一致
void println(int a)
void println(String a)
考察方式一般是问你哪个方法或者构造方法可以添加到类的定义不报错或者哪个添加进去会报错,会导致 comopile-error。
继承
考试中,2022 和 2016 年的题目都考察了重载父类的方法以及用 super 调用父类的构造方法。选择题一般会考察子类如何合理的调用父类的构造方法;选择合适的代码片段补全构造方法,使得程序可以达到预期的目标(注意不合适的代码片段从语法上可能是正确的)。
默认构造方法
如果没有定义构造方法,java 会为类生成一个没有参数的构造方法。
class A{}
尽管 A 类中没有定义构造方法,我们依然可以A a = new A()来创建对象,因为系统生成了默认的构造方法。
class A
{
public A(int a){}
}
如果我们定义了有一个参数的构造方法,那么A a = new A()则会报错:因为,A 中不存在没有参数的构造方法,解决方法如下:
- 使用正确的方式调用构造方法
- 重新定义没有参数的构造方法
子类调用父类的构造方法
如何判断方法是否可以执行
首先要区分两个重要的概念,对象的引用类型 reference type 和实际对象类型 object(actual) type。
class Animal { void run(){} void eat(){}
}
class Dog extends Animal { void bark(){}
}
class PetDog extends Dog { void greet(){}
}
class Tedi extends PetDog { void sun(){}
}
对于Animal pet = new PetDog()来说,变量 pet 的引用类型是 Animal 类,实际指向的是 PetDog 类型。那么能够通过 pet 调用greet()类型么,不可以,在 Animal 中并没有定义这个方法,所以不能调用,尽管在实际指向的 object type PetDog 确实定义了这个方法。
所以,如上图所以,判断一个方法能发执行,分为两个步骤:
首先判断引用变量的类型(引用类型)是否定义了这个方法(或者调用)
我们看引用类型是否有父类
如果父类中有这个方法,则说明用引用变量可以调用
如果没有定义这个方法,重复查找父类,如果最顶级父类中也没有这个方法,则说明不能通过这个引用变量执行这个方法
如果引用类型中没有定义这个方法
如果引用类型中定义这个方法说明可以执行
解决了能不能执行的问题,再判断实际执行的是哪个方法
如果定义了,则执行实际指向的对象中的方法
如果没有定义,看看有没有从其他父类中继承
如果引用类型和实际类型相同,则执行刚才查找的方法
如果不同,则看实际指向的对象中,有没有继承或者定义这个方法
class Animal{ void run(){} void eat(){}
} class Dog extends Animal{ void bark(){}
} class PetDog extends Dog{ void greet(){} void eat(){}
} class Tedi extends PetDog{ void sun(){}
}
比如下面的代码
Dog tedi = new Tedi();
tedi.eat();
首先,Dog 类中没有定义这个方法,然后我们看 Dog 类的父类 Animal 中有这个方法,所以可以通过 Dog 类型的引用变量 tedi 调用 eat();解决了能不能、行不行的问题之后,我们在看实际调用的是哪个方法。
因为 java 在执行过程中动态的判定实际指向对象,我们实际指向的是 Tedi 类,但是 Tedi 中没有 eat 方法,但是在 Tedi 的父类 PetDog 类中,有定义 eat() 方法,那么利用 tedi 这个引用变量访问的实际上在 PetDog 这个类中定义的 eat() 方法。
二维数组
二维数组四种最基本的遍历方式,这里容易出现的问题是把 foreach 循环的循环变量用作了索引。
另外两种方式是外层是 for 循环,内存 foreach;或者外层 foreach,内层 for 循环。
二维数组的 column 优先模式
image.png
二维数组和一维数组的转换
注意有的时候不是 row-major 的顺序,不是从左向右,从上到下的顺序。
注意读取二维数组的列
在 latin 方针和 lightboard 中需要用到统计二维数组中列的元素的数量
ArrayList
一道经典的题目
从 ArrayList 中筛选元素添加到 Array
单纯的 Array 和 ArrayList 的互相转换很容易;从 Array 中筛选元素添加到 ArrayList 中也很容易,因为列表可以动态添加元素;但是如果是从 ArrayList 中删除元素,添加到数组中,则需要先统计 ArrayList 中符合条件的元素的个数,然后创建数组,注意 index 变量的使用,因为是从 ArrayList 中筛选一部分添加到数组,索引是不完全一致的,所以我们用 index 额外表示符合条件的元素在 Array 中的索引。
set 和 remove 的返回值
set 返回修改之前的元素;remove 返回被删除的元素。
关于 ArrayList,这是一道非常经典的题目;需要注意的是,ArrayList 中的元素是可以动态增删的,删除之后,元素的索引会发生变化。这道题的答案就是,经过操作,ArrayList 恢复了原状。
TIPS
尽可能的使用中间变量保存方法调用的结果,减少书写量
对于 Array String list 务必标出索引
如果是有返回值的方法,正确的声明跟返回类型相同的变量,并且用了 return 返回,就可以混一分,所以代码能写尽量写,玩意得分呢?
for-each 与引用类型、参数传递组合考点
AP CSA 考点预测&梳理:ArrayList、二维数组和增强 for 循环的考察方法
AP CSA 考点预测&梳理:值的传递——primitive type 和 reference type
AP CSA FRQ class writing 复习题汇总(分类)由易到难
AP CSA 考点预测&梳理:ArrayList、二维数组和增强 for 循环的考察方法
AP 计算机科学 FRQ 中的 ArrayList