Unit 1 notes · 15 topics, read straight through

Unit 1: Using Objects and Methods

Every topic in one read: the big idea, the notes, the Java examples and the exam traps. Practice comes after, on each topic's checkpoint.

1.1 Introduction to Algorithms, Programming, and Compilers

Big ideaA program is an algorithm written in a language the computer can check and run.

1. Algorithms and sequencing

An algorithm is a step-by-step process for completing a task or solving a problem. You can represent an algorithm in written language (plain words) or as a diagram, for example a flowchart 1.1.A.1.

Here is an everyday algorithm in written language:

  1. Boil water.
  2. Put a tea bag in a cup.
  3. Pour in the water.
  4. Wait 3 minutes.
  5. Remove the bag.

As a flowchart, each step is a box, and arrows join the boxes in this order: boil water, then tea bag in cup, then pour, then wait, then remove the bag.

Sequencing defines the order in which the steps happen. Steps are completed one at a time 1.1.A.2. Change the order and you may change the result: swap steps 1 and 3 and you get cold, wet tea leaves.

A Java program is an algorithm too. The statements in main run in sequence, top to bottom, one at a time:

int score1 = 80;
int score2 = 90;
int score3 = 85;
int total = score1 + score2 + score3;
System.out.println("Total: " + total);
System.out.println("Average: " + total / 3);

Output:

Total: 255
Average: 85

Watch out: the total must be computed before the average. If the average line came first, total would not exist yet and the code would not compile.

2. Writing, compiling and running code

Code can be written in any text editor. However, programmers often use an integrated development environment (IDE), because it gives tools to write, compile and run code in one place 1.1.B.1. Without an IDE, you run the compiler and then the program yourself.

A compiler checks your code for some errors. Errors the compiler can detect must be fixed before the program can run 1.1.B.2.

The path from code to a working program has four stages. Each type of error shows up at a different stage:

Stage What happens Error that shows up here
1. Write code You type the program in a text editor or IDE.
2. Compile The compiler checks some errors. Syntax error: rules broken; fix it, then compile again.
3. Run The statements execute. Run-time error: for example an exception; the program stops abnormally.
4. Test You try known inputs and compare with the expected outcome. Logic error: the program runs, but gives a wrong result.

Here the programmer forgot a semicolon:

// does not compile
public class Lives
{
    public static void main(String[] args)
    {
        int lives = 3
        System.out.println(lives);
    }
}

Real view: the compiler stops and reports the file, the line number (6) and the problem. Nothing runs.

Lives.java:6: error: ';' expected
        int lives = 3
                     ^
1 error

3. The three types of programming error

Error What it is Who or what finds it Example
Syntax error The rules of Java are not followed 1.1.C.1. The compiler A missing ; or )
Logic error The algorithm or program is wrong, so it behaves incorrectly or unexpectedly 1.1.C.2. Testing with specific data and comparing to the expected outcome Area computed as length + width
Run-time error Happens while the program runs (during execution); usually makes it stop abnormally 1.1.C.3. Shows up during execution Dividing an int by 0

A logic error compiles and runs without complaint. This program should print the area of a 5 by 3 rectangle, which is 15:

int length = 5;
int width = 3;
int area = length + width;
System.out.println("Area: " + area);

Output:

Area: 8

The output is wrong because the formula is wrong. Testing with data where you already know the answer (5 and 3 give 15) reveals the error. The fix is length * width.

Watch out: “it compiles” does not mean “it is correct”.

4. Exceptions

An exception is a type of run-time error. It happens because of an unexpected problem that the compiler did not detect, and it interrupts the normal flow of the program’s execution 1.1.C.4. In this course, an exception stops the program, so the statements after it do not run.

int total = 12;
int count = 0;
System.out.println("Start");
System.out.println(total / count);
System.out.println("End");

Output:

Start
Exception in thread "main" java.lang.ArithmeticException: / by zero

The code compiles, because the compiler does not know that count will be 0. The program prints Start, then stops at the division. End is never printed.

Unit 1 names three exceptions:

  • ArithmeticException: an integer divided by the integer zero (topic 1.3).
  • NullPointerException: a method called on null (topic 1.14).
  • StringIndexOutOfBoundsException: an index outside a String (topic 1.15).

Background (not tested): what the compiler actually makes. The Java compiler turns your .java file into bytecode (a .class file). The Java Virtual Machine (JVM) then runs the bytecode, which is why the same Java program runs on different operating systems. Every program starts running at its main method: public static void main(String[] args). Programmers use these words often; the exam does not test them.

5. Unit 1 on the AP® exam

  • The College Board weights Unit 1 at 15 to 25 percent of the multiple-choice section. That section has 42 questions in 90 minutes and is 55 percent of the exam score.
  • Unit 1 skills also appear in the free-response section (4 questions, 90 minutes, 45 percent). Question 1, Methods and Control Structures, has a part (3 points) that requires calling String methods, and the sample free-response Questions 1, 3 and 4 in the official Course and Exam Description (CED) all use Unit 1 objectives.
  • The unit develops 9 skills: 1.A (design), 2.A, 2.B, 2.C (develop code), 3.A, 3.C, 3.D (analyze code) and 4.A, 4.B (document code).
  • Topic 1.15 (String Manipulation) is the largest topic in the unit.
  • You get the Java Quick Reference on the exam. Learn the Math and String methods on it now (topics 1.11 and 1.15).
  • Tags like 1.3.C on these pages point to the College Board learning objective each note covers. Background boxes help you understand a topic; their wording is not tested.

Official practice: do the CED sample multiple-choice Questions 1 to 4 (Exam Information section of the AP® Computer Science A CED, effective Fall 2025; Questions 1 and 2 are on page 149, Questions 3 and 4 on page 150, answer key on page 170). Questions 5 to 20 test later units. Sample free-response Question 1, Methods and Control Structures (pages 161 to 163): part (b) uses Unit 1 String methods, and part (a) needs Unit 2 loops, so try the full question after Unit 2. The same goes for the 2026 Free-Response Question 1 (released exam, pages 4 to 6) on the AP® Central past exam questions page. Score yourself with the College Board’s own scoring guidelines.

Background (not tested): words you will hear. Programmers use these words every day. They are useful, but they are not the official course wording, so on the exam look for the course term.

You may hear Course term or meaning
static method class method (1.10)
field, property attribute (1.7); Unit 3 adds the term instance variable
pass by value call by value (1.9)
actual parameter / formal parameter argument / parameter (1.9)
build, make an object instantiation: create an object with new (1.13)
type casting, type conversion casting (1.5)
bytecode, JVM, main method not in the course framework; see section 4 above
operand; unary / binary operator the value an operator works on; an operator with one / two operands (1.3)
crash; bug run-time error; bug means any error, often a logic error (1.1)
string joining concatenation (1.15)
object address, pointer object reference (1.12)

Exam traps

  • "It compiles" does not mean "it is correct". A logic error compiles and runs; only testing reveals it.
  • A program with a syntax error never starts running. Errors the compiler finds must be fixed first.
  • Match the error to who finds it: compiler for syntax, testing for logic, execution for run-time.

Simulator and checkpoint for 1.1 →

1.2 Variables and Data Types

Big ideaEvery value has a type, and the type decides what values are allowed and what you can do with them.

1. What a data type is

A data type is a set of values and the set of operations allowed on those values. Every data type is in one of 2 categories: primitive or reference 1.2.A.1.

  • Primitive types define the values and operations for numbers and Boolean values 1.2.A.2. The variable stores the value directly.
  • A reference type is used for objects, that is, for anything that is not a primitive type 1.2.A.3. Examples: String, or a class such as Plant.

The type decides which operations make sense. You can multiply two int values, but you cannot multiply two boolean values.

2. The three primitive types in this course

The three primitive types used in this course are int, double and boolean 1.2.B.1.

