Skip to content

Using Objects and Methods

AP Computer Science A Topic 1 15:05 English narration · English + 中文 subtitles burned in

space play · ←/→ 5s · j/l 10s · f fullscreen · ,/. speed

Chapters

Transcript
Here are two Java programs. 这里有两段 Java 程序。
The first is missing a semicolon. The second divides seven by two and stores the answer in a whole number. 第一段少了一个分号;第二段把七除以二, 并把结果存进一个整数变量里。
The compiler stops the first one dead — it will not even build. 编译器会当场拦下第一段——它根本编译不过。
The second compiles perfectly, runs perfectly, and gives you three. 而第二段编译完美、运行完美,然后给你三。
Not three point five. Three. 不是三点五,是三。
The compiler catches your typos. It cannot catch your mistakes. 编译器能抓住你的笔误,却抓不住你的错误。
That difference has a name, and it is where this course begins. 这个区别有个名字, 而这门课就从这里开始。
Welcome to Unit One. 欢迎来到第一单元。
We will build up from a single variable to a whole object: types, expressions, casting, methods, and the reference that makes objects behave the way they do. 我们将从一个变量出发,一路搭建到一个完整的对象: 数据类型、表达式、类型转换、方法,以及让对象呈现出那种行为的"引用"。
Let's begin. 让我们开始吧。
Before any line of Java, start with the idea. 在写任何一行代码之前,先抓住这个想法。
An algorithm is a finite, step-by-step procedure that solves a problem — finite means it ends, and step-by-step means every move is clear. 算法是解决一个问题的有限、逐步的过程—— 有限表示它会结束,逐步表示每一步都清楚。
A program is that algorithm written in a language a computer can run. 程序就是把那个算法写成计算机能运行的语言。
You write precise instructions, compile them, and run them. 你写出精确的指令,编译它们,再运行它们。
This unit is how those instructions are named, typed, combined, and handed off to methods and objects. 本单元就是这些指令如何被命名、定类型、组合,以及交给方法和对象。
Two ways to run source code sit side by side. 运行源代码有两种并排的方式。
A compiler translates the whole program at once into a form the machine can execute later. 编译器把整个程序一次翻译成机器以后能执行的形式。
An interpreter reads and runs the program line by line as it goes. 解释器则边读边运行,一行一行往下走。
Java is compiled: the compiler produces bytecode, then the virtual machine runs that bytecode. Java 是编译型的:编译器产出字节码, 再由虚拟机运行那些字节码。
That split is why one build can travel to many devices — the hard translation work is done up front, and each device only needs a virtual machine. 正因为有这个分工,一次构建能带到许多设备上—— 艰苦的翻译工作在前面做完,每台设备只需要有虚拟机。
The bytecode is run by the Java Virtual Machine, the J V M. 字节码由 Java 虚拟机,也就是 J V M,来运行。
Look closely at what the compiler translates your file INTO, because that is the part students get wrong. 仔细看看编译器把你的文件翻译成了什么,因为学生正是在这里出错。
Not machine code for your own laptop — bytecode, a portable half-way form that no processor runs directly. 它不是你自己笔记本电脑的机器码,而是字节码—— 一种可移植的中间形式,没有哪个处理器能直接运行它。
Only then does the Java Virtual Machine take over, turning that bytecode into instructions for whatever machine it happens to be running on. 之后才轮到 Java 虚拟机接手,把这些字节码变成 它当下所运行的那台机器的指令。
Write once, run anywhere is not a slogan; it is this two-stage split. "一次编写,到处运行"不是一句口号, 它就是这个两段式的划分。
Now the two error types, and you must be able to tell them apart. 现在说两类错误,你必须能把它们分开。
A syntax error breaks the language's grammar — a missing semicolon, an unclosed bracket — and the compiler refuses to build, so the program never runs at all. 语法错误违反了语言的语法规则——少一个分号、括号没闭合—— 编译器会拒绝构建,所以程序根本不会运行。
A logic error is grammatically perfect but wrong: it builds, it runs, and it quietly gives you the wrong answer. 逻辑错误在语法上完全正确,结果却是错的: 它能构建、能运行,然后悄悄给你一个错误的答案。
That is the dangerous one, because nothing complains. 那才是危险的一类,因为没有任何东西会报警。
Everything you store lives in a variable: a named box that holds one value of one fixed type. Java has three primitive types you must know for this course. 你存的每一样东西都放在变量里:一个有名字的盒子,装着一个固定类型的值。
An int holds whole numbers. A double holds decimals. A boolean holds only true or false. 这门课你必须掌握三种基本类型:int 存整数,double 存小数, boolean 只存 true 或 false。
And String, which is not a primitive at all, holds text. 还有 String,它根本不是基本类型,用来存文本。
You declare a variable by writing the type first, then the name, then the value. 声明变量时先写类型,再写名字,然后是值。
Once declared, that type never changes — try to put a decimal into an int and the compiler stops you. 一旦声明,类型就不再改变—— 想把小数放进 int,编译器会拦住你。
Expressions and output, next. 接下来是表达式与输出。
Expressions combine values with operators. Plus, minus, times and divide — and percent, which is the modulus: the remainder left after a division. 表达式用运算符把值组合起来:加、减、乘、除——还有百分号, 它表示取模,也就是相除之后剩下的余数。
Two rules matter enormously here. 这里有两条极其重要的规则。
First, precedence: times, divide and modulus all happen before plus and minus, exactly as in maths. 第一是优先级:乘、除、取模都先于加、减,和数学里完全一样。
Second, and this is the classic trap: when both sides of a division are integers, Java performs integer division and simply throws the remainder away. 第二,也是最经典的陷阱:当除号两边都是整数时,Java 执行整数除法, 直接把余数丢掉。
Seven divided by two is three. Seven modulus two is one. 七除以二等于三;七对二取模等于一。
And dividing an integer by zero does not give infinity — it crashes the program at run time. 而整数除以零不会得到无穷大——程序会在运行时崩溃。
To show a result you print. 要显示结果就打印。
System dot out dot print writes text and stays on the same line. System 点 out 点 print 写出文字并留在同一行。
System dot out dot println writes text and then moves to a new line. System 点 out 点 println 写出文字然后换到新行。
Inside a string, a backslash starts an escape sequence. 在字符串里面,反斜杠开始一段转义。
Backslash quote prints a double quote. 反斜杠加引号会打印一个双引号。
Backslash backslash prints a single backslash. 反斜杠再反斜杠会打印一个单独的反斜杠。
Backslash n starts a new line. 反斜杠 n 会换行。
Without those escapes, a quote would end the string too early and the program would not compile. 没有这些转义,引号会过早结束字符串,程序就编译不过。
Assignment statements and input. 赋值语句与输入。
Assignment is the equals sign used as a store command. 赋值就是把等于号当成「存进去」的命令。
The right side is evaluated first; then that result is placed into the variable on the left. 先计算右边,再把结果放进左边的变量。
So x equals expression means compute the expression, then put the answer in x. 所以「x 等于表达式」的意思是:先算出表达式,再把答案放进 x。
To read from the keyboard you use a Scanner. 要从键盘读入,就用 Scanner。
You build one with new Scanner of System dot in. 用 new Scanner 接 System 点 in 来创建它。
Then next int reads a whole number, and next reads a word of text into a String. 然后 next int 读一个整数,next 读一个单词放进 String。
Assignment and input are how values enter your program before any method does interesting work with them. 赋值和输入,就是在任何方法做更有意思的事之前,值怎样进入你的程序。
There is one more limit worth knowing. 还有一个值得知道的限制。
An int does not hold arbitrarily large numbers — it holds about plus or minus two point one billion. int 并不能存任意大的数—— 它的范围大约是正负二十一亿。
Push past that and Java does not raise an error; the value silently wraps around to a large negative number. 一旦超出,Java 不会报错; 数值会悄悄地绕回成一个很大的负数。
Watch it happen. 看它是怎么发生的。
That is overflow, and it is exactly why you reach for a long, or a double, once the values get big. 这就是溢出,也正是数值变大时你要改用 long 或 double 的原因。
Which brings us to casting: converting a value from one type to another. 这就说到了类型转换:把一个值从一种类型变成另一种。
Going from a smaller type to a larger one — int to double — is called widening, and Java does it automatically, because nothing can be lost. 从小类型转到大类型——比如 int 转 double——叫做拓宽, Java 会自动完成,因为不会丢失任何信息。
Going the other way is narrowing, and you must ask for it explicitly, by writing the target type in brackets. 反过来叫做收窄, 你必须用小括号写出目标类型来显式要求它。
Narrowing truncates: it chops the decimal part off rather than rounding, so casting three point nine to an int gives you three, not four. 收窄会截断: 它直接砍掉小数部分,而不是四舍五入,所以把三点九转成 int 得到的是三,不是四。
And here is the classic use: cast one operand to double to force real division instead of integer division. 而它最经典的用法是:把其中一个操作数转成 double, 以强制进行真正的除法,而不是整数除法。
Trace these carefully — the exam loves them. 仔细追踪这些——考试很爱考。
Seven divided by two is three, both ints, so division truncates. 七除以二是三,两边都是整数,所以除法截断。
Seven point zero divided by two is three point five, because one double forces real division. 七点零除以二是三点五,因为有一个小数会强制真正的除法。
Seven modulus two is one. 七对二取模是一。
Now the trap pair. 现在是那对陷阱。
Cast double of seven, then divide by two, is three point five — the cast binds tighter than divide. 把七转成小数再除以二,得到三点五——转换比除法绑得更紧。
But cast double of the whole group seven divided by two is three point zero — parentheses do integer division first, then widen. 但如果把整个「七除以二」再转成小数,得到的是三点零——括号先做整数除法再拓宽。
Same words, different parentheses, different answers. 同样的说法,括号不同,答案就不同。
Compound assignment operators come next. 接下来是复合赋值运算符。
Java gives you shorthand for updating a variable in place. Java 提供了原地更新变量的简写。
Plus-equals adds to it, minus-equals subtracts, times-equals multiplies, divide-equals divides, and percent-equals stores the remainder. 加等于就是加上去,减等于是减去, 乘等于是乘上,除等于是除以,取模等于则保存余数。
Each of these is exactly the long form, written shorter. 每一个都只是把完整写法写得更短而已。
And two more you will meet everywhere: plus-plus increments a variable by one, and minus-minus decrements it by one. 还有两个你到处都会见到的: 加加让变量自增一,减减让变量自减一。
You will read these constantly inside loops, so learn to recognise them at a glance. 你会在循环里不停地读到它们, 所以要练到一眼就认得。
An API — application programming interface — is the published list of classes and methods you may use. 应用程序接口是你可以使用的类与方法的公开清单。
A library is a collection of ready-made classes, like Math, String, and Scanner. 库是一套现成的类, 比如数学类、字符串类和输入扫描类。
You read the API documentation to learn what a method needs as parameters and what it returns, without seeing its inner code. 你读接口文档,就能知道方法需要什么参数、 返回什么,而不必看它的内部代码。
That is abstraction: you use the tool by its contract. 这就是抽象:你按约定使用工具。
On the exam, match the signature you are given; do not invent methods that are not in the API. 考试时要对齐题目给出的签名;不要发明接口里没有的方法。
Comments are ignored by the compiler but written for humans. 注释会被编译器忽略,却是写给人看的。
Two slashes start a single-line comment. 两个斜杠开始单行注释。
Slash star opens a block comment until star slash. 斜杠加星号打开块注释,直到星号加斜杠。
Slash star star opens a Javadoc comment that documents a method's purpose, parameters, and return value. 斜杠加两个星号打开文档注释, 用来说明方法的目的、参数和返回值。
Precise preconditions and postconditions live here: what must be true before the method runs, and what will be true when it finishes. 精确的前置条件和后置条件就写在这里: 方法运行前必须为真的事,以及结束后会为真的事。
Now, methods. 现在说方法。
A method's signature is its name plus the list of parameter types, in order — and that pair is what identifies it. 方法的签名是它的名字加上参数类型的有序列表—— 这两者合起来才能标识一个方法。
In front of the signature comes the return type: the kind of value the method hands back, or the word void if it hands back nothing at all. 签名前面是返回类型: 方法交回来的值是什么类型;如果什么都不返回,就写 void。
To call a method that belongs to a class, you write the class name, a dot, and the method name. To call one that belongs to an object, you write the object's name, a dot, and the method name. 要调用属于某个类的方法,就写类名、一个点、方法名; 要调用属于某个对象的方法,就写对象名、一个点、方法名。
That single dot is the whole idea: it means "go inside this thing and use what is there". 这一个点就是全部要义:它表示"进到这个东西里面,用里面的东西"。
When you call a method, arguments must match parameters in number, type, and order. 调用方法时,实参必须在数量、类型和顺序上匹配形参。
The full header also states the return type, but the return type is not part of the signature — two methods cannot differ by return type alone. 完整的方法头也会写返回类型,但返回类型不是签名的一部分—— 两个方法不能只靠返回类型不同来区分。
Class methods are static and are called on the class name. 类方法是静态的,在类名上调用。
Instance methods act on one object, so you call them on that object's reference. 实例方法作用在某个对象上,所以在那个对象的引用上调用。
The Math class is a toolbox you get for free, and its methods are static, which means you call them on the class itself, never on an object. Math 类是白送给你的工具箱,它的方法都是静态的, 也就是说你在类本身上调用它们,而不是在某个对象上。
Math dot abs gives the absolute value. Math dot pow raises a number to a power. Math dot sqrt takes the square root. Math 点 abs 求绝对值,Math 点 pow 求幂,Math 点 sqrt 求平方根。
And Math dot random gives you a double from zero up to, but never including, one. 而 Math 点 random 会给你一个从零开始、但取不到一的 double。
To turn that into a whole number in a range, multiply by the size of the range and cast the result to an int. 要把它变成某个范围内的整数,就乘以范围的大小,再把结果转成 int。
Object creation and storage — instantiation — is the last big idea. 对象的创建与存储,也就是实例化,是最后一个大概念。
Finally, objects — the heart of object-oriented programming. 最后说对象——这就是面向对象编程的核心。
A class is a blueprint; an object is one particular instance built from that blueprint. 类是蓝图,对象是照着这张蓝图造出来的 一个具体实例。
A class bundles data, the fields, with behavior, the methods. 类把数据(字段)和行为(方法)捆在一起。
Instantiation creates that object: the keyword new builds it, and calls the constructor. 实例化创建那个对象: 关键字 new 负责创建它,并调用构造方法。
Then here is the difference that trips absolutely everyone up. A primitive variable holds the value itself. An object variable holds a reference — the address of the object, not the object. 接下来是几乎所有人都会栽的那个区别: 基本类型的变量装的是值本身,而对象变量装的是引用——是对象的地址, 不是对象本身。
So assigning one object variable to another makes both of them point at the same object, and a change made through one name is visible through the other. 所以把一个对象变量赋给另一个,会让两者指向同一个对象, 通过其中一个名字做的修改,从另一个名字也看得见。
Strings are objects too, and they are immutable: every String method returns a brand-new String instead of changing the old one. String 也是对象,而且它是不可变的:每个 String 方法都会返回一个全新的 String,而不是修改原来的那个。
Classes can form a hierarchy. 类可以组成层次。
A superclass holds attributes and behaviors shared by several subclasses that extend it — that is an inheritance relationship. 父类保存若干子类通过继承共享的属性和行为——这就是继承关系。
Every class in Java is ultimately a subclass of the built-in Object class, which is why every object already has a to-string method. Java 里每个类最终都是内置根基类的子类,所以每个对象都已经有转成文字的方法。
Writing a subclass method with the same signature as a superclass one is method overriding. 在子类里写一个与父类签名相同的方法,就是方法重写。
You must recognise the words superclass, subclass, extend, override, and Object. 你必须认得这些词:父类、子类、继承、重写,以及根基类。
Watch assignment with objects. 看对象的赋值。
When you write one object variable equals another, Java copies the reference — the arrow — not a second copy of the object. 当你写一个对象变量等于另一个时,Java 复制的是引用——那支箭头—— 而不是对象的第二份拷贝。
After that, both names point at the same thing. 之后两个名字指向同一个东西。
Change the object through either name and the other name sees the change. 通过任一名字改对象,另一个名字也能看到变化。
That is the opposite of assigning a primitive, where the number itself is copied into a new box. 这和给基本类型赋值正好相反: 基本类型是把数字本身复制进一个新盒子。
A reference can also point to nothing. 引用也可以什么都不指向。
The special value null means not attached to any object. 特殊值 null 表示没有附着到任何对象。
Calling a method on a null reference crashes at run time with a null pointer exception. 在 null 引用上调用方法会在运行时崩溃,抛出空指针异常。
Guard against it by testing first: if the reference is not null, and only then call the method. 先测试再使用来防范:如果引用不是 null,才调用方法。
Write the null check on the left of and-and so short-circuit evaluation skips the method when the reference is null. 把 null 检查写在「并且」的左边,这样短路求值会在引用为 null 时跳过方法。
That pattern — check, then use — saves free-response points. 这个「先检查再用」的模式,能保住自由作答的分数。
String manipulation closes the unit. 字符串操作为本单元收尾。
Every string index starts at zero. 每个字符串的下标都从零开始。
Length returns how many characters there are. length 返回有多少个字符。
Substring from a to b includes index a and excludes b. 从 a 到 b 的 substring 包含下标 a,排除 b。
Index of finds the first position of a piece of text, or negative one if it is missing. index of 找到一段文字第一次出现的位置, 找不到就返回负一。
Equals compares content — never use double equals for string content. equals 比较内容——绝不要用双等号比较字符串内容。
Compare to returns less than zero, zero, or greater than zero by dictionary order. compare to 按字典序返回小于零、零或大于零。
A bad index throws a string index out of bounds exception at run time. 错误下标会在运行时抛出字符串下标越界异常。
Worked example. 例题。
Let s be C O M P U T E R — eight characters, indices zero through seven. 设 s 是八个字母 C O M P U T E R——下标从零到七。
Length is eight. 长度是八。
Substring from zero to four is C O M P — indices zero through three; four is excluded. 从零到四的 substring 是 C O M P——下标零到三;四被排除。
Substring from four alone is U T E R. 只写从四开始的 substring 是 U T E R。
Index of P U is three. P U 的 index of 是三。
Index of X is negative one. X 的 index of 是负一。
Counting the excluded endpoint of substring is the most common slip on this unit. 数清 substring 被排除的那一端,是本单元最常见的失误。
Three marks students throw away. 三个学生常丢的分。
First, integer division: if both operands are ints, the result is an int and the remainder is simply gone. 第一,整数除法:如果两个操作数都是 int, 结果就是 int,余数直接没了。
Cast one of them to double when you want the real answer. 想要真正的结果,就把其中一个转成 double。
Second, a cast truncates — it never rounds. 第二,类型转换是截断,绝不四舍五入。
Casting three point nine gives three. 把三点九转换后得到三。
Third, objects are handled by reference. 第三,对象是按引用处理的。
Assigning one object variable to another copies the reference, not the object, so afterwards both names refer to exactly the same thing. 把一个对象变量赋给另一个, 复制的是引用而不是对象,之后两个名字指的是同一个东西。
Name the run-time errors the exam expects. 说出考试期望的运行时错误名字。
Integer divided by integer zero throws an arithmetic exception. 整数除以整数零会抛出算术异常。
A method call on a null reference throws a null pointer exception. 在空引用上调用方法会抛出空指针异常。
A bad string index throws a string index out of bounds exception. 错误的字符串下标会抛出字符串下标越界异常。
Compile-time errors are syntax and type problems. 编译期错误是语法和类型问题。
Logic errors compile and run but print the wrong answer. 逻辑错误能编译能运行,但打印错误答案。
On free response, write complete compilable Java: match the method header, return the right type, and initialise every variable before you use it. 自由作答时要写完整可编译的代码:对齐方法头,返回正确类型,使用前初始化每个变量。
Trace code line by line in a table when asked. 题目要求追踪时,用表格一行一行跟。

Log in or create account

IGCSE, A-Level & AP