Classes and objects: fields, methods, get/set
A class is a template, an object is an instance made from that template. Creating objects with new, instance variables, the dot operator, private fields and get/set methods, reference variables and null. The biggest topic of the final starts here.
Until now you wrote everything inside main and in static methods. Real programs, however, are made of objects: accounts in a banking application, players in a game, students in a school system. Every object has its own data (fields) and its own behavior (methods). This week you will write your first classes. On the final, this topic comes as a writing question: “write a class with these fields and methods, create two objects in main”.
Golden rules:
- A class is a template, an object is an instance. From a
Dogclass you can make as many dog objects as you like. - Every object has its own fields. Changing one does not affect another.
- A variable holds not the object but the object’s reference.
b = adoes not create a new object. - Fields private, access through public methods (get/set).
- Instance methods are not static and are called on an object.
The first class
class Dog {
String name; // instance variables (instance variables / fields)
int age;
void bark() { // instance method (instance method): NO static
System.out.println(name + " (" + age + ") says Hav!");
}
}
A class defines a type. By itself it runs nothing; there is no main in it. The code that uses it is in the main of another class:
Dog d1 = new Dog(); // create a new object (instantiation)
d1.name = "Karabas";
d1.age = 3;
d1.bark();
Dog d2 = new Dog();
System.out.println(d2.name + " " + d2.age);
d2.name = "Pamuk";
d2.bark();
d1.bark();
Karabas (3) says Hav!
null 0
Pamuk (0) says Hav!
Karabas (3) says Hav!
Observations:
new Dog()creates a new Dog object in memory and returns its address.d1holds this address.- With the dot operator you access the object’s field and method:
d1.name,d1.bark(). - The
nameinsidebark()is the field of the object that called the method.d1.bark()prints Karabas,d2.bark()prints Pamuk. - Before d2 is given values, its fields are at their default values: String null, int 0. (Local variables inside a method have no such default.)
A file can contain several classes, but only one can be public, and the file name is its name. In real projects each class goes in its own file: Dog.java, Main.java.
Encapsulation: private fields, get and set
If the fields were public, anyone could write acc.balance = -5000;. To prevent this, the fields are made private and controlled public methods are exposed. This is called encapsulation.
class Account {
private String owner;
private double balance;
public String getOwner() { return owner; } // get (accessor)
public void setOwner(String newOwner) { owner = newOwner; } // set (mutator)
public double getBalance() { return balance; } // NO set for balance
public void deposit(double amount) {
if (amount > 0) balance += amount;
}
public void withdraw(double amount) {
if (amount <= balance) balance -= amount;
else System.out.println("Insufficient funds");
}
}
Account acc = new Account();
acc.setOwner("Deniz");
acc.deposit(500);
acc.withdraw(200);
acc.withdraw(1000);
System.out.println(acc.getOwner() + " " + acc.getBalance());
acc.deposit(-50);
System.out.println(acc.getBalance());
Insufficient funds
Deniz 300.0
300.0
The balance can only change through deposit and withdraw, and both check the rules. If you try to access it directly from outside:
Acc a = new Acc();
a.balance = 1000;
Main.java:7: error: balance has private access in Acc
| Access modifier | Who can access? |
|---|---|
private | only inside the same class |
public | everywhere |
| (none) | classes in the same package |
get/set naming
| Field | get | set |
|---|---|---|
private String name | public String getName() | public void setName(String n) |
private int age | public int getAge() | public void setAge(int a) |
private boolean active | public boolean isActive() | public void setActive(boolean a) |
The return type of a get method is the type of the field, and it has no parameters. A set method is void, and its parameter has the type of the field. You do not have to write a set for every field: for a field like the balance that should not be changed directly, no set is written.
Validation
class Thermostat {
private double celsius;
public void setCelsius(double value) {
if (value >= 5 && value <= 35) celsius = value; // out of range is rejected
}
public double getCelsius() { return celsius; }
public double getFahrenheit() { return celsius * 9 / 5 + 32; }
}
// in main:
Thermostat t = new Thermostat();
t.setCelsius(45);
System.out.println(t.getCelsius());
t.setCelsius(22.5);
System.out.println(t.getCelsius() + " " + t.getFahrenheit());
0.0
22.5 72.5
45 was rejected, the field stayed at the default 0.0. getFahrenheit is not a field, it is a value computed from a field; there is no need to store it separately.
Reference variables
A primitive variable holds the value itself. An object variable holds the object’s reference (its place in memory).
Account a = new Account();
a.deposit(100);
Account b = a; // the reference was copied, not the object
b.deposit(50);
System.out.println(a.getBalance() + " " + b.getBalance());
System.out.println(a == b);
Account c = new Account();
c.deposit(150);
System.out.println(a == c);
150.0 150.0
true
false
a ──┐
├──► [Account: balance 150.0]
b ──┘
c ─────► [Account: balance 150.0] another object
With objects, == looks not at the contents but at whether it is the same object. The balances of a and c are equal but they are different objects: false. (This is also why we use equals with Strings.)
null
The value of a reference that points to no object is null. Calling a method through a null reference crashes the program:
Account n = null;
n.deposit(10);
NullPointerException
The code compiles, because the compiler only looks at the type (Account has deposit). The error appears at run time.
The difference between static and instance methods
main is static; it does not belong to an object. Instance methods, on the other hand, belong to an object. That is why, from main, an instance method is called on an object:
Acc a = new Acc();
System.out.println(Acc.getBalance()); // with the class name: WRONG
Main2.java:8: error: non-static method getBalance() cannot be referenced from a static context
The correct way is a.getBalance(). Whose balance? a’s. The class does not have a single balance; each object has its own. You will see static fields, which all objects share, in week 12.
| static method | instance method | |
|---|---|---|
| How it is called | Math.sqrt(4), ClassName.m() | object.m() |
| Is an object needed | No | Yes |
| Access to fields | Cannot access instance fields directly | Accesses the fields of its own object |
| Example | isPrime(int n), main | deposit, getBalance |
Worked example: a class writing question
Question: “Write a Rectangle class: private int width and height, set methods, getWidth(), methods that return the area and the perimeter.”
class Rectangle {
private int width, height;
public void setWidth(int w) { width = w; }
public void setHeight(int h) { height = h; }
public int getWidth() { return width; }
public int area() { return width * height; }
public int perimeter() { return 2 * (width + height); }
}
Grading is usually like this: the private declaration of the fields, the correct header of each method (the return type!), the correct formula in the body, and creating an object with new in main and calling the methods with a dot. For a 3 by 4 rectangle the area is 12 and the perimeter is 14.
Common mistakes
| Wrong idea | The truth |
|---|---|
Dog d; creates an object | It only declares a reference; the object comes with new Dog() |
An instance method is written static | Instance methods are not static |
Account.getBalance() | On an object: acc.getBalance() |
| Fields are undefined at the start, it does not compile | They get a default value: 0, null, false |
| Two objects share the same fields | Each object has its own copy |
b = a; copies the object | It copies the reference; the same object |
a == b compares contents | It checks whether it is the same object |
| Make the fields public, it is easier | private + get/set, for validation |
| A get method is void | It returns the type of the field |
| A set method returns a value | Usually void |
| A method call on a null reference does not compile | It compiles, NullPointerException while running |
Test yourself
Exam-style questions. Solve them on paper first, then reveal the answer.
Counter has a private int count, increment() adds 1 to it and getCount() returns it. What is printed?
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println(c1.getCount() + " " + c2.getCount());Show answer
Two separate news, two separate objects. Each object has its own count field. c1's counter is 2, c2's is 1.
Using the same Counter class, what is printed?
Counter c3 = new Counter();
Counter c4 = c3;
c3.increment();
c4.increment();
c4.increment();
System.out.println(c3.getCount());Show answer
c4 = c3 does not create a new object; both point to the same object. The three increment calls increase the same count: 3.
deposit adds the amount only if it is positive; withdraw subtracts only if the amount is not more than the balance, otherwise it prints Insufficient funds. What is printed?
Account a = new Account();
a.deposit(300);
a.withdraw(100);
a.withdraw(250);
a.deposit(-20);
System.out.println(a.getBalance());Show answer
200.0
Deposit 300 → 300. Withdraw 100 → 200. 250 > 200 → not withdrawn, the message is printed. -20 is not positive → ignored. Because balance is a double, 200.0 is printed.
Dog has fields String name; and int age; with no initial values. What is printed?
Dog d = new Dog();
System.out.println(d.name + " " + d.age);Show answer
Instance variables, unlike local variables, get a default value: object references (String) get null, int gets 0. That is why there is no compile error.
What is printed?
class Box {
private int size = 1;
public void setSize(int s) { if (s > 0) size = s; }
public int getSize() { return size; }
public int volume() { return size * size * size; }
}
// in main:
Box bx = new Box();
bx.setSize(4);
bx.setSize(-2);
System.out.println(bx.getSize() + " " + bx.volume());Show answer
The set method does validation: -2 is invalid, the field does not change. size stays 4, the volume is 4 * 4 * 4 = 64. This is the real benefit of a private field: an invalid value cannot get in.
Using Account (deposit adds positive amounts), what is printed?
Account p = new Account();
Account q = new Account();
p.deposit(100);
q = p;
q.deposit(25);
p = new Account();
p.deposit(5);
System.out.println(p.getBalance() + " " + q.getBalance());Show answer
After q = p both point to the first account; 100 + 25 = 125. Then p is redirected to a new account (q is still on the old one) and 5 is deposited. The empty object that q originally pointed to is no longer pointed to by anyone.
Rectangle has private int width and height, setters, getWidth(), area() and perimeter(). What is printed?
Rectangle r = new Rectangle();
r.setWidth(3);
r.setHeight(4);
System.out.println(r.area() + " " + r.perimeter());
r.setWidth(r.getWidth() * 2);
System.out.println(r.area());Show answer
24
The area is 3 * 4 = 12, the perimeter is 2 * (3 + 4) = 14. The width is read with get and set to twice its value: 6. The new area is 6 * 4 = 24.
What is printed?
class Light {
private boolean on;
public void toggle() { on = !on; }
public boolean isOn() { return on; }
}
// in main:
Light l = new Light();
l.toggle();
l.toggle();
l.toggle();
System.out.println(l.isOn());Show answer
A boolean field starts as false. Each toggle flips it: true, false, true. By convention, boolean getters start with is: isOn().
balance is declared private in class Acc. Which statement in main (another class) does not compile, and why?
Acc a = new Acc();a.balance = 1000;System.out.println(a.getBalance());a.deposit(50);
Show answer
A private field can be accessed only from inside its own class. javac: balance has private access in Acc. Access from outside is done through public methods (getBalance, deposit).
What happens when this code runs?
Account n = null;
n.deposit(10);Show answer
null means the reference points to no object. Since the compiler looks at the type, the code compiles, but when you call a method of an object that does not exist while running, a NullPointerException is thrown.
Write the withdraw method of Account (private double balance): subtract amount only if it is positive and not more than the balance; otherwise print Insufficient funds.
Show answer
An instance method is not static; it uses the object's field directly.public void withdraw(double amount) { if (amount > 0 && amount <= balance) { balance -= amount; } else { System.out.println("Insufficient funds"); }}The example version on this page checks only amount <= balance; amount > 0 was added to block negative withdrawals too.
Write a class Thermostat with a private double celsius, a setter that accepts only values from 5 to 35 (inclusive), a getter, and a method getFahrenheit().
Show answer
class Thermostat { private double celsius; public void setCelsius(double value) { if (value >= 5 && value <= 35) celsius = value; } public double getCelsius() { return celsius; } public double getFahrenheit() { return celsius * 9 / 5 + 32; }}Test: setCelsius(45) is rejected, getCelsius() → 0.0 (the default). setCelsius(22.5) → 22.5, getFahrenheit() → 72.5. Because celsius is a double, * 9 / 5 does not fall into the int division trap.
Verification: All outputs were run with JDK 26 (verify/SEN1001/W10.java; the classes Dog, Account, Thermostat, Counter, Box, Rectangle and Light are in the same file). The answer to the withdraw writing question was run as is in the Account2 class in W11.java. The private access and static context errors were obtained with javac under verify/SEN1001/err/priv/.