Type Holds Example values
int an integer -4, 0, 120
double a real number 3.75, -0.5, 87.5
boolean only true or false true, false

Outside the course: Java has 5 other primitive types (long, short, byte, float and char). You will not need them on the AP® exam.

3. Declaring variables

A variable is a storage location that holds a value, and the value can change while the program is running. Every variable has a name and a data type. A variable of a primitive type holds a primitive value of that type 1.2.B.2.

int lives = 3;            // whole number
double average = 87.5;    // real number
boolean gameOver = false; // true or false only
String player = "Ana";    // reference type: an object
System.out.println(player + " has " + lives + " lives");
System.out.println("Average: " + average);
System.out.println("Game over? " + gameOver);
lives = 2;                // the value can change
System.out.println(player + " has " + lives + " lives");

Output:

Ana has 3 lives
Average: 87.5
Game over? false
Ana has 2 lives

The name and type stay the same for the life of the variable. Only the value changes.

4. Primitive and reference variables in memory

A primitive variable holds the value itself. A reference variable holds a reference (an address) that leads to an object somewhere else in memory.

Code What the variable holds
int count = 3; count holds the value 3.
boolean done = false; done holds the value false.
Plant p = new Plant("Fern", 30); p holds a reference to a Plant object, and that object stores name "Fern" and height 30.
Plant q = null; q holds null: there is no object. Calling a method on q throws a NullPointerException (topic 1.14).

Assigning p to another variable copies the reference, not the object, so both variables then refer to the same object (topics 1.4, 1.12 and 1.14).

Plant p = new Plant("Fern", 30);
Plant other = p;           // copies the reference
other.grow(5);
System.out.println(p.getHeight());

Output:

35

There is only one Plant object. Growing it through other changes what p sees too.

5. Choosing the right type for a specification

Read the specification and ask: what values must this hold? 1.2.A

Specification Best type Category
Number of people on a bus int primitive
Price of a ticket, average score double primitive
Whether a door is locked boolean primitive
A player’s name String reference

Watch out: do not store a number you will calculate with as text. "12.6" is a String, so you cannot do arithmetic with it.

Background (not tested): naming conventions. Java programmers name variables in camelCase (totalScore, isReady) and classes in PascalCase (Plant, String). Names cannot start with a digit, contain spaces, or be a keyword such as int or new, and Java is case-sensitive (score and Score are different variables). Declaring creates a variable (int x;); initializing gives it its first value (x = 5;).

Exam traps

  • Choose the type from the specification. A count of people is an int, a price or an average is a double, a yes/no state is a boolean, text is a String (a reference type).
  • String starts with a capital letter because it is a class: a reference type, not a primitive.

Simulator and checkpoint for 1.2 →

1.3 Expressions and Output

Big ideaJava evaluates expressions by fixed rules: the types decide the result, and precedence decides the order.

1. Output: print and println

System.out.print and System.out.println display information on the computer display. System.out.println moves the cursor to a new line after the information has been displayed; System.out.print does not 1.3.A.1. System.out.println(); with nothing inside just ends the line.

System.out.print("Total: ");
System.out.println(7 + 3);    // 10, after "Total: "
System.out.println("7" + 3);  // 73 (text joined, not added)
System.out.print("A");
System.out.print("B");
System.out.println();         // just ends the line
System.out.println("C");

Output:

Total: 10
73
AB
C

Watch out: print does not add a space. If you want one, put it inside the quotes, as in "Total: ".

2. Literals and string literals

A literal is the code representation of a fixed value, such as 42, 3.5 or true 1.3.B.1. A string literal is a sequence of characters enclosed in double quotes, such as "Game over" 1.3.B.2.

A literal’s form sets its type: 7 is an int, 7.0 is a double, "7" is a String and true is a boolean. So 7 / 2 uses int division but 7.0 / 2 does not 1.3.B, 1.3.C.

System.out.println(7 / 2);
System.out.println(7.0 / 2);
System.out.println("7 / 2");

Output:

3
3.5
7 / 2

The last line prints the characters exactly as written, because they are inside a string literal. Java does not calculate anything inside quotes.

3. Escape sequences

Escape sequences are special sequences of characters inside a string. They start with a backslash \ and have a special meaning in Java. The 3 escape sequences in this course are \" (double quote), \\ (backslash) and \n (newline) 1.3.B.3.

Each escape sequence stands for one character in the String, so "a\nb".length() is 3 (length() is in topic 1.15).

System.out.println("She said \"go\"\nC:\\temp");
System.out.println("a\nb".length());

Output:

She said "go"
C:\temp
3

Watch out: a single \ inside a string always starts an escape sequence. In "C:\temp", Java reads \t as a tab (outside the course), so the backslash is never printed; with most other letters, such as "C:\data", the code does not compile. To print one backslash, write two: \\.

4. Arithmetic expressions

An arithmetic expression is made of numeric values, variables and operators, and it can have type int or double 1.3.C.1. The 5 arithmetic operators are +, -, *, / and % (remainder) 1.3.C.2.

  • An operation with two int values evaluates to an int. An operation with at least one double value evaluates to a double 1.3.C.2.
  • Dividing two int values gives only the integer portion of the quotient. Dividing when at least one value is a double gives the full quotient 1.3.C.3.
  • The remainder operator % computes the remainder when one number a is divided by another number b 1.3.C.4.
  • int division drops the decimal part, so the result moves toward zero: -7 / 2 is -3, not -4.
Expression Value Why
17 / 5 3 int / int keeps only the integer part
17 % 5 2 remainder of 17 divided by 5
17 / 5.0 and 17.0 / 5 3.4 at least one double, so the result is a double
2 + 3 * 4 14 *, /, % before +, -
(2 + 3) * 4 20 parentheses change the grouping
10 - 4 - 3 3 same precedence: left to right
8 % 3 * 2 4 same precedence: 8 % 3 is 2, then * 2
System.out.println(17 / 5);
System.out.println(17 % 5);
System.out.println(17 / 5.0);
System.out.println(17.0 / 5);
System.out.println(-7 / 2);
System.out.println(2 + 3 * 4);
System.out.println((2 + 3) * 4);
System.out.println(10 - 4 - 3);
System.out.println(8 % 3 * 2);

Output:

3
2
3.4
3.4
-3
14
20
3
4

Outside the course: % with a negative first value or with a divisor of 0 or less, double division by zero, and results such as infinity or NaN (not a number).

5. Operator precedence

Operator precedence is the order in which Java groups operators. At compile time, values are associated with operators by precedence. Parentheses change the grouping. Multiplication, division and remainder have precedence over addition and subtraction, and operators with the same precedence are evaluated from left to right 1.3.C.5.

Higher rows group first (they hold their operands more tightly). Within rows 3 and 4, Java works left to right. The course framework states rows 1, 3 and 4; rows 2 and 5 are how Java works, and they explain the casting and assignment rules in topics 1.4 to 1.6.

Order Operators Example Value
1 ( ) parentheses (2 + 3) * 4 20
2 one-operand operators: -x (negation), casts (int) and (double) (int) 3.9 * 2 6 (the cast applies to 3.9 only)
3 * / % 10 - 4 * 2 2
4 + - (two operands) 10 - -3 13 (subtract negative 3)
5 = += -= *= /= %= x *= 2 + 3 the whole right side first (topic 1.6)
System.out.println((int) 3.9 * 2);
System.out.println((int) (3.9 * 2));
System.out.println(10 - -3);
System.out.println(7 + 9 / 4 * 2);

Output:

6
7
13
11

In the last line, 9 / 4 is 2 (int division), 2 * 2 is 4, and 7 + 4 is 11.

