AP Computer Science :: Lessons :: Object-Oriented Programming
Classes
Every program involves at least one object, which is something that is created and manipulated by the program's operations. An object has a state and a behavior that describe the object and explain what it is doing.
A class is a blueprint for implementing objects. An object is a single instance of a class. You can think of a class like a blueprint for a house, and the objects as the actual houses that were built from the blueprint. Below is the framework for a bank account class.
public class BankAccount { private String myPassword; private double myBalance; public static final double OVERDRAWN_PENALTY = 20.00; // Default constructor // Construct bank account with defaults public BankAccount() { } // Constructs bank account with password and balance public BankAccount(String password, double balance) { } // accessor public double getBalance() { } // mutator public void deposit(String password, double amount) { } // Withdraw amount from bank account with given password public void withdraw(String password, double amount) { } }
The public keyword means the class is usable by all programs. A private class would only be accessible to classes within the same program. Public methods are also available to all programs, but their private variables are not. A static final variable is also known as a constant, and cannot be changed by any code.
Methods
A method provides the behaviors for an object as well as the operations that manipulate an object. All method headers, except for constructors and static methods, are declared like so:
public void withdraw(String password, double amount)
public: The access specifier determines what other methods can call this method.
void: The return type specifies what variable type the method must return. Void indicates the method does not have to return a value.
withdraw: This is the name of the method.
(String password, double amount): The parameter list contains all variables that must be sent to the method.
A constructor is a special type of method that creates an object of a class. It always has the same name as the class and does not have a return type. The default constructor has no parameters and sets default values for the object.
public BankAccount() { myPassword = ""; myBalance = 0.0; }
The declaration
BankAccount b = new BankAccount()
will construct a new BankAccount object with a balance of 0 and a password equal to the empty string. The instance b will store a reference to the object itself as you can see below.

An object with parameters must send values, or arguments, for each of the required parameters.
public BankAccount(String password, double balance) { myPassword = password; myBalance = balance; }
The declaration
BankAccount c = new BankAccount("IndianaJ", 800.00)
will construct a new BankAccount object with a balance of 800 and a password equal to "Indiana J."

b and c are both object variables that store the address of the BankAccount objects. They do not store the objects themselves.
An accessor method accesses a class object without altering the object. It returns some information about the object, which usually involves one or more of the instance variables.
public double getBalance() { return myBalance; }
The getBalance method simply returns the value of the myBalance variable. It can be used in the following way:
BankAccount b1 = new BankAccount("HomerS", 25.00); BankAccount b2 = new BankAccount("MontyB", Double.MAX_VALUE); if (b1.getBalance() > b2.getBalance()) ...
The dot operator (.) is used to indicate that getBalance() is a method included with the BankAccount class, which b1 and b2 are instances of.
A mutator method changes the state of an object by modifying at least one of its instance variables.
public void deposit(String password, double amount) { myBalance += amount; } public void withdraw(String password, double amount) { if (myBalance >= amount) myBalance -= amount; else myBalance -= OVERDRAWN_PENALTY; }
A mutator method is invoked in the same way as an accessor, using the dot operator.
b1.withdraw("HomerS", 200.0);
b2.deposit("MontyB", 2000000.0);
A static method is a method that performs an operation for the entire class, not for its objects.
public static double getInterestRate() { System.out.println("Enter bank account interest rate"); System.out.println("Enter in decimal form:"); double rate = IO.readDouble(); return rate; }
A static method is invoked by calling it upon the class as a whole, not upon an instance.
double interestRate = BankAccount.getInterestRate();
Finally, an overloaded method is a group of methods in the class with the same name, but different parameter lists.
public int product(int n) { return n * n; } public double product(double x) { return x * x; } public double product(int x, int y) {return x * y; }
The compiler determines which method to use by looking at the parameter list. The return type is not considered and two methods with the same parameter list will cause an ambiguous method error.
Variable Scope
The scope of a variable is the region in which that variable is accessible. This applies to methods as well. All instance variables, static variables, and methods of a class belong to that class' scope, which is within the opening and closing curly brackets of the class. All of these variables can be accessed within the class without using the dot operator.
A local variable is defined inside a method or inside a statement (such as a loop or if statement). These variables are only accessible inside the {} pair of the block and are removed from memory once the block ends.
The this keyword refers to the current instance of an object. You can access all instance variables using the this keyword, but it isn't necessary unless there is a conflict between an instance variable and a local variable.
public void deposit(String password, double amount) { this.myBalance += amount; }
The this keyword is not required in the method above since myBalance would be recognized as an instance variable.
private int num; private int denom; public Rational(int num, int denom) { this.num = num; this.denom = denom; }
The this keyword is required above since the num and denom instance variables would conflict with the local method variables without it.
Expressions
Every expression in Java has a type. We have already discussed objects, but the other type of expression is a primitive data type. A primitive data type is predefined by the programming language and uses a reserved keyword. There are 8 primitive types in Java, although we will only focus on a few of them.
Data Type | What It Stores |
---|---|
int | Stores positive or negative numbers with no decimals. |
double | Stores positive or negative numbers with decimals. |
boolean | Either true or false. |
char | Stores single characters. |
You can find the range of an integer by using the Integer.MAX_VALUE and Integer.MIN_VALUE constants. These are especially useful for error checking.
Strings are actually objects because they are a collection of chars. More specifically, an array of chars is used to create a string. You can use the following arithmetic operations on integers and doubles:
Addition | + |
Subtraction | - |
Multiplication | * |
Division | / |
Modulus (Remainder) | % |
You can also use the addition operator for concatenating strings as long as at least one of the operands is a string. The following are valid expressions using the addition operator for concatenation:
Expression | Value |
---|---|
"book" + "worm" | "bookworm" |
.5 + "baked" | ".5baked" |
2 + 2 + " = 4" | "4 = 4" |
"2 + 2" + " = 4" | "2 + 2 = 4" |
"Nintendo" + 64 | "Nintendo64" |
Division can be tricky when it comes to programming. When you divide two integers the result is truncated, not rounded. That means a result of 2/3 would be 0, not 1.
You can use casting to round integers instead of truncate them. Casting allows one data type to be converted to another. To cast to an integer or a double you simply put (int) or (double) in front of the value you want to cast. To round positive integers you would do the following:
(int)(x + .5)
Modulus simply calculates the remainder obtained from division. For example, 9 % 5 would give you a result of 4 since 9/5 has a remainder of 4.
Assignments & Logical Operators
An assignment in programming assigns a value to the right of an equal sign to the expression on the left of the equal sign. The following are all assignment operators.
Assignment | = |
Add-Then-Assign | += |
Subtract-Then-Assign | -= |
Multiply-Then-Assign | *= |
Divide-Then-Assign | /= |
Modulus-Then-Assign | %= |
The last five assignments operators are compound assignments that perform an operation on the left-side expression and then store the result in the same expression. You can also use the increment or decrement operators (++) or (--) to increase or decrease an expression by 1.
Comparing expressions is a very important part of programming and comparisons must be made between compatible types. Below are the different comparison operators you can use in Java:
Equal To | == |
Not Equal To | != |
Less Than | < |
Less Than Or Equal To | <= |
Greater Than | > |
Greater Than Or Equal To | >= |
Logical NOT | ! |
Logical AND | && |
Logical OR | || |
An expression involving the above operators always evaluates as either true or false so the type of the entire expression is a boolean. When you use the logical AND or OR operators they are evaluated from left to right. They also stop execution as soon as the final value is known. This is known as short-circuit evaluation where the second argument of an expression is only evaluated if the first argument is sufficient to determine the expression. For example, in the following expression the second argument will not evaluate because the first argument is true.
(5 > 0) || isPrime(54321)
The same is true of the next expression involving logical AND except the second argument does not evaluate because the first argument is false.
(5 < 0) && isPrime(54321)
When evaluating logical statements De Morgan's laws are useful to remember. De Morgan's laws are rules relating the logical AND and OR operators in terms of negation. That means the following statements are true:
! (x && y) == !x || !y ! (x || y) == !x && !y
To prove that the above laws are true you can use something known as a truth table. A truth table is a mathematical table used to compute the value of logical expressions. Below is a truth table involving the four expressions for De Morgan's laws.
x | y | !(x && y) | !x || !y | !(x || y) | !x && !y |
---|---|---|---|---|---|
false | false | true | true | true | true |
false | true | true | true | false | false |
true | false | true | true | false | false |
true | true | false | false | false | false |
You can see from the truth table that De Morgan's laws hold since the expressions that the laws say are equal have the same boolean values.
If Statements
An if-else statement runs some code if a condition is true and another block of code if the condition is not true. The condition must evaluate to a boolean so you can use any of the comparisons operators discussed above. Below are two example if statements, one with an else statement and one without.
if (condition){ statement; statement; } if (condition) statement; else { statement; statement; }

Notice that the curly brackets are optional if there is only one statement associated with an if or else statement. Also note that you do not put a semicolon at the end of an if or else line. The curly brackets are used instead. The flowchart to the right illustrates how if and if-else statements work.