Classes and Objects
Scope: what a class is, creating objects with new,
fields, constructors, and encapsulation. All samples were
compiled and run with OpenJDK 21.
The idea
A class is a blueprint; an object is a thing built
from it. The class Dog describes what dogs have (a name)
and do (bark); each Dog object has its own name.
public class Dog {
String name; // a field: each dog's own data
void bark() { // a method: what dogs do
System.out.println(name + " says woof!");
}
public static void main(String[] args) {
Dog d1 = new Dog(); // build a Dog object
d1.name = "Rex";
d1.bark();
Dog d2 = new Dog();
d2.name = "Luna";
d2.bark();
}
}
Check: prints Rex says woof! then Luna says woof!.
Notes:
new Dog()builds the object;d1is a reference to it (think: a nametag tied to the dog, not the dog itself).bark()is notstatichere — it belongs to each object, and uses that object'sname. That's whymain(static) had to build dogs first: static code can't call instance methods without an object.
Constructors
d1.name = "Rex" after construction is clumsy. A
constructor runs at new time and sets things up:
public class Dog {
String name;
Dog(String name) { // the constructor: same name as the class,
this.name = name; // no return type
}
void bark() {
System.out.println(name + " says woof!");
}
public static void main(String[] args) {
Dog d = new Dog("Rex");
d.bark();
}
}
Check: prints Rex says woof!.
this.name means "this object's name field" —
needed because the parameter is also called name.
If you define no constructor, Java gives you a free
empty one (new Dog()).
Encapsulation: keep fields private
Direct field access (d.name = ...) works until someone
sets d.name = null and bark() prints null says
woof!. The fix: private fields plus methods that guard
them:
public class Dog {
private String name;
Dog(String name) {
setName(name);
}
void setName(String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name required");
}
this.name = name;
}
String getName() {
return name;
}
void bark() {
System.out.println(name + " says woof!");
}
}
private means "only code inside this class may touch
it." Outsiders go through getName/setName (called
getters and setters), where you can validate.
throw and IllegalArgumentException are Exceptions
— peek ahead if you're curious.
Static vs instance, finally
static |
instance (no static) |
|
|---|---|---|
| Belongs to | the class itself | each object |
| Called as | Math.sqrt(9) |
d.bark() |
| Can use | other statics only | fields, instance and static methods |
| Example | main, utility functions |
name, bark() |
Rule of thumb: if a method needs an object's data, it's
instance. If it's a pure calculation on its arguments,
static is fine.
Try it
In jshell, classes work too:
jshell> class Cat { String name; void meow() { System.out.println(name + ": meow"); } }
jshell> Cat c = new Cat(); c.name = "Miso"; c.meow();
Miso: meow
Next: Interfaces and Inheritance — how classes relate to each other.