Background (not tested): unary and binary operators. The values an operator works on are its operands. A unary operator has one operand: -x, (int) x, x++ (see topic 1.6). A binary operator has two: a - b, a * b. The same symbol can do different jobs. - is negation in -x but subtraction in a - b. + adds when both operands are numbers but joins text when either operand is a String (concatenation, see topic 1.15), and because Java works left to right, 1 + 2 + "!" is "3!" while "!" + 1 + 2 is "!12". The words unary, binary and operand are not official course wording, but they help you read any expression.

System.out.println(1 + 2 + "!");
System.out.println("!" + 1 + 2);

Output:

3!
!12

6. Dividing by zero

An attempt to divide an integer by the integer zero results in an ArithmeticException 1.3.C.6. The code compiles, but the program stops when the division runs.

int players = 0;
System.out.println("Splitting 20 points");
System.out.println(20 / players);

Output:

Splitting 20 points
Exception in thread "main" java.lang.ArithmeticException: / by zero

Outside the course: dividing by zero when one of the values is a double.

7. Using / and % together

/ and % together split a number into parts 1.3.C:

  • n % 2 is 0 for even numbers and 1 for odd ones (for n of 0 or more).
  • n % 10 gives the last digit and n / 10 removes it, so 347 % 10 is 7 and 347 / 10 is 34.
  • minutes / 60 and minutes % 60 split 135 minutes into 2 hours and 15 minutes.
int minutes = 135;
System.out.println(minutes / 60 + " h " + minutes % 60 + " min");
int code = 347;
System.out.println(code % 10);
System.out.println(code / 10);
System.out.println(code % 2);

Output:

2 h 15 min
7
34
1

These moves return in Unit 2 and in free-response questions.

Exam traps

  • Integer division: 7 / 2 is 3, not 3.5. Check the types of BOTH values before you divide.
  • A cast applies only to the value right after it. (int) 3.9 * 2 is 6, but (int) (3.9 * 2) is 7. Put parentheses around everything you want cast.
  • "7" + 3 is "73": when either operand is a String, + joins text instead of adding.
  • Each escape sequence is one character: "a\nb".length() is 3, not 4.

Simulator and checkpoint for 1.3 →

1.4 Assignment Statements and Input

Big idea= means "store the value on the right in the variable on the left", not "is equal to".

1. Giving a variable its first value

Every variable must be assigned a value before it can be used in an expression, and that value must be of a compatible data type. A variable is initialized the first time it is assigned a value 1.4.A.1.

// does not compile
int n;
System.out.println(n);

Real view: the compiler rejects the code because n has no value yet.

error: variable n might not have been initialized

Declaring and initializing can happen in one statement or in two:

int lives = 3;     // declared and initialized together
int bonus;         // declared only
bonus = 2;         // initialized here
System.out.println(lives + bonus);

Output:

5

A reference variable can be assigned a new object, or null if there is no object. The literal null is a special value that means a reference is not associated with any object 1.4.A.1.

String title = "Chess Club";
String nickname = null;      // no String object yet
System.out.println(title);
System.out.println(nickname);

Output:

Chess Club
null

Printing a null variable prints the word null. Calling a method on it is different: that throws a NullPointerException (topic 1.14).

2. The assignment operator

The assignment operator = gives a variable its first value (initializes it) or replaces the value it holds. Java stores the value of the expression on the right side in the variable on the left side 1.4.A.2.

Java evaluates the right side first, using the current values, and then stores the result. So c = c + 1; is not an equation: it adds 1 to c.

int c = 4;
c = c + 1;
System.out.println(c);

Output:

5

Assigning a primitive copies the value. After int b = a;, changing a does not change b.

int a = 10;
int b = a;   // b gets a copy of 10
a = 99;
System.out.println(a + " " + b);

Output:

99 10

For a reference variable, the value copied is the reference, so both variables then refer to the same object (see aliasing in topic 1.14).

Outside the course: assignments inside expressions, such as a = b = 4;.

3. Expressions produce one value

During execution, an expression is evaluated to produce a single value, and that value has a type based on the evaluation 1.4.A.3. a + 4 is an expression: it produces a value. A simple statement, such as an assignment or a method call, is a complete instruction that ends in ;, such as int b = a + 4;.

int a = 7;
double half = a / 2.0;  // the expression a / 2.0 has type double
int whole = a / 2;      // the expression a / 2 has type int
System.out.println(half + " " + whole);

Output:

3.5 3

The type of the expression must be compatible with the variable. a / 2.0 is a double, so it could not be stored in an int variable without a cast (topic 1.5).

4. Trace tables

A trace table follows the values step by step. Each row runs one line of code and shows the values stored afterwards. A blank cell means the variable does not exist yet.

int a = 3;
int b = a + 4;
a = b * 2;
b = b - a;
System.out.println(a + " " + b);
Line Code a b
1 int a = 3; 3
2 int b = a + 4; 3 7
3 a = b * 2; 14 7
4 b = b - a; 14 -7

Output:

14 -7

Watch out: line 4 uses the NEW value of a (14, not 3). Update your trace table after every line; never use a value from memory.

5. Input

Input can come in a variety of forms, such as tactile (touch), audio, visual or text. The Scanner class is one way to get text input from the keyboard 1.4.B.1. No specific form of user input is tested on the AP® exam, so you only need the idea.

import java.util.Scanner;

public class Greeting
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        System.out.println("Name?");
        String name = input.nextLine();
        System.out.println("Age?");
        int age = input.nextInt();
        System.out.println("Hi " + name + ", next year you will be " + (age + 1));
    }
}

Real view: the console when the user types Ana and 16 (the typed lines are the user’s input).

Name?
Ana
Age?
16
Hi Ana, next year you will be 17

Exam traps

  • In a trace, each line uses the NEW values from the lines before it. Update your trace table after every line; never use a value from memory.
  • Using a variable before it has a value does not compile.
  • Assigning a primitive copies the value; assigning a reference copies the reference, so both variables refer to the same object.

Simulator and checkpoint for 1.4 →

1.5 Casting and Range of Variables

Big ideaConverting between int and double changes values in predictable ways, and both types have limits.

1. The casting operators

The 2 casting operators are (int) and (double). They convert a double value to an int value, or an int value to a double value 1.5.A.1. Casting a double to an int causes the digits to the right of the decimal point to be truncated (cut off) 1.5.A.2. Truncating moves toward zero, for negative numbers too.

A cast is a one-operand operator, so it applies only to the value right after it (see the precedence table in topic 1.3).

Code Result Rule
(int) 3.86 3 casting to int truncates (cuts off) the decimal part
(int) -3.86 -3 truncating moves toward zero for negatives too
(double) 7 / 2 3.5 the cast happens first, so this is 7.0 / 2
(double) (7 / 2) 3.0 7 / 2 is already 3 before the cast
double d = 7; 7.0 an int is automatically cast (widened) to double
(int) (3.86 + 0.5) 4 rounds a non-negative double to the nearest int
(int) (-3.86 - 0.5) -4 rounds a negative double to the nearest int
System.out.println((int) 3.86);
System.out.println((int) -3.86);
System.out.println((double) 7 / 2);
System.out.println((double) (7 / 2));
double d = 7;
System.out.println(d);
System.out.println((int) (3.86 + 0.5));
System.out.println((int) (-3.86 - 0.5));

Output:

3
-3
3.5
3.0
7.0
4
-4

2. Widening: int to double automatically

Some code causes int values to be automatically cast (widened) to double values 1.5.A.3. This happens when you store an int in a double variable, or when an int meets a double in an expression.

int steps = 7;
double km = steps;          // widened to 7.0
System.out.println(km);
System.out.println(steps * 1.5);

Output:

7.0
10.5

The other direction is never automatic, because it could lose information. A double cannot be stored in an int variable without a cast:

// does not compile
int k = 3.5;

Real view:

error: incompatible types: possible lossy conversion from double to int

int k = (int) 3.5; compiles and stores 3.

3. Rounding to the nearest integer

