Scroll to turn the page
Computer Science A · AP Computer Science A
values, references and the methods that use them
A variable is a named box in memory. A primitive variable holds its value; a reference variable holds the location of an object.
int score = 42; int copy = score; // copy gets its own 42 copy = 7; // score is still 42 String name = "Ada"; // a reference String other = name; // the same reference
The figure runs these lines. copy = score copies the value 42 into a second box, so when copy becomes 7, score is untouched. name holds no characters at all: its box holds an arrow (red) to a String object made elsewhere in memory. other = name copies the arrow, not the object: two arrows, one object.
That difference runs through all of Java, and through this chapter: what a variable holds, what a method is given and gives back, what new makes, and why a String never changes once it exists.
This chapter is AP Computer Science A Unit 1, Using Objects and Methods, 15–25% of the multiple-choice score: compiling and errors (1.1), types, expressions and assignment (1.2–1.6), libraries, documentation and methods (1.7–1.11), objects and their creation (1.12–1.14) and Strings (1.15). The exam’s 42 multiple-choice questions come with the Java Quick Reference, which lists every library method it may use; its first free-response question calls String methods.
and the three kinds of error
An algorithm is a step-by-step process for completing a task or solving a problem. It can be written in words, drawn as a diagram, or written as a program.
Sequencing puts the steps in order, and they run one at a time: a Java method runs its statements from top to bottom unless something changes the flow.
Code can be written in any text editor, but most programmers use an integrated development environment (IDE), which has tools to write, compile and run it. The compiler checks the source for some errors and translates it; Java’s compiler makes bytecode, which the Java Virtual Machine (JVM) runs. Errors the compiler finds must be fixed before the program can run at all.
The figure sends three programs down the line, each with one kind of error.
int total = 7 + 3 // missing ; System.out.println(total); A syntax error breaks the rules of the language. The compiler finds it (error: ';' expected) and nothing runs.
int count = 0; System.out.println(10 / count);
A run-time error happens while the program runs, and typically ends it abnormally. This one is an exception: an error the compiler did not detect, which interrupts the normal flow of execution (ArithmeticException: / by zero).
double avg = (7 + 8) / 2; System.out.println(avg); // prints 7.0 A logic error compiles and runs, but behaves incorrectly: the average of 7 and 8 should be 7.5. Only testing with specific data, and comparing with the expected outcome, finds it. (Why it prints 7.0: page 1.3.)
int, double, boolean, and references
A data type is a set of values and the operations on them. Every type is either primitive or a reference type.
The course uses three primitive types, for numbers and Boolean values:
| type | values | examples |
|---|---|---|
int | integers | 7, -40, 0 |
double | real numbers | 2.5, 7.0, -0.01 |
boolean | true or false | true |
Java has five other primitive types (long, short, byte, float, char); they are outside the course and exam. Anything that is not a primitive, such as a String, is an object, and its type is a reference type.
A variable is a storage location that holds a value, which can change while the program runs. Every variable has a name and a type, and a variable of a primitive type holds a value of that type.
int n = 7; double d = 2.5; boolean ok = true; double w = 7; // stores 7.0 int m = 2.5; // does not compile
An int fits in a double: double w = 7; stores 7.0. A double does not fit in an int, so int m = 2.5; is a compile error: incompatible types: possible lossy conversion from double to int.
Choose the type from what the value can be: a count of students is an int, a price or an average a double, whether a light is on a boolean.
print, println and escape sequences
System.out.print and System.out.println display information on the screen. println then moves the cursor to a new line; print leaves it where it is.
A literal is the code representation of a fixed value: 7, 2.5, true. A string literal is a sequence of characters in double quotes: "CSA".
Some characters cannot be typed inside the quotes directly. An escape sequence starts with a backslash and has a special meaning. The course uses three:
| escape sequence | means |
|---|---|
\" | a double quote |
\\ | a backslash |
\n | a newline |
System.out.print("AP "); System.out.println("CSA"); System.out.println("say \"hi\""); System.out.print("a\\b\nc"); The console then shows (the figure types it out):
AP CSA say "hi" a\b c The first print leaves the cursor after AP , so CSA lands on the same line. In the last line, \\ prints one backslash and \n starts a new line in the middle of the string.
int division, remainder and precedence
An arithmetic expression combines numeric values, variables and the operators +, -, *, / and %. Two int values give an int; at least one double gives a double.
System.out.println(17 / 5); // 3 System.out.println(17 % 5); // 2 System.out.println(17.0 / 5); // 3.4
Dividing two ints keeps only the integer part of the quotient: 17 blocks make 3 full groups of 5. The remainder operator % gives what is left over: 2. With a double in the division, the result is the quotient itself, 3.4. (The course uses % only with a ≥ 0 and b > 0.)
Precedence: *, / and % are applied before + and -; operators of equal precedence go left to right; parentheses change the grouping. The compiler groups the values with their operators this way at compile time.
| expression | value |
|---|---|
2 + 3 * 4 | 14 |
(2 + 3) * 4 | 20 |
10 - 4 - 3 | 3 |
7 + 9 % 4 | 8 |
1 / 2 * 4.0 | 0.0 |
1.0 / 2 * 4 | 2.0 |
In 1 / 2 * 4.0, 1 / 2 is int division and is already 0 before the double appears.
Dividing an int by the int zero throws an ArithmeticException when the line runs. (Dividing by zero with a double, and the special double values it makes, are outside the course.)
the right side, stored on the left
The assignment operator = evaluates the expression on its right to a single value and stores it in the variable on its left.
A variable must be given a value before it is used in an expression, and the value must be of a compatible type. The first assignment initializes it. Each later one replaces the value: the old one is gone.
int a = 3; // a 3 int b = 8; // a 3, b 8 int temp = a; // a 3, b 8, temp 3 a = b; // a 8, b 8, temp 3 b = temp; // a 8, b 3, temp 3
That is why swapping two variables takes a third. Without temp, a = b would destroy a’s 3 before b could get it. The figure moves each copy from box to box: the source keeps its value.
When the program runs, an expression is evaluated to one value, and that value has a type: a + b is an int, a + 0.5 a double. A statement like count = count + 1 is not an equation; it reads count, adds 1, and stores the result back.
A reference variable can be assigned a new object or null. The literal null means the reference is not associated with any object.
Assignments inside expressions, such as a = b = 4;, are outside the course.
Input can be tactile, audio, visual or text. The Scanner class is one way to read text typed at the keyboard; the exam does not test any specific form of user input.
truncating, widening and rounding
The casting operators (int) and (double) convert a value from one primitive type to the other.
Casting a double to an int truncates: the digits after the decimal point are cut off, so the value moves toward zero, whatever its sign.
| expression | value |
|---|---|
(int) 3.99 | 3 |
(int) -3.99 | -3 |
7 / 2 | 3 |
(double) 7 / 2 | 3.5 |
(double) (7 / 2) | 3.0 |
7 / 2.0 | 3.5 |
1 + 2.5 | 3.5 |
A cast applies to the value right after it. (double) 7 / 2 casts 7, then divides as doubles; (double) (7 / 2) does the int division first and casts its result, 3.0.
Some code widens an int to a double automatically: in 1 + 2.5, and when an int is stored in a double variable (page 1.2).
To round a double to the nearest integer, shift it half a unit away from zero and then truncate: (int) (x + 0.5) for non-negative x, (int) (x - 0.5) for negative x.
| x | (int) x | rounded |
|---|---|---|
2.7 | 2 | 3 |
-2.7 | -2 | -3 |
3.2 | 3 | 3 |
-1.4 | -1 | -1 |
The figure casts each of these: red truncates toward zero; blue shifts by a half, then truncates.
integer overflow and round-off error
An int is stored in a fixed amount of memory, 4 bytes, so it has a range: from Integer.MIN_VALUE to Integer.MAX_VALUE, inclusive.
| constant | value |
|---|---|
Integer.MAX_VALUE | 2147483647 |
Integer.MIN_VALUE | -2147483648 |
int n = Integer.MAX_VALUE - 2; // n is 2147483645 n = n + 1; // n is 2147483646 n = n + 1; // n is 2147483647 n = n + 1; // n is -2147483648 n = n + 1; // n is -2147483647
If an expression would evaluate to an int outside the range, an integer overflow occurs. The result is an int inside the range, but not the value expected: one past MAX_VALUE is MIN_VALUE. The figure draws the ints as a ring (not to scale) with the seam at the top. There is no error message; the program carries on with the wrong number.
Doubles have a different limit. A double is stored in a fixed amount of memory too, so a result more precise than it can hold is rounded to the nearest value it can represent: a round-off error.
System.out.println(0.1 + 0.2); // 0.30000000000000004 Neither 0.1 nor 0.2 has an exact binary form, and the small errors show in the sum. To avoid round-off error, use int values where you can: count money in cents, not dollars. (Special decimal types that avoid it are outside the course.)
+=, −=, *=, /=, %=, ++ and −−
A compound assignment operator does the arithmetic between the variable’s value and the value on the right, then assigns the result to the variable.
score += 5 does what score = score + 5 does. The same holds for -=, *=, /= and %=; /= on an int is int division.
The post-increment operator ++ adds 1 to a numeric variable and stores it; the post-decrement operator -- subtracts 1.
int score = 10; // score is 10 score += 5; // score is 15 score -= 3; // score is 12 score *= 2; // score is 24 score /= 5; // score is 4 score %= 3; // score is 1 score++; // score is 2 score--; // score is 1
The figure runs the lines and keeps each value on a tape. Trace on paper the same way: one line, one new value.
The prefix forms (++x) and increments inside other expressions (arr[x++]) are outside the course.
using classes you did not write
A library is a collection of classes. An application programming interface (API) specification tells a programmer how to use them.
A class defines a reference type. Library classes are grouped into packages: String and Math are in java.lang, Scanner and ArrayList in java.util. Existing classes can be used to create objects without seeing their code; their documentation is what makes them usable.
A class’s attributes are the data related to it, stored in variables: a String’s characters. Its behaviors are what its instances can do, or what can be done with them, and are defined by methods: length(), substring.
Comments explain code to the original programmer and to others. The compiler ignores them and they are never run. Java has three kinds:
// a comment to the end of the line /* a block of comment, over several lines */ /** a Javadoc comment, used to make API documentation */
The figure takes String off the shelf and opens its documentation for substring.
A precondition must be true just before a method runs for it to work as expected. The method is not expected to check it: calling substring with to past the end breaks the precondition, and the result is an exception, not a polite answer.
A postcondition must always be true after the method runs. It describes the outcome: what is returned, or the values of the object’s attributes afterward.
parameters, arguments, return values
A method is a named block of code that runs only when it is called. A block is any code in braces.
Procedural abstraction: you can use a method knowing what it does, without knowing how it was written. Its header tells you what you need:
public static double pow(double base, double exponent)
A parameter is a variable declared in the header (base, exponent), used inside the method. The method signature is the method’s name and the ordered list of parameter types: pow(double, double). A method without parameters has an empty list: length().
An argument is a value passed in when the method is called. Arguments must match the parameters in number and order. They are passed by value: each parameter starts as a copy of its argument. In the figure, 2 and 10 become the copies 2.0 and 10.0.
double r = Math.pow(2, 10); System.out.println(r); // 1024.0 A non-void method returns a value of its return type; to use it, store it in a variable or use it in an expression. A void method returns nothing, so it cannot be part of an expression: int x = System.out.println(5); does not compile.
Methods are overloaded when several have the same name and different signatures: Math.abs(int) and Math.abs(double). The arguments decide which runs.
A call interrupts the sequence of statements: the method’s statements run first, and when the last one (or a return) has run, control comes back to just after the call.
static methods, and Math.random()
Class methods belong to the class, not to any one object. Their header has the keyword static, and they are called with the class name and the dot operator: Math.sqrt(2.0). Inside the class that defines them, the class name can be left off.
The Math class is in java.lang, so it is available without an import, and it has only class methods. The Java Quick Reference lists five:
| method | returns |
|---|---|
static int abs(int x) | the absolute value of an int |
static double abs(double x) | the absolute value of a double |
static double pow(double base, double exponent) | base raised to the exponent |
static double sqrt(double x) | the nonnegative square root |
static double random() | a double ≥ 0.0 and < 1.0 |
Math.random()’s range includes 0.0 (an inclusive endpoint) and excludes 1.0 (an exclusive one). Arithmetic and casting move it to the range you want:
int roll = (int) (Math.random() * 6) + 1;
The figure does it in steps. * 6 stretches [0.0, 1.0) to [0.0, 6.0). (int) truncates each part to 0, 1, …, 5: 6 equal parts, so 6 equally likely values. + 1 shifts them to 1, …, 6. In general, (int) (Math.random() * count) + low gives one of count ints starting at low.
Its 30 rolls landed 5 on 1, 5 on 2, 6 on 3, 4 on 4, 6 on 5, 4 on 6: equally likely does not mean equally often in a short run.
the blueprint and what it makes
A class is the formal implementation, or blueprint, of the attributes and behaviors of an object. An object is a specific instance of a class, with its own values for those attributes.
The figure uses a hypothetical class, Book, with two attributes (a title and a number of pages) and two behaviors (getTitle() and getPages()). Each Book stamped from it has its own title and pages: "Maps", 120; "Birds", 340; "Stars", 96.
Related classes can share common attributes and behaviors by putting them in one class, a superclass. Classes that extend it, subclasses, draw on those attributes and behaviors without writing them again: an inheritance relationship. (Designing and writing inheritance is outside the course.)
Every class in Java is a subclass of the Object class, which is why every object has methods like toString() and equals.
A variable of a reference type holds an object reference, which can be thought of as the object’s memory address: the arrow in the figures, not the object.
Book b; // b can hold a reference to a Book String s; // s can hold a reference to a String
new, constructors and null
An object is created with the keyword new followed by a call to one of the class’s constructors.
A constructor has the same name as its class. Its signature is that name and the ordered list of parameter types; its header lists the types and names of the parameters. The documentation of the hypothetical Book lists:
Book(String title, int pages) Book(String title) String getTitle() int getPages()
Two constructors with different signatures: the constructors are overloaded, and the arguments decide which is called. new Book("Maps") calls the second.
Book b = new Book("Maps", 120); Book c = null; The figure runs the first line in order: new makes memory for a Book; the constructor runs, its parameters set the initial values of the attributes; then the reference to the new object is stored in b. Like a method call, a constructor call interrupts the sequence of statements, and control returns to just after the call when its last statement has run.
Constructor arguments must be compatible in number and order with the parameter types, and are passed by value: new Book(120, "Maps") does not compile, because no constructor takes an int and then a String.
A variable of a reference type holds an object reference or, if there is no object, null: c refers to nothing.
the dot operator, and null
Instance methods are called on an object of the class, with the object’s name, the dot operator and the method: b.getPages().
int p = b.getPages(); // p is 120 int q = c.getPages(); // NullPointerException
The call follows the reference in b to its object, runs getPages() on that object, and the int it returns (120) is stored in p. A different Book object would answer with its own pages.
c is null: there is no object to follow the arrow to. Calling a method on a null reference throws a NullPointerException when the line runs. It compiles: the compiler only checks that a Book has a getPages().
Compare the class method of page 1.10: Math.sqrt(x) is called on the class; s.length() is called on one String object, and answers for that string alone.
immutable; concatenation makes new ones
A String object represents a sequence of characters. It is made from a string literal, "cat", or with the constructor, new String("cat"). String is in java.lang, available by default.
A String object is immutable: once created, its characters never change. Methods called on a String do not change it; they return a new value.
String s = "cat"; // s is "cat" s = s + "s"; // s is "cats" String t = s + 1 + 2; // t is "cats12" String v = 1 + 2 + s; // v is "3cats"
+ and += concatenate Strings, making a new String object. In the figure, s = s + "s" builds "cats" and points s at it; the "cat" object is still exactly "cat".
A primitive concatenated with a String is converted to a String. + works left to right, so where the String first appears matters: in s + 1 + 2, each number is joined on as text; in 1 + 2 + s, 1 + 2 is added first, as ints.
Any object can be concatenated with a String: Java calls the object’s toString method, which every class has from Object, and which returns a string representing the object. Subclasses often override it (a public method with the same signature as the superclass’s, with behavior of their own); writing such an override is outside the course.
indices, length, substring, indexOf
A String’s characters have indices from 0 to one less than its length. Using an index outside that range throws a StringIndexOutOfBoundsException.
The Java Quick Reference lists these String methods (and the constructor; split comes with text files, in topic 4.6):
| method | returns |
|---|---|
int length() | the number of characters |
String substring(int from, int to) | the characters from index from to index to - 1 |
String substring(int from) | substring(from, length()) |
int indexOf(String str) | the index of the first occurrence of str; −1 if not found |
boolean equals(Object other) | next page |
int compareTo(String other) | next page |
String s = "BANANAS"; s.length(); // 7 s.substring(1, 4); // "ANA" s.substring(4); // "NAS" s.indexOf("NA"); // 2 s.indexOf("X"); // -1 s.substring(3, 4); // "A"
to is the first index left out, so substring(from, to) has to - from characters. indexOf finds only the first occurrence: "NA" also starts at index 4.
A string holding the single character at index is substring(index, index + 1).
equals, compareTo, and not ==
equals asks whether two Strings hold the same sequence of characters. compareTo asks which comes first.
String a = "pear"; String b = new String("pear"); System.out.println(a == b); // false System.out.println(a.equals(b)); // true System.out.println(a.compareTo("peach") > 0); // true a and b refer to two different objects that hold the same characters. a.equals(b) compares the characters, pair by pair: true. a == b compares the references, whether they point at the same object: false. Compare Strings with equals. (Comparing references with == returns in topic 2.6.)
a.compareTo(other) returns a value less than 0 if a comes before other, 0 if they are equal, and greater than 0 if a comes after. Strings are ordered based on the alphabet: the first characters that differ decide. "pear" and "peach" agree up to index 3, where 'r' comes after 'c', so the result is positive. Rely only on its sign: that is all the Quick Reference promises.
The course uses equals only to compare a String with another String.