Values of type double can be rounded to the nearest integer with (int) (x + 0.5) for non-negative numbers or (int) (x - 0.5) for negative numbers 1.5.A.4.

double rating = 4.7;
double drop = -2.6;
System.out.println((int) rating);
System.out.println((int) (rating + 0.5));
System.out.println((int) (drop - 0.5));

Output:

4
5
-3

Watch out: the parentheses matter. (int) rating + 0.5 casts first, giving 4 + 0.5, which is the double 4.5.

4. The range of int and integer overflow

The constant Integer.MAX_VALUE holds the largest possible int value, and Integer.MIN_VALUE holds the smallest 1.5.B.1. An int is stored in a fixed amount of memory (4 bytes), so every int value must lie in the range from Integer.MIN_VALUE (-2147483648) to Integer.MAX_VALUE (2147483647), inclusive 1.5.B.2.

If an expression would evaluate to an int outside this range, integer overflow occurs. The result is still an int in the allowed range, but not necessarily the value you expected 1.5.B.3. No error is reported; the program keeps running with the wrong value.

int big = Integer.MAX_VALUE;
System.out.println(big);
System.out.println(big + 1);
System.out.println(big + 2);
System.out.println(Integer.MIN_VALUE);

Output:

2147483647
-2147483648
-2147483647
-2147483648

5. Round-off error with double

Computers give each data type a fixed amount of memory. A double also has limited memory. When an expression would produce a double that is more precise than can be stored, a round-off error occurs, and the result is rounded to the nearest representable value. To avoid these rounding errors, use int values where you can, for example by storing money in cents 1.5.C.1.

System.out.println(0.1 + 0.2);
int cents = 10 + 20;
System.out.println(cents + " cents");

Output:

0.30000000000000004
30 cents

Outside the course: other special decimal types that avoid rounding errors.

Background (not tested): why 0.1 is not exact. Computers store numbers in binary (base 2). Just as 1/3 never ends in decimal (0.333…), 1/10 never ends in binary, so a double holds a value very close to 0.1, not exactly 0.1. Tiny errors like this are why you should not test double values with == (Unit 2).

Exam traps

  • (int) does not round. (int) 9.99 is 9. To round, add 0.5 first (or subtract 0.5 for negative numbers).
  • A double cannot be stored in an int variable without a cast. int k = 3.5; does not compile; int k = (int) 3.5; stores 3. The other way is automatic: double d = 7; stores 7.0.
  • A cast applies only to the value right after it: (double) 7 / 2 is 3.5, but (double) (7 / 2) is 3.0.
  • Integer overflow is not an exception. Integer.MAX_VALUE + 1 is a large negative int, with no error.

Simulator and checkpoint for 1.5 →

1.6 Compound Assignment Operators

Big ideaShortcuts that do the arithmetic and the assignment in one step.

1. The five compound assignment operators

The compound assignment operators +=, -=, *=, /= and %= can be used in place of the assignment operator in numeric expressions. A compound assignment operator takes the current value of the variable on the left, does the arithmetic with the value on the right, and stores the result back in that variable 1.6.A.1.

Compound form Same as
x += 3; x = x + 3;
x -= 3; x = x - 3;
x *= 3; x = x * 3;
x /= 3; x = x / 3;
x %= 3; x = x % 3;

Each line uses the value left by the line before:

int k = 7;
k += 3;    // 10
k *= 2;    // 20
k -= 5;    // 15
k /= 4;    // 3 (int division)
k %= 3;    // 0
System.out.println(k);

Output:

0

k /= 4 follows the same int division rule as /: 15 / 4 is 3.

2. The right side comes first

The whole right side is worked out first. If x is 4, x *= 2 + 3 means x = x * (2 + 3), so x becomes 20, not 11 1.6.A.1.

int x = 4;
x *= 2 + 3;
System.out.println(x);
double price = 10.0;
price -= 2.5 * 2;
System.out.println(price);

Output:

20
5.0

Watch out: /= and %= on an int variable keep int arithmetic, so the decimal part is lost. On a double variable, /= keeps the decimals.

3. Increment and decrement

The post-increment operator ++ adds 1 to the stored value of a numeric variable, and the post-decrement operator -- subtracts 1. The new value is assigned to the variable 1.6.A.2.

int lives = 3;
lives++;   // 4
lives++;   // 5
lives--;   // 4
System.out.println("Lives: " + lives);

Output:

Lives: 4

Outside the course: the prefix form ++x, and using ++ or -- inside another expression, such as arr[x++]. On the exam, x++ and x-- appear as statements on their own.

4. Tracing a full sequence

Trace one line at a time and write the new value after each line.

int score = 12;
score += 8;
score /= 3;
score *= 4;
score %= 7;
score--;
System.out.println(score);
Line Code score
1 int score = 12; 12
2 score += 8; 20
3 score /= 3; 6 (int division: 20 / 3)
4 score *= 4; 24
5 score %= 7; 3
6 score--; 2

Output:

2

Exam traps

  • /= and %= on an int variable keep int arithmetic, so the decimal part is lost.
  • The whole right side is worked out first: if x is 4, x *= 2 + 3 makes x 20, not 11.
  • Each line uses the value left by the line before it. Trace one line at a time.

Simulator and checkpoint for 1.6 →

1.7 Application Program Interface (API) and Libraries

Big ideaYou do not write everything yourself; you use classes other programmers wrote, guided by their documentation.

1. Libraries, APIs and packages

You do not write every class yourself. A library is a collection of classes. An application programming interface (API) specification informs the programmer how to use those classes. To understand what attributes and behaviors a class in the API has, you read its documentation 1.7.A.1.

  • A class defines a specific reference type. String is a class, so String is a reference type 1.7.A.1.
  • Classes in APIs and libraries are grouped into packages 1.7.A.1.
  • Existing classes and class libraries can be used to create objects 1.7.A.1.

Example: String and Math are classes in the java.lang package, part of the library that comes with Java. The Java Quick Reference tables in topics 1.11 and 1.15 are short extracts of their API documentation.

2. Using a class you did not write

You can use a library class by reading its documentation. You do not need to see its code.

String city = "Lisbon";
System.out.println(city.length());
System.out.println(Math.sqrt(81.0));

Output:

6
9.0

The String documentation says length() returns the number of characters. The Math documentation says sqrt returns a square root. Neither class was written by you.

3. Attributes and behaviors

Attributes are the data that belong to a class; they are kept in variables. Behaviors are the actions an instance of the class can do, or that can be done to it; methods define them 1.7.A.2.

Example: a Plant class might have the attributes name and height and the behaviors grow, getName and getHeight. Its documentation could look like this:

Documentation entry Attribute or behavior?
String name: the plant’s name attribute (data in a variable)
int height: the height in centimeters attribute (data in a variable)
void grow(int cm): adds cm to the height behavior (defined by a method)
int getHeight(): returns the height behavior (defined by a method)
String getName(): returns the name behavior (defined by a method)

Using the behaviors changes or reports the attributes:

Plant fern = new Plant("Fern", 30);
fern.grow(5);
System.out.println(fern.getName() + " is " + fern.getHeight() + " cm");

Output:

Fern is 35 cm

Watch out: attribute = noun stored in a variable (height); behavior = verb defined by a method (grow). In documentation, a method name is followed by parentheses.

Exam traps

  • Attribute = noun stored in a variable (height); behavior = verb defined by a method (grow).
  • A method name is followed by parentheses in documentation, such as grow(int cm). A variable such as height has no parentheses.

Simulator and checkpoint for 1.7 →

1.8 Documentation with Comments

Big ideaComments explain code to people; the compiler ignores them.

1. Comments and their three types

Comments are written for both the original programmer and other programmers, to help them understand the code and what it does. Comments are ignored by the compiler and are not executed when the program runs 1.8.A.1.

The 3 types of comment in Java 1.8.A.1:

Comment Use
// text one line
/* text */ a block over several lines
/** text */ Javadoc: used to create API documentation
/* Scoreboard: adds the points for one round.
   Written for the class quiz game. */
int points = 40;   // points before this round
points += 15;
// points = 0;     this line is a comment, so it never runs
System.out.println(points);

Output:

55

The line // points = 0; looks like code, but it is a comment, so the compiler ignores it.

2. Preconditions

A precondition is a condition that must be true just before a method runs, in order for it to behave as expected. There is no expectation that the method will check that its preconditions are satisfied 1.8.A.2. It is the caller’s job to meet them.

3. Postconditions

A postcondition is a condition that must always be true after a method runs. Postconditions describe the outcome of the method: what is returned, or the current values of the object’s attributes 1.8.A.3.

Both conditions are often written in a Javadoc comment above the method:

/** Returns the average score: total divided by count.
 *  Precondition: count > 0
 *  Postcondition: returns the average (total divided by count) as a double */
public static double average(int total, int count)
{
    return (double) total / count;
}

// in main
System.out.println(average(170, 2));
System.out.println(average(10, 4));

Output:

85.0
2.5

What if a caller breaks a precondition? This method shares points equally. It does not check people, so with 0 its behavior is not what anyone wants:

/** Returns each person's share of the points.
 *  Precondition: people > 0
 *  Postcondition: returns total divided by people (int division) */
public static int share(int total, int people)
{
    return total / people;
}

// in main
System.out.println(share(90, 4));
System.out.println(share(90, 0));

Output:

22
Exception in thread "main" java.lang.ArithmeticException: / by zero

The first call meets the precondition and returns 22. The second call breaks it, so the program stops with an ArithmeticException. The fault belongs to the caller who broke the precondition, not to the method.

Watch out: if a call breaks a precondition, the method’s behavior is not guaranteed. It is the caller’s job, not the method’s, to meet it.

Exam traps

  • If a call breaks a precondition, the method's behavior is not guaranteed. It is the caller's job, not the method's, to meet it.
  • Code inside a comment does not run, even if it looks like a valid statement.

Simulator and checkpoint for 1.8 →

1.9 Method Signatures

Big ideaA method's signature tells you exactly how to call it.

1. Methods and procedural abstraction

A method is a named block of code that only runs when it is called. A block is any section of code enclosed in braces { } 1.9.A.1.

Procedural abstraction allows a programmer to use a method by knowing what the method does, even without knowing how it was written 1.9.A.1. You call Math.sqrt(16.0) without ever seeing its code.

2. Parameters and method signatures

A parameter is a variable declared in the header of a method or constructor. It can be used inside the body of the method, and it lets values (arguments) be passed in and used by the method 1.9.A.2.

A method signature for a method with parameters is the method name plus the ordered list of parameter types. For a method without parameters, the signature is the method name plus an empty parameter list, for example getHeight() 1.9.A.2.

Reading a method header, part by part:

// not runnable: a method header from the Java Quick Reference
public static double pow(double base, double exponent)
Part of the header Meaning
static a class method (topic 1.10)
double (before pow) the return type: the type of value sent back
pow the method name
(double base, double exponent) the parameter list: the type and name of each parameter
pow(double, double) the signature: name + ordered parameter types

Same name, different signatures means overloaded methods (section 5).

3. Calling void and non-void methods

A void method does not have a return value, so it is not called as part of an expression 1.9.B.1. p.grow(5); is fine as a statement on its own.

// does not compile
Plant p = new Plant("Fern", 30);
int h = p.grow(5);

Real view:

error: incompatible types: void cannot be converted to int

A non-void method returns a value of the same type as the return type in its header. To use the returned value, store it in a variable or use it as part of an expression 1.9.B.2.

Plant p = new Plant("Fern", 30);
p.grow(5);                   // void: a statement on its own
int h = p.getHeight();       // non-void: value stored
System.out.println(h);
System.out.println(p.getHeight() * 2);   // value used in an expression

Output:

35
70

4. Arguments and call by value

An argument is a value passed into a method when the method is called. Arguments must be compatible in number and order with the types in the parameter list of the method signature. An int argument can go to a double parameter, as in Math.pow(2, 10), because the int is widened (topic 1.5). Arguments are passed using call by value: each parameter is initialized with a copy of the argument 1.9.B.3. Changing the parameter inside the method does not change the caller’s variable.

public static void addTen(int value)
{
    value = value + 10;
    System.out.println("Inside: " + value);
}

// in main
int score = 5;
addTen(score);
System.out.println("Outside: " + score);

Output:

Inside: 15
Outside: 5

value gets a copy of 5 and becomes 15, but score in main is still 5. The copy disappears when the method ends.

5. Overloaded methods

Methods are overloaded when there are several methods with the same name but different signatures 1.9.B.4, for example abs(int x) and abs(double x). Java picks the method whose parameter types match the arguments, in order.

public static void show(int points)
{
    System.out.println("Points: " + points);
}

public static void show(String player, int points)
{
    System.out.println(player + ": " + points);
}

public static void show(int points, String player)
{
    System.out.println(points + " for " + player);
}

// in main
show(12);
show("Ana", 12);
show(12, "Ana");

Output:

Points: 12
Ana: 12
12 for Ana

Two methods with the same name and the same parameter types do not compile, even if the parameter names differ:

// does not compile
public static int area(int side) { return side * side; }
public static int area(int length) { return length * length; }

// in main
System.out.println(area(3));

Real view:

error: method area(int) is already defined in class Main

Background (not tested): exact matches win. When one overload matches the argument types exactly, Java uses it, so Math.abs(-4) uses abs(int) and returns the int 4, while Math.abs(-4.0) uses abs(double) and returns 4.0.

System.out.println(Math.abs(-4));
System.out.println(Math.abs(-4.0));

Output:

4
4.0

6. Flow of control in a method call

A method call interrupts the sequential execution of statements. The program first runs the statements in the method. Once the last statement in the method has run, or a return statement runs, the flow of control returns to the point right after the call 1.9.B.5.

public static void greet()
{
    System.out.println("  inside greet");
}

// in main
System.out.println("before");
greet();
System.out.println("after");

Output:

before
  inside greet
after

Arguments are worked out before the call, so nested calls run inside out. In Math.sqrt(Math.abs(-16)), Math.abs(-16) runs first and gives 16, then Math.sqrt(16) gives 4.0.

System.out.println(Math.sqrt(Math.abs(-16)));

Output:

4.0

Exam traps

  • The return type and parameter names are NOT part of the signature. Only the name and the ordered parameter types are.
  • Order matters: show(int, String) and show(String, int) are different signatures, so show(12, "Ana") calls only the first.
  • A void method call is a statement on its own: p.grow(5); compiles, int h = p.grow(5); does not.
  • Call by value: after addTen(score), score is unchanged in the caller.

Simulator and checkpoint for 1.9 →

1.10 Calling Class Methods

Big ideaSome methods belong to the class itself, not to any one object.

1. What a class method is

Class methods are associated with the class, not with instances (objects) of the class. Their header includes the keyword static before the method name 1.10.A.1.

Example header: public static double toFahrenheit(double c). The keyword static tells you this is a class method. You can call it without creating any object.

2. Calling a class method from another class

Class methods are typically called using the class name along with the dot operator 1.10.A.2. Here a TempConverter class (written by someone else) has the class method toFahrenheit, and a Weather class uses it:

public class Weather
{
    public static void main(String[] args)
    {
        double hot = TempConverter.toFahrenheit(100.0);
        System.out.println(hot);
        System.out.println(TempConverter.toFahrenheit(30.0));
    }
}

Output:

212.0
86.0

TempConverter.toFahrenheit(100.0) returns 212.0. The return type is double, so the result is stored in a double variable or used in an expression, exactly as in topic 1.9.

In an unrelated class, leaving out the class name does not compile:

// does not compile
public class Weather2
{
    public static void main(String[] args)
    {
        System.out.println(toFahrenheit(100.0));
    }
}

Real view:

Weather2.java:6: error: cannot find symbol
        System.out.println(toFahrenheit(100.0));
                           ^
  symbol:   method toFahrenheit(double)
  location: class Weather2
1 error

3. Calling a class method inside its own class

When the method call occurs in the defining class, the use of the class name is optional 1.10.A.2:

public class TempConverter
{
    public static double toFahrenheit(double c)
    {
        return c * 9 / 5 + 32;
    }

    public static void main(String[] args)
    {
        System.out.println(toFahrenheit(100.0));               // class name left out
        System.out.println(TempConverter.toFahrenheit(0.0));   // class name used
    }
}

Output:

212.0
32.0

Both calls work, because main is inside TempConverter.

Background (not tested): “static method”. Many programmers say static method for what the course calls a class method. They mean the same thing. On the exam, expect “class method”.

Exam traps

  • In an unrelated class, calling toFahrenheit(100.0) without the class name does not compile.
  • Read the header: static means a class method, called with the class name. No static means an instance method, called on an object (topic 1.14).
  • The arguments must still match the signature: TempConverter.toFahrenheit("30") does not compile because a String is not a double.

Simulator and checkpoint for 1.10 →

1.11 Math Class

Big ideaThe Math class gives you ready-made, tested class methods for common calculations.

1. The Math class

The Math class is part of the java.lang package. Classes in the java.lang package are available by default, so you need no import 1.11.A.1. The Math class contains only class methods 1.11.A.2, so you call each one with the class name: Math.sqrt(2.25).

2. The five Math methods on the Java Quick Reference

These methods, what they do and when to use them are part of the Java Quick Reference 1.11.A.2:

Method Returns Example
static int abs(int x) the absolute value of an int Math.abs(-4) is 4
static double abs(double x) the absolute value of a double Math.abs(-4.5) is 4.5
static double pow(double base, double exponent) base raised to the power exponent Math.pow(2, 10) is 1024.0
static double sqrt(double x) the non-negative square root of x Math.sqrt(2.25) is 1.5
static double random() a double from 0.0 (included) up to 1.0 (not included) at least 0.0 and less than 1.0
System.out.println(Math.abs(-4));
System.out.println(Math.abs(-4.5));
System.out.println(Math.pow(2, 10));
System.out.println(Math.sqrt(2.25));
double side = Math.sqrt(49);
System.out.println("Side: " + side);

Output:

4
4.5
1024.0
1.5
Side: 7.0

Math.pow(2, 10) has int arguments, but the parameters are double, so the arguments are widened and the result is a double.

Watch out: pow and sqrt return a double, even with int arguments, so Math.pow(2, 3) prints 8.0, not 8, and int p = Math.pow(2, 3); does not compile without a cast:

// does not compile
int p = Math.pow(2, 3);

Real view:

error: incompatible types: possible lossy conversion from double to int

int p = (int) Math.pow(2, 3); compiles and stores 8.

3. Random numbers in a range

The values returned from Math.random() can be changed with arithmetic and casting operators to produce a random int or double in a defined range. Each endpoint of the range can be inclusive, meaning the value can occur, or exclusive, meaning it cannot 1.11.A.3.

Building a die roll, int die = (int) (Math.random() * 6) + 1;, step by step:

Step Expression Possible values What it does
1 Math.random() 0.0 up to 1.0 1.0 is never returned
2 ... * 6 0.0 up to 6.0 stretches to 6 values
3 (int) (...) 0, 1, 2, 3, 4, 5 drops the decimal part
4 ... + 1 1, 2, 3, 4, 5, 6 shifts: the lowest is 1

Pattern: (int) (Math.random() * (max - min + 1)) + min gives an int from min to max, both inclusive 1.11.A.3.

You cannot predict a random value, but you can test the two extremes. Here r stands in for the smallest and a very large value that Math.random() could return:

double r = 0.0;                  // smallest possible value
System.out.println((int) (r * 6) + 1);
r = 0.9999999;                   // just below 1.0
System.out.println((int) (r * 6) + 1);
System.out.println((int) r * 6 + 1);   // cast too early

Output:

1
6
1

The last line shows the trap: (int) r is 0 for every value below 1.0, so the result is always 1.

A random double in a range works the same way, without the cast. Math.random() * 5 + 10 gives a double from 10.0 (inclusive) up to 15.0 (exclusive):

double r = 0.0;
System.out.println(r * 5 + 10);
r = 0.5;
System.out.println(r * 5 + 10);

Output:

10.0
12.5

In a real program, write Math.random() in place of r, for example int card = (int) (Math.random() * 13) + 1; for a card value from 1 to 13.

Exam traps

  • (int) Math.random() * 6 is ALWAYS 0, because the cast happens first and (int) of a value below 1.0 is 0. Put parentheses around Math.random() * 6.
  • pow and sqrt return a double, even with int arguments, so Math.pow(2, 3) prints 8.0, not 8, and int p = Math.pow(2, 3); does not compile without a cast.
  • For a range from min to max inclusive, multiply by max - min + 1, not by max - min.

Simulator and checkpoint for 1.11 →

1.12 Objects: Instances of Classes

Big ideaA class is the blueprint; objects are the things built from it.

1. Classes and objects

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 defined attributes 1.12.A.1.

One Plant class can produce many Plant objects. Each object has its own values for the attributes name and height:

Plant fern = new Plant("Fern", 30);
Plant mint = new Plant("Mint", 12);
fern.grow(4);
System.out.println(fern.getName() + " " + fern.getHeight());
System.out.println(mint.getName() + " " + mint.getHeight());

Output:

Fern 34
Mint 12

Growing fern does not change mint. They are two different objects built from the same blueprint.

2. Class hierarchies: superclasses and subclasses

When related classes share attributes and behaviors, the shared parts can be written once, in one class called the superclass. This builds a class hierarchy. The classes that extend the superclass are its subclasses, and they can use the superclass’s attributes and behaviors without writing them again. The link from each subclass up to its superclass is an inheritance relationship 1.12.A.2.

Example: in a hierarchy with superclass Vehicle and subclasses Bus and Bicycle, both subclasses can use Vehicle’s attributes (such as speed) without rewriting them.

Class Role What it has
Vehicle superclass attributes and behaviors all vehicles share, such as speed
Bus subclass of Vehicle everything from Vehicle, plus its own, such as a number of seats
Bicycle subclass of Vehicle everything from Vehicle, plus its own, such as a number of gears

Outside the course: designing and implementing inheritance relationships. You only need to understand what they are.

3. Every class is a subclass of Object

All classes in Java are subclasses of the Object class 1.12.A.3. So every object, from any class, has the behaviors defined in Object, such as toString and equals, even if its own class never wrote them.

public class Coin
{
    // no methods written here at all
}

// in main
Coin c = new Coin();
System.out.println(c.equals(c));

Output:

true

Coin declares nothing, yet c.equals(c) compiles and runs, because Coin is a subclass of Object and draws on its equals behavior. Topic 1.15 uses the inherited toString behavior.

4. Reference variables hold object references

A variable of a reference type holds an object reference, which can be thought of as the memory address of that object 1.12.B.1. Declare a reference variable with the class name as its type:

String s = "Hi";
String t = s;          // copies the reference, not the object
Plant a = new Plant("Basil", 10);
Plant b = a;           // b refers to the same Plant as a
b.grow(5);
System.out.println(t);
System.out.println(a.getHeight());

Output:

Hi
15

After String t = s;, t holds a reference to the same String object that s refers to. After Plant b = a;, there is still only one Plant, so growing it through b changes what a.getHeight() returns.

Watch out: a reference variable does not contain the object; it contains where to find it.

Exam traps

  • A reference variable does not contain the object; it contains where to find it.
  • Assigning one reference variable to another copies the reference, not the object: both then refer to the same object.
  • Designing and implementing inheritance is outside the course, but you must know that every class is a subclass of Object.

Simulator and checkpoint for 1.12 →

1.13 Object Creation and Storage (Instantiation)

Big ideanew plus a constructor builds an object; the variable stores a reference to it.

1. Constructors and constructor signatures

A class contains constructors that are called to create objects. They have the same name as the class 1.13.A.1.

A constructor signature is the constructor’s name (the same as the class name) plus the ordered list of parameter types. In the constructor header, the parameter list gives the type and the variable name of each value passed in 1.13.A.2.

Constructors are overloaded when a class has several constructors with different signatures 1.13.A.3. The Plant class used on these pages has 2 constructors:

Constructor header Signature What it does
public Plant(String n) Plant(String) name n, height starts at 0
public Plant(String n, int h) Plant(String, int) name n, height h

Java picks the constructor by comparing the argument types with the parameter types, in order:

Plant p = new Plant("Fern", 30); // calls Plant(String, int)
Plant q = new Plant("Mint");     // calls Plant(String): height 0
System.out.println(p.getHeight());
System.out.println(q.getHeight());

Output:

30
0

Two constructors with the same parameter types, such as Box(int side) and Box(int len), do not compile, because their signatures are the same (Box(int)):

// does not compile
public class Box
{
    private int size;
    public Box(int side) { size = side; }
    public Box(int len) { size = len; }
}

Real view:

error: constructor Box(int) is already defined in class Box

2. Variables that hold object references

A variable of a reference type holds an object reference or, if there is no object, null 1.13.B.1. The variable’s type is the class name.

Plant r = null;                 // r refers to no object
System.out.println(r);
r = new Plant("Sage", 8);       // now r refers to a Plant
System.out.println(r.getName());

Output:

null
Sage

3. Creating an object with new

An object is typically created with the keyword new followed by a call to one of the class’s constructors 1.13.C.1. Parameters allow constructors to accept values that set the initial values of the object’s attributes 1.13.C.2.

Reading Plant p = new Plant("Fern", 30); part by part:

Part Meaning
Plant (first) the class: the reference type of the variable
p the variable that will hold the reference
= assignment: store the reference in p
new the keyword that creates the object
Plant("Fern", 30) the constructor call: same name as the class; it runs, then control returns here
"Fern", 30 the arguments, copied into the parameters n and h

4. Constructor arguments

A constructor argument is a value passed into a constructor when it is called. The arguments must be compatible in order and number with the types in the parameter list of the constructor signature. Arguments are passed using call by value: the parameters are initialized with copies of the arguments 1.13.C.3. An int argument can go to a double parameter, because the int is widened to a double (topic 1.5).

public class Ticket
{
    public Ticket(String event, double price)
    {
        System.out.println(event + " ticket: " + price);
    }

    public Ticket(double price)
    {
        System.out.println("General ticket: " + price);
    }

    public Ticket(int seat, String event)
    {
        System.out.println(event + " seat " + seat);
    }
}

// in main
Ticket a = new Ticket("Gala", 40);
Ticket b = new Ticket(15.5);
Ticket c = new Ticket(12, "Gala");

Output:

Gala ticket: 40.0
General ticket: 15.5
Gala seat 12

new Ticket("Gala", 40) has a String then an int. Only Ticket(String, double) has a String first, and 40 is widened to 40.0.

Watch out: order matters. new Plant(30, "Fern") does not compile, because no Plant constructor takes an int first:

// does not compile
Plant f = new Plant(30, "Fern");

Real view:

error: incompatible types: int cannot be converted to String

The only Plant constructor with two parameters is Plant(String, int), and its first parameter needs a String, not the int 30.

5. Flow of control in a constructor call

A constructor call interrupts the sequential execution of statements: the program first runs the statements in the constructor. Once the last statement in the constructor has run, the flow of control returns to the point immediately after the constructor call 1.13.C.4.

Here a version of the Plant constructor also prints:

public class Plant
{
    private String name;
    private int height;

    // a version of the Plant constructor that also prints
    public Plant(String n, int h)
    {
        name = n;
        height = h;
        System.out.println("Made " + n);
    }

    public int getHeight()
    {
        return height;
    }
}

// in main
System.out.println("Start");
Plant f = new Plant("Fern", 30);
System.out.println(f.getHeight());

Output:

Start
Made Fern
30

Start prints first. The constructor call then runs every statement in the constructor (printing Made Fern), and control comes back to the next line, which prints 30.

Exam traps

  • Java picks the constructor by comparing argument types with parameter types, in order. new Plant(30, "Fern") does not compile.
  • An int argument can go to a double parameter (it is widened), so new Ticket("Gala", 40) can call Ticket(String event, double price).
  • Two constructors with the same parameter types, such as Box(int side) and Box(int len), do not compile: parameter names are not part of the signature.
  • Plant p = null; holds no object. Plant p = new Plant(""); holds an object whose name is the empty string.

Simulator and checkpoint for 1.13 →

1.14 Calling Instance Methods

Big ideaInstance methods act on one particular object.

1. Calling instance methods with the dot operator

Instance methods are called on objects of the class. The dot operator is used with the object name to call an instance method 1.14.A.1. The method acts on that one object.

This continues the topic 1.13 example: p refers to a Plant named "Fern" with height 30, and q refers to a Plant named "Mint" with height 0.

Plant p = new Plant("Fern", 30);
Plant q = new Plant("Mint");
p.grow(5);                         // void: a statement on its own
System.out.println(p.getHeight()); // 35
System.out.println(q.getName() + " " + q.getHeight()); // Mint 0

Output:

35
Mint 0

p.grow(5) changed only the object p refers to. q still has height 0.

An instance method needs an object, so calling it with the class name does not compile:

// does not compile
Plant.grow(5);

Real view:

error: non-static method grow(int) cannot be referenced from a static context

2. NullPointerException

A method call on a null reference results in a NullPointerException 1.14.A.2. The code compiles, but the program stops when the call runs.

Plant r = null;                    // r refers to no object
System.out.println("Checking r");
System.out.println(r.getHeight());
System.out.println("Done");

Output:

Checking r
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Plant.getHeight()" because "r" is null

Done is never printed: the exception interrupts the normal flow of the program (topic 1.1). The exact wording after the colon can differ between Java versions; the exception name is what matters.

Watch out: printing a null variable, as in System.out.println(r);, is fine and prints null. Only calling a method on it throws the exception.

3. Aliases: two names, one object

After Plant b = a;, both variables refer to the SAME object. Calling an instance method through either name changes that one object.

Plant a = new Plant("Basil", 10);
Plant b = a;
b.grow(5);
a.grow(3);
System.out.println(a.getHeight() + " " + b.getHeight());

Output:

18 18

10 + 5 + 3 is 18, and both names report it, because there is only one Plant. (Unit 3 studies aliasing in more depth.)

4. Looking ahead to Unit 3: inside a non-void method

Inside a class, a method’s statements can use the object’s attributes directly, and a return statement sends one value back to the caller and ends the method. The value must match the return type in the header. This is what the free-response practice for this unit asks you to write.

public class Plant
{
    private String name;
    private int height;

    public Plant(String n, int h)
    {
        name = n;
        height = h;
    }

    // inside the Plant class
    public String getInitial()
    {
        return name.substring(0, 1);
    }
}

// in main
Plant p = new Plant("Fern", 30);
String first = p.getInitial();
System.out.println(first);

Output:

F

If p refers to a Plant named "Fern", p.getInitial() returns "F". A method returns a value; it does not print it. The caller decides what to do with the value.

Exam traps

  • Aliasing: after Plant b = a; both variables refer to the SAME object, so b.grow(5) changes what a.getHeight() returns too.
  • Printing a null variable prints null, but calling a method on it throws a NullPointerException.
  • A void instance method, such as grow, is a statement on its own; a non-void one, such as getHeight, gives a value to store or use.

Simulator and checkpoint for 1.14 →

1.15 String Manipulation

Big ideaA String is an object holding a sequence of characters, and its methods never change it.

1. Creating String objects

A String object represents a sequence of characters. You can create one with a string literal or by calling the String class constructor 1.15.A.1.

The String class is part of the java.lang package, and classes in java.lang are available by default 1.15.A.2, so no import is needed.

String team = "Falcons";             // string literal
String city = new String("Porto");   // String constructor
System.out.println(team + " of " + city);

Output:

Falcons of Porto

2. Strings are immutable

A String object is immutable: after it is made, nothing about it can change, and calling a method on it never changes its characters 1.15.A.3. Methods such as substring return a new String; no String method changes the original.

String w = "data";
w.substring(1);           // new String made, but not stored
System.out.println(w);
w = w.substring(1);       // now w refers to the new String
System.out.println(w);

Output:

data
ata

Watch out: a String method result that is not stored is lost.

3. Concatenation with + and +=

Two String objects can be concatenated (joined) with the + or += operator, which results in a new String object. A primitive value can be concatenated with a String; the primitive is implicitly converted to a String 1.15.A.4. Java works left to right, so where the text first appears matters.

Code Value or output Why
"Score: " + 4 + 5 "Score: 45" left to right: text first, so 4 and 5 are joined as text
4 + 5 + " pts" "9 pts" left to right: 4 + 5 is added first
w.substring(1); then print w (w is "data") data the new String was not stored
w = w.substring(1); then print w ata now the variable refers to the new String
System.out.println("Score: " + 4 + 5);
System.out.println(4 + 5 + " pts");
String msg = "Level";
msg += " " + 3;
msg += "!";
System.out.println(msg);
boolean won = true;
System.out.println("Won: " + won);

Output:

Score: 45
9 pts
Level 3!
Won: true

4. Concatenating objects: toString

A String can be concatenated with any object. This implicitly calls the object’s toString method, which returns a string representing the object. Every object has a toString method, because every class is a subclass of Object (topic 1.12) and inherits it 1.15.A.5.

Subclasses of Object often override toString with their own class-specific version. A subclass overrides a method (method overriding) when it writes a public method with the same method signature as a public method of its superclass, so that the method behaves in a way that fits the subclass 1.15.A.5.

Example: p refers to a Plant whose toString method returns "Fern, 30 cm".

Plant p = new Plant("Fern", 30);
System.out.println("Plant: " + p);
p.grow(2);
String label = "Now: " + p;
System.out.println(label);

Output:

Plant: Fern, 30 cm
Now: Fern, 32 cm

Outside the course: writing (overriding) your own toString method. You only need to know that concatenation calls it.

5. Indices and StringIndexOutOfBoundsException

A String has index values from 0 to one less than its length. Attempting to access an index outside this range results in a StringIndexOutOfBoundsException 1.15.B.1. (The to argument of substring may equal length(), because it stops before to. The from argument may also equal length(): "moon".substring(4) is "".)

For String word = "INTERFACE";:

Index 0 1 2 3 4 5 6 7 8
Character I N T E R F A C E
  • length() is 9, so the valid indices are 0 to 8.
  • word.substring(0, 5) is "INTER": it stops BEFORE index 5.
  • word.substring(5) is "FACE": from index 5 to the end.
  • word.substring(2, 3) is "T".
String word = "INTERFACE";
System.out.println(word.substring(0, 5));
System.out.println(word.substring(5));
System.out.println(word.substring(2, 3));
System.out.println("moon".substring(4).length());
System.out.println(word.substring(7, 10));

Output:

INTER
FACE
T
0
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: Range [7, 10) out of bounds for length 9

Index 10 is past the end (the largest allowed to is 9), so the last call throws the exception. The message after the colon can differ between Java versions.

6. The six String methods on the Java Quick Reference

These String methods, what they do and when to use them are part of the Java Quick Reference 1.15.B.2:

Method Returns Example with word = "INTERFACE"
int length() the number of characters word.length() is 9
String substring(int from, int to) the characters from index from to to - 1 word.substring(0, 5) is "INTER"
String substring(int from) substring(from, length()) word.substring(5) is "FACE"
int indexOf(String str) the index of the first occurrence of str; -1 if not found word.indexOf("FACE") is 5; word.indexOf("X") is -1
boolean equals(Object other) true if the same sequence of characters, false otherwise "Cat".equals("cat") is false
int compareTo(String other) a value < 0 if this comes first alphabetically, 0 if equal, a value > 0 if this comes later "cat".compareTo("dog") < 0 is true

Outside the course: using equals to compare a String with an object that is not a String.

String word = "INTERFACE";
System.out.println(word.length());
System.out.println(word.indexOf("FACE"));
System.out.println(word.indexOf("E"));
System.out.println(word.indexOf("X"));
System.out.println("Cat".equals("cat"));
System.out.println("cat".compareTo("dog") < 0);
System.out.println("pear".compareTo("pear"));
System.out.println("plum".compareTo("pear") > 0);

Output:

9
5
3
-1
false
true
0
true

indexOf("E") gives 3, the first E, even though there is another E at index 8.

Watch out: compare String contents with equals, not ==. The == operator checks whether two references point to the same object:

String a = "go";
String b = new String("go");
System.out.println(a.equals(b));
System.out.println(a == b);

Output:

true
false

a and b hold the same characters, but they refer to two different objects.

7. One character, empty strings and null

A string identical to the single character at position index can be created with substring(index, index + 1) 1.15.B.3. The last character is s.substring(s.length() - 1).

String s = "ROBOT";
System.out.println(s.substring(2, 3));
System.out.println(s.substring(s.length() - 1));
int pos = s.indexOf("B");
System.out.println(s.substring(pos, pos + 1));

Output:

B
T
B

Empty string or no string? "" is the empty string: a real String object with length 0, so "".length() is 0, and s.substring(i, i) returns "" for any i from 0 to s.length(). null means no object at all: if s is null, s.length() throws a NullPointerException 1.14.A, 1.15.B.

String empty = "";
System.out.println(empty.length());
System.out.println("ROBOT".substring(3, 3).length());
String none = null;
System.out.println(none.length());

Output:

0
0
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "none" is null

Background (not tested): characters and capitals. Java also has a char type ('A') and methods such as charAt and toUpperCase. char is outside the course and those methods are not on the Java Quick Reference, so use substring in exam answers. compareTo compares character codes, so all capital letters come before lowercase ones: "Zoo".compareTo("apple") is negative. On the exam, strings are “ordered based upon the alphabet”, so most questions use the same case throughout.

System.out.println("Zoo".compareTo("apple") < 0);

Output:

true

Exam traps

  • substring(from, to) stops BEFORE to. The number of characters returned is to - from.
  • Compare String contents with equals, not ==. The == operator checks whether two references point to the same object.
  • A String method result that is not stored is lost: w.substring(1); leaves w unchanged.
  • Left to right: 1 + 2 + "3" + 4 + 5 is "3345", because 1 + 2 is added before any text appears.
  • The to argument of substring may equal length(); an index past that throws a StringIndexOutOfBoundsException.

Simulator and checkpoint for 1.15 →

Notes done

Now check yourself

Close the notes and take each topic's checkpoint. Retrieval practice works better for memory than reading again.

Start with the 1.1 checkpoint →

Was this page helpful?

No names are ever shown, and every public comment is checked by us first. Please do not include personal details. To get a reply, email [email protected].

↑ Top

Enlarged view of the selected figure