- Learn
- Computer Science & IT
- Programming
- Object-Oriented Programming with Java
- Java Classes and Objects
Java Classes and Objects
toString, and finish by designing, building and testing a complete class from a short description.BeginnerLesson 5 of 11 in Object-Oriented Programming with Java Course
What you will learn
- Explain how a class defines a new type of data with its own behavior, and create and use objects of that type in a program.
- Explain what a class and an object areDescribe a class as the definition of a type, an object as one instance of it, and state and behavior as what objects hold and do.
- Create objects and call their methodsCreate objects with
new, call methods on them with dot notation and predict how separate objects behave.
- Explain what a class and an object are
- Declare the instance variables that hold an object's state and write constructors that give every new object valid starting values.
- Declare instance variablesDeclare fields with suitable types, know their default values and tell them apart from local variables and parameters.
- Write constructors that initialize objectsWrite constructors that set every field, use
thisto tell fields from parameters and avoid the mistakes that leave fields unset. - Offer several constructors and chain themOverload constructors for different ways of creating an object, and use
this(...)so the setup code is written once.
- Declare instance variables
- Write instance methods that read and change an object's state, trace their effect, and decide when something belongs to an object or to the class as a whole.
- Write instance methods that use and change stateWrite methods that report on or change an object's fields, call other methods of the same object and trace the state of objects step by step.
- Tell instance members apart from static membersUse
thisfor the current object, decide what should be static and fix the errors that come from mixing static and instance code.
- Write instance methods that use and change state
- Hide fields behind access modifiers, give controlled access through getters, setters and meaningful methods, and keep every object in a valid state.
- Hide data with access modifiersUse
private, package access,protectedandpublicto control which code can use a class's members, and explain why fields are kept private. - Write getters and settersWrite accessor and mutator methods with the standard naming, and decide which fields need them and when a meaningful method is better.
- Keep objects valid with checksDefine the rules an object's state must follow, enforce them in constructors and methods, and avoid handing out internal data that bypasses those checks.
- Hide data with access modifiers
- Give objects a readable text form with
toString, then design, write and test a complete class from a short description.- Write a toString methodWrite a
toStringmethod that returns a readable description of an object, and know when Java calls it automatically. - Design, build and test a complete classTurn a short description into a class with fields, constructors, methods and rules, then test every behavior from a main program.
- Write a toString method
Java Classes and Objects study guide
1Classes, objects, and method calls
A program often needs to keep several related values together: a pet's name, species, and age, for example. A class gives that group a type and puts the actions that use it in one place. You will connect class definitions with the objects created while a program runs, then follow method calls to see which object's data changes. The distinction between a class, an object, and a variable will help you read the code you write next.
1.1 A type with state and behavior
A class defines a type: the data its objects remember and the operations they offer. An object, also called an instance, is one value of that type created while a program runs. Writing a class definition does not create an object.
State and behavior
A pet's name, species, and age make up its state. Those current values live in instance variables, also called fields. An operation such as celebrating a birthday is behavior, written as a method. The birthday method belongs with the age it changes, so the rule is kept in one place.
Think of a class as a building plan. Many houses can follow one plan, but each house has its own contents. Likewise, two pets can follow the same definition and have different ages. You write the field names once; each object gets its own values.
Read a small class
public class Pet {
private String name;
private String species;
private int age;
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
public void celebrateBirthday() {
this.age++;
}
}
Read this from the outside in. public class Pet introduces the type, and the outer braces contain its definition. The first three declarations describe state. The block named Pet is a constructor: it gives a new object its first values. celebrateBirthday is a method: it increases the current object's age. The words private and public control access; later examples use them to protect state.
The constructor's parameters are values supplied when an object is created. In this.age = age;, the left side names the object's field and the right side names the supplied parameter. The constructor stores that input so the object can remember it after construction ends.
Put a class to work
You have already used library classes. Scanner describes objects that read input, ArrayList describes lists, and a String object offers operations such as length(). A class you write follows the same basic idea: it makes a useful type available to the rest of your program.
Without Pet, a program might pass a name, species, and age separately to many methods. It must keep each group together correctly. A Pet object carries the related values as one unit. Methods on that object know which age they should use.
Organize and name the code
For ordinary source files, a public class named Pet is saved in Pet.java, with matching capitalization. A separate Main class can contain the program's main method, create pets, and call their methods. Pet needs no main of its own. Classes in the same unnamed package can use one another without imports; the simple examples keep those classes in one folder.
Use UpperCamelCase nouns for classes, such as LibraryBook. Use lowerCamelCase for fields and methods: pageCount names data; giveBack() names an action. These are conventions that help a reader recognize each part, even though the compiler allows many other names.
Key Takeaways
- A class defines a type; an object is one instance created while the program runs.
- Fields hold state, and methods provide behavior.
- Objects of one class follow the same definition and hold their own instance-field values.
- A public class in an ordinary source file uses the matching class name as its filename.
1.2 New objects and the references that reach them
Creating an object and declaring a variable are different operations. A variable gives you a name through which to reach an object; new creates the object that the name will refer to.
Read an object-creation statement
Pet luna = new Pet("Luna", "cat", 3);
Pet is the variable's type, and luna is its name. new Pet(...) creates a new object and calls a matching constructor with three arguments. The constructor stores the name, species, and age. The resulting reference is assigned to luna.
A reference tells Java which object to use. It is useful to draw a variable as a name with an arrow to an object. The variable is not a second copy of all the object's fields.
Call a method on a particular object
The dot in luna.celebrateBirthday() connects a reference with a method to run on its object. A returning method can supply a value to another expression:
luna.celebrateBirthday();
int years = luna.getAge();
System.out.println(years); // 4
Here getAge() is a public method that returns the pet's age. The birthday call changes state; the getter reads that state. Pet.celebrateBirthday() fails because this instance method needs a particular pet. The class name alone does not answer whose birthday it is.
Separate objects and shared references
Pet max = new Pet("Max", "dog", 5);
luna.celebrateBirthday();
System.out.println(luna.getAge()); // 5
System.out.println(max.getAge()); // 5
Luna was already 4, so the next birthday takes her to 5. Max stays 5. Equal ages do not make them the same object: the two new expressions created separate pets.
Now consider an assignment with no new:
Pet other = luna;
other.celebrateBirthday();
System.out.println(luna.getAge()); // 6
The assignment copies Luna's reference. Both names reach one pet, so changing it through other is visible through luna. To make a second pet, call new again.
Match the constructor's parameters
Arguments must fit a declared constructor's number, order, and types. If the only available constructor takes (String, String, int), new Pet() fails to compile. Java does not guess missing values. Swapping the two strings, however, still compiles: new Pet("cat", "Luna", 3) supplies the right types but the wrong meanings. Read the parameter names to check that order.
These two unfinished attempts fail for different reasons:
Pet a; // declaration only
// System.out.println(a.getAge()); // a has no assigned value
// Pet b = Pet("Bo", "cat", 2); // missing new
A local variable must be assigned before it is used. Without new, Java searches for a method named Pet, not an object-creation expression. Once an object exists, printing it may show text like Pet@8bcc55f until you supply a readable toString() method; that output does not mean construction failed.
Key Takeaways
- Use new with arguments that match an available constructor.
- Dot notation calls an instance method on the object reached by a reference.
- Another new expression creates another object; reference assignment shares an existing one.
- Arguments of the same type can be swapped without a compiler error, so check their meanings.
- A local declaration alone creates no object and gives the variable no usable value.
2Fields and the first state of an object
Objects need somewhere to keep their data and a reliable way to get their first values. Fields provide the storage; constructors set up each new object. You will choose field types, separate lasting state from temporary local work, and follow construction from default values to a ready object. Then you will offer several useful ways to create the same kind of object while keeping shared setup and checks in one place.
2.1 Data that an object remembers
An object needs a field for each value it must remember between method calls. Choose those values before writing methods: they form the object's lasting state.
Declare fields with suitable types
A field sits inside the class braces but outside every constructor and method. A declaration needs a type and a name; an access modifier and an initializer can also appear.
private String title;
private int pageCount;
private boolean lentOut = false;
String suits text, int suits a whole-number count, and boolean suits a yes-or-no condition. Fields can also use class types such as ArrayList<String>. These examples use private; leaving the modifier out gives package access, not private access.
Every object gets a separate copy of each instance field. Two Rectangle objects each have a width and a height, even though the declarations appear only once in the class.
Defaults are not always usable starting values
| Field type | Default value |
|---|---|
int, long | 0 |
double | 0.0 |
boolean | false |
Class types, including String and ArrayList | null |
A default is assigned to a field when storage for the object is created. It may not fit the object's purpose. A list field with the value null is not an empty list: you still need to create the list before adding an item.
Local variables receive no such default. Inside a method, int total; followed by System.out.println(total); fails to compile because total has not been assigned. Keep the field rule and the local-variable rule separate.
Decide what must last
| Kind of variable | Where it is declared | What it is for |
|---|---|---|
| Instance field | In the class, outside methods | Values remembered by one object |
| Parameter | In a constructor or method header | Inputs for that call |
| Local variable | Inside a method or constructor block | Temporary work for that call |
A field remains with its object. A parameter is available during its call, and a local variable is available in its block while that call runs. If a counter must retain its count from one call to the next, the count belongs in a field. A temporary subtotal used for one calculation can be local.
Store the inputs; calculate derived values
public class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double area() {
return this.width * this.height;
}
}
The dimensions are in centimeters, so area() returns an area in square centimeters. Storing a separate area field would create another value to update whenever either dimension changed. Computing it from the dimensions keeps the answer consistent.
Use an instance final field for a value assigned once, such as private final String title;. Give it a value in its declaration or in every constructor. final prevents reassignment. static has a different meaning: it creates one shared class field. Adding static to a pet's name would make different pets share one name variable.
Key Takeaways
- Instance fields are declared outside methods and remember each object's state.
- Fields receive defaults; local variables must be assigned before use.
- Choose fields for lasting data and locals for temporary work.
- Calculate values that follow from stored fields to avoid inconsistent copies.
- An instance final field is assigned once; a static field is shared by the class.
- A null list field still needs a list object before it can be used.
2.2 From arguments to initialized fields
A constructor sets up an object when new creates it. Its name must match the class, and it has no return type. Even void would turn the declaration into a method.
Transfer inputs into state
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
A constructor usually accepts inputs as parameters and stores them in fields. Here each parameter has the same name as its field. The bare name age means the parameter; this.age means the field of the object being created. The assignment reads the supplied value on the right and writes the field on the left.
For new Pet("Luna", "cat", 3), first the new object's fields receive defaults: null, null, and 0. The constructor then receives the three arguments and replaces those defaults. When construction finishes, new produces the reference that the caller stores.
Two bugs that compile
public Pet(String name, String species, int age) {
name = name;
this.species = species;
this.age = age;
}
Both occurrences of name refer to the parameter, so the first line assigns that parameter to itself. The object's name stays null. The code is legal, which is why checking the new object's values matters.
A declaration inside the constructor causes a related problem:
String nick = initialNick;
If a field named nick already exists, this line creates a local variable with the same name. The local disappears when construction ends. Write this.nick = initialNick; to store the input in the field; do not repeat the type.
Know when a no-argument constructor exists
If a class declares no constructors, Java supplies a default constructor with no parameters. For a simple class, its fields keep their declared initializers or default values. As soon as you declare any constructor, Java stops supplying that default one.
A class with only Pet(String name, String species, int age) therefore cannot be created with new Pet(). Add an explicit no-argument constructor only when there is a useful starting state for it. Also watch for public void Pet(...): that is a method, so it does not provide the intended constructor at all.
Set internal starting values too
Not every field needs to come from an argument. A new book can always start with this.lentOut = false;. A class that owns a list can initialize it like this, with ArrayList imported:
private ArrayList<String> tracks;
public Playlist() {
this.tracks = new ArrayList<>();
}
The empty list is ready for add. Leaving tracks at null makes a later tracks.add(...) fail with NullPointerException.
A field initializer runs before the constructor body. If private int score = 10; is followed by this.score = 5; in the constructor, the finished object's score is 5. Test the values after construction, not just the values written beside the field declarations. Constructors also need the same validation rules as later changes, so the first state is valid.
Key Takeaways
- A constructor has the class name and no return type.
- Use this.field = parameter when the names match.
- Neither parameter self-assignment nor a new local variable initializes the intended field.
- Java supplies a default constructor only when the class declares no constructors.
- Initialize internal state such as empty lists, and apply validation during construction.
2.3 Several ways to construct one kind of object
A class can offer several useful ways to create an object. Constructor overloading means declaring constructors with different parameter lists.
Distinguish constructors by parameters
Java tells constructors apart by the number, types, and order of their parameters. Parameter names do not distinguish them. Box(String label) and Box(String name) describe the same parameter list, so they cannot both be declared in one class.
A pet may be created with an age or as a newborn:
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
public Pet(String name, String species) {
this(name, species, 0);
}
new Pet("Pip", "rabbit") selects the two-parameter constructor. That constructor supplies 0 as the missing age and calls the three-parameter constructor. The new object ends with the state "Pip", "rabbit", and 0.
Chain setup on the same object
Inside a constructor, this(...) calls another constructor of the same class. The shorter constructor chooses defaults; the fuller constructor does the shared setup. Checks placed in that setup apply to both construction routes.
Contrast two lines that look similar:
| Line inside a constructor | Effect |
|---|---|
this(name, species, 0); | Initializes the current object through another constructor |
new Pet(name, species, 0); | Creates a separate pet |
The second line does not fill the current object's fields. If its result is never stored, that extra pet is discarded. The current pet may still have null fields.
Follow a chain before tracing later code
A clock can offer midnight as a default:
public Clock() {
this(0, 0);
}
public Clock(int hours, int minutes) {
this.hours = hours;
this.minutes = minutes;
}
For new Clock(), enter the no-argument constructor, follow this(0, 0), and assign both fields in the two-argument constructor. Then control returns to the no-argument constructor. This creates one clock, not two. A call to new Clock(9, 5) starts directly in the fuller constructor.
Keep the chain legal and clear
A constructor can contain at most one this(...) call. The chain must eventually reach setup that does not call back into the chain: two constructors that delegate to each other cause a compile-time recursive-constructor error.
Putting this(...) first is a clear style that works across Java versions. In Java 24 and earlier without preview features, it must be first. Java 25 allows earlier statements for tasks such as computing or checking arguments. Those statements cannot read the current object's instance fields or call its instance methods; assignments to fields declared in the class without declaration initializers are allowed.
Offer overloads because callers have different useful inputs. A midnight clock is meaningful; a book with no title may not be. The existence of a full constructor does not create any shorter overloads automatically.
Key Takeaways
- Overloaded constructors differ by parameter lists, not parameter names.
- The call this(...) delegates to another constructor on the same object.
- Keep shared initialization and checks in one construction route.
- A constructor chain must not circle back to a constructor already in that chain.
3Methods that read and change state
A useful object can answer questions about itself and carry out actions that change its state. Instance methods put those operations next to the fields they use. You will trace changes one statement at a time, handle a clock's rollover, and return values that other code can use. You will also decide which data belongs to each object and which data or operations belong to the class, so that separate objects stay separate.
3.1 Calculations, changes, and state traces
An instance method runs for one particular object. Declare it without static, and use fields of that object through names such as this.width. Decide what the caller needs: a state change, a returned result, or both.
Return calculations; keep state changes explicit
For a rectangle whose dimensions are stored in centimeters:
public double area() {
return this.width * this.height;
}
public double perimeter() {
return 2 * (this.width + this.height);
}
public void scale(double factor) {
this.width = this.width * factor;
this.height = this.height * factor;
}
A rectangle with sides 3.0 and 4.0 has area 12.0 square centimeters and perimeter 14.0 centimeters. scale(2) changes the sides to 6.0 and 8.0. The next calls return area 48.0 and perimeter 28.0. Each method reads the current fields, so no stored area needs updating.
area() returns a number that can be stored or used in a calculation. If it only printed the number and had return type void, the caller could not write double twice = r.area() * 2;. Leave printing to the caller when a method's job is to compute a value.
Update related fields in order
A clock's advance() method must handle both minute and hour rollover:
public void advance() {
this.minutes++;
if (this.minutes == 60) {
this.minutes = 0;
this.hours++;
if (this.hours == 24) {
this.hours = 0;
}
}
}
At 23:58, the first call reaches 23:59 and skips both reset blocks. The next call briefly reaches minute 60, resets it to 0, raises the hour to 24, and resets that to 0. The finished state is 00:00. One more call gives 00:01.
Trace objects separately
Write a row after each statement and a column for each object's fields. Change only the object named by the receiver of the call. For pets aged 2 and 7, two birthdays on the first pet and setAge(1) on the second leave ages 4 and 1. Do not run a method's body for every instance just because they share a class.
A local declaration can hide the field you meant to update. public void reset() { int count = 0; } only creates a temporary variable. this.count = 0; resets the lasting count.
Reuse methods and complete return paths
Within an instance method, area() and this.area() call the same object's area method. A description method can reuse that calculation instead of copying its expression. A method may also change state and return success, as lend() does when it marks a book as borrowed and reports true.
A non-void method cannot simply reach the end without returning a compatible value. If get() returns only inside if (count > 0), what happens when the count is 0? Add the needed return path or throw an exception for a value the method rejects. A path that throws does not return to the caller and needs no return value.
Key Takeaways
- Instance methods read or change the state of the object they are called on.
- Return computed values so callers can use them in expressions.
- Trace statements in order, keeping each object's fields separate.
- Rollover methods must restore every related field to its allowed range.
- Reuse other methods of the same object by calling them directly or with this.
- A returning method needs a value on every path that returns normally.
3.2 Per-object members and shared class members
Ask who owns a value or an operation before deciding whether to use static. A pet's age belongs to one pet. A count of all pets created belongs to the class as a whole.
The current object is this
Inside a constructor or instance method, this refers to the object being constructed or receiving the call. In this.age++, it identifies whose age changes. In this.name = name, it separates the field from a same-named parameter. this(...) is the constructor-chaining form.
A static method has no current object, so this cannot be used there. It may still create an object or receive a reference and use that reference to call instance methods.
Shared fields and per-object fields
public class Counter {
private int count;
private static int created = 0;
public Counter() {
this.count = 0;
created++;
}
public void increment() {
this.count++;
}
public int getCount() {
return this.count;
}
public static int getCreated() {
return created;
}
}
After two new Counter() calls, there are two separate count fields, both initially 0, and one created field equal to 2. Incrementing the first counter changes its count to 1; the second stays 0. Counter.getCreated() still returns 2 because no new object was constructed.
Work through an object from main
public static void main(String[] args) {
Counter c = new Counter();
c.increment();
System.out.println(c.getCount());
}
The classic main method is static. A bare call to increment() there would have no target object and would fail to compile. The variable c supplies that target. Making count static to silence the error would change the design: every counter would then share one count.
| Kind of method | Direct access available |
|---|---|
| Instance method | Its instance members and the class's static members |
| Static method | Static members; instance members through an object reference |
Java 25 also supports instance forms of main, but the classic static header remains valid. These examples use it consistently.
Choose methods and constants deliberately
An operation that needs an object's fields should be an instance method. An operation that depends only on its parameters can be static, like a helper that converts a total number of minutes into hours. Static calls normally use the class name: Math.sqrt(16) or Counter.getCreated().
A shared fixed value is usually declared as a constant:
public static final int MAX_CELSIUS = 30;
public makes it available to callers, static gives the class one shared field, and final prevents reassignment. UPPER_SNAKE_CASE signals a constant by convention. This is a common exception to making fields private. Do not use static for ordinary names, dimensions, or other state that must differ between objects.
Key Takeaways
- The reference this identifies the current object inside instance code.
- Static members belong to the class; instance members belong to individual objects.
- A static method needs an object reference to use instance members.
- Fix static-context mistakes by supplying the right object when the state belongs to an object.
- A public static final field commonly provides a shared constant.
4Controlled access and valid state
A class should control the values that can enter its state. Private fields and public methods let the class check each change and give callers useful operations. You will choose access levels, write getters and setters where they help, and protect rules such as an allowed temperature range. You will also see why a private list can still escape through a getter and how to keep outside code from bypassing the class's checks.
4.1 Private state and a public interface
Encapsulation keeps an object's state together with the code that controls it. Fields are usually private, while callers use public operations. This hides storage details and gives the class a place to enforce its rules.
Choose an access level
| Access | Who can use the member |
|---|---|
private | Code in the same class |
| No modifier | Code in the same package |
protected | The same package, plus subclass access under Java's subclass rules |
public | Code that can access the declaring type |
A package groups classes. The simple examples place ordinary classes together without a package declaration, in one unnamed package. Package access is the result of leaving the modifier out; there is no package access keyword to add to a field.
Start with the narrowest useful access. Make fields private, constructors and operations needed by other classes public, and internal helper methods private. Public constants are a common exception for fields.
Put the class in charge of changes
If Pet declares private int age;, a separate Main class cannot assign luna.age = -5;. The compiler rejects the access. A call such as luna.setAge(-5) can be allowed, because the public method belongs to Pet and can decide whether to store the argument.
A public field would let any caller bypass that method. Once all changes go through the class's code, the checks can live in one place. Private access alone does not validate an age; the methods must perform the checks too.
Keep the public interface stable
Suppose a clock initially stores separate hours and minutes fields. Callers use getHours() and getMinutes(). You later replace the fields with a single minutesSinceMidnight value:
public int getHours() {
return this.minutesSinceMidnight / 60;
}
public int getMinutes() {
return this.minutesSinceMidnight % 60;
}
With 615 stored minutes, division returns 10 and remainder returns 15. The clock reports 10:15 through the same methods. Callers do not need rewriting because they depended on the public operations, not on how the state was stored. This freedom to change internals is information hiding.
Access belongs to classes, not individual objects
Code inside Pet can read a private field of another Pet object. The access permission comes from being inside the class. A different top-level class does not gain permission by holding a pet reference or being in the same folder.
For ordinary top-level class declarations, the access choices are public or no modifier. A top-level private class Pet is illegal. A public top-level class goes in the matching source file, and one ordinary source file contains at most one public top-level class.
Private fields are a program-design boundary. They prevent other ordinary code from depending directly on internal fields, but they are not a way to keep a value secret from a person who can inspect the program. Use them to control your class's interface and protect its state.
Key Takeaways
- Private fields and public operations keep control of state inside the class.
- Leaving out an access modifier gives package access.
- Public methods let internal storage change without changing callers.
- Private access is checked by class, so code inside the class can access another instance's fields.
- Ordinary top-level classes use public or package access.
4.2 Access methods that fit the class
A class can let callers read or change selected parts of its state through methods. Decide which operations the class should offer before creating access methods for every field.
Return values with getters
A getter, also called an accessor, returns information without changing the object. A common getter reads a field:
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
The returned type matches the information being supplied. A getter that prints and returns void cannot give a value to an expression such as pet.getAge() + 1. The caller should receive the value and decide how to use it.
Change selected values with setters
A setter, also called a mutator, takes a new value and updates state:
public void setName(String name) {
this.name = name;
}
this.name is the field. name is the parameter. Writing name = name; compiles but changes no field. There is no return value here because this setter's job is to perform a change.
For a pet whose age is 3:
luna.setName("Lulu");
System.out.println(luna.getName() + " is " + luna.getAge());
// Lulu is 3
The caller never touches a field directly. The setter changes the name, and the getters return the current values for the caller to combine.
Follow names that other Java code expects
| Field | Getter | Setter, if needed |
|---|---|---|
pageCount | getPageCount() | setPageCount(int pageCount) |
name | getName() | setName(String name) |
lentOut | isLentOut() | setLentOut(boolean lentOut) |
Capitalize the first letter of the field name after get, set, or the usual boolean prefix is. A name such as getname() may compile, but it does not follow the convention that tools and other programmers expect.
Expose only useful operations
A book's title may have a getter and no setter because callers should read it but not replace it. A private final field can enforce that it is assigned once. An internal counter may need neither getter nor setter if only the class uses it.
An unchecked setter can accept the same damaging value as a public field. Add checks where a change has restrictions. Also consider an action method: celebrateBirthday() expresses increasing the age by one, and lend() expresses a lending attempt. lend() can inspect the current state and reject a second loan. A setter can perform that check too; the action name makes the operation clearer to its caller.
A getter can compute an answer. getArea() may return the product of width and height without any area field.
Key Takeaways
- A getter returns information; a setter changes a selected value.
- Follow getName, setName, and the usual boolean isName naming pattern.
- Give fields only the access methods that callers need.
- Action methods such as lend express allowed behavior clearly and can check transitions.
4.3 Rules that survive every change
An invariant is a rule about an object's state that holds after construction and after every public operation. A thermostat might allow targets from 5 °C through 30 °C. Every way to set its target must preserve that range.
Choose what invalid input means
Three useful responses are to keep the old value, clamp the value to a limit, or throw an exception. They have different effects, so choose a clear response for each operation.
| Response | Result of an invalid call |
|---|---|
| Ignore | The old field value stays unchanged |
| Clamp | The nearest allowed boundary is stored |
| Throw | The call stops with an error such as IllegalArgumentException |
For a nonnegative pet age, an ignoring setter can assign only inside if (age >= 0). If the stored age is 4, setAge(-2) leaves it at 4. It does not turn the age into 0.
Put range checks inside the class
public static final int MIN_CELSIUS = 5;
public static final int MAX_CELSIUS = 30;
private int target;
public void setTarget(int celsius) {
if (celsius < MIN_CELSIUS) {
this.target = MIN_CELSIUS;
} else if (celsius > MAX_CELSIUS) {
this.target = MAX_CELSIUS;
} else {
this.target = celsius;
}
}
public void raise() {
setTarget(this.target + 1);
}
Starting at 20 °C, setTarget(35) stores 30. setTarget(-3) stores 5. After setTarget(29), a call to raise() stores 30; another call still stores 30. Reusing the setter prevents raise() from slipping past the upper limit.
Checks in Main alone cannot protect the thermostat. Another caller could forget them. The class must check the input at the place where it controls storage.
Validate the first state too
public Thermostat(int target) {
setTarget(target);
}
With this clamping constructor, new Thermostat(50) finishes at 30 °C. Directly assigning this.target = target; would allow the invalid first state of 50. A shared private checking method is another way to reuse validation in constructors and later methods.
Throwing is useful when an invalid argument signals a programming error. For example, a constructor can reject a negative count with throw new IllegalArgumentException("count must not be negative");. The object is not successfully constructed, so no invalid finished object is given to the caller. Ignoring input is simpler but silent; the caller may need another way to notice that nothing changed.
Keep mutable internal data inside
A private list can still escape if a getter returns the original list. A caller could then add or remove entries without using the class's methods, bypassing a maximum-size rule.
For an ArrayList<String> field named tracks, return new ArrayList<>(this.tracks); gives a separate list containing the same strings. Changing that returned list does not change the internal list. Operations such as addTrack(String title) can keep list changes inside the class and check its rules before accepting them.
Key Takeaways
- An invariant holds after construction and after each public operation.
- Ignoring, clamping, and throwing are different responses to invalid input.
- Every constructor and state-changing method must preserve the same rules.
- Reuse validation so different change routes cannot bypass it.
- Returning an internal mutable list lets callers bypass the class's checks.
- A copy of an internal string list protects the original list from outside list changes.
5Readable objects and complete classes
Readable object descriptions make it easier to use and check a class. A toString method supplies that text wherever an object is printed or joined to a string. You will write the method with the right header, then bring fields, constructors, methods, and validation together in a complete class. Starting from a short description, you will turn requirements into code and test normal calls, repeated actions, and boundary cases.
5.1 An object description returned as text
A useful object should be easy to inspect as text. Java's built-in toString() returns a class name, an @ sign, and a hexadecimal hash code, such as Pet@8bcc55f. A named package becomes part of the class name. The hash text varies and usually says little about the object's state.
Return a readable description
@Override
public String toString() {
return this.name + " (" + this.species + ", "
+ this.age + " years)";
}
For Luna, a cat aged 3, the returned string is "Luna (cat, 3 years)". The method reads fields and builds a string. It does not change the pet or send output to the screen.
@Override asks the compiler to check that the declaration really replaces an existing method. That catches errors such as writing tostring with a lowercase s. It does not format the result for you; the return expression determines the text.
Recognize automatic calls
System.out.println(luna);
String label = "Pet: " + luna;
String details = luna.toString();
The first line prints the pet's readable description. The second builds "Pet: Luna (cat, 3 years)". The third asks for the same description explicitly and stores it without printing. When an ArrayList of pets is printed, its display uses each pet's toString() inside the list's square delimiters.
Automatic conversion is why returning text matters. The caller may be printing, storing, or joining the result. A method that only prints cannot supply the string needed by all those callers.
Match the method header
| Declaration | What happens |
|---|---|
public String toString() | Supplies the object description |
public String tostring() | Declares a different method; @Override catches it |
public String toString(int width) | Declares an overload; automatic printing does not call it |
public void toString() | Fails: it conflicts with the existing String-returning method |
Use the exact no-argument header and include the annotation. An overload with parameters may be a valid separate method, but printing an object does not provide those parameters.
Format values without changing them
A clock needs two-digit hours and minutes. Inside its toString() method:
return String.format(java.util.Locale.US,
"%02d:%02d", this.hours, this.minutes);
For hours 9 and minutes 5, the string is "09:05". Each %02d formats an integer in at least two positions, using a leading zero when needed. String.format(java.util.Locale.US, "%.2f", 7.5) returns "7.50". Supplying the locale makes the decimal-point output independent of the computer's default formatting locale.
Keep the description short enough to read while debugging. It can reveal unset state: joining a null name field to a string produces the text "null", which points you back to initialization. The description should report the current state, so printing the object twice should not advance a clock or celebrate a birthday.
Key Takeaways
- Write public String toString() with no parameters and return readable text.
- The annotation @Override lets the compiler check that the method replaces an existing one.
- Printing an object and joining it to a string use toString automatically.
- Keep toString free of state changes and let its caller decide where text goes.
- String.format can pad values and use an explicit locale for predictable output.
5.2 From a requirement to a tested class
Start with what one object must remember, what callers can ask it to do, and which states must be allowed. Then turn each part into fields, constructors, and methods.
Extract the design from a description
"A library book has a title, an author, and a page count. It can be lent out and given back. It cannot be lent out again while already on loan."
Use LibraryBook as the class name. Store the three descriptive values and a boolean loan status. The title, author, and page count stay fixed, so make them final. The loan status changes through meaningful actions. A setter for every field is unnecessary.
Build the complete class
public class LibraryBook {
private final String title;
private final String author;
private final int pages;
private boolean lentOut;
public LibraryBook(String title, String author, int pages) {
this.title = title;
this.author = author;
this.pages = pages;
this.lentOut = false;
}
public boolean isLentOut() {
return this.lentOut;
}
public boolean lend() {
if (this.lentOut) {
return false;
}
this.lentOut = true;
return true;
}
public void giveBack() {
this.lentOut = false;
}
@Override
public String toString() {
String status = this.lentOut ? "lent out" : "available";
return this.title + " by " + this.author + ", "
+ this.pages + " pages, " + status;
}
}
The constructor establishes availability. lend() checks the existing state before changing it; returning false on a second loan preserves the rule. giveBack() makes the book available. The getter reports status, and toString() describes the whole book without changing it.
Write expectations before running calls
In a separate Main class's classic main method:
LibraryBook b = new LibraryBook("Night Train", "A. Rivera", 320);
System.out.println(b); // Night Train by A. Rivera, 320 pages, available
System.out.println(b.lend()); // true
System.out.println(b.lend()); // false
b.giveBack();
System.out.println(b.lend()); // true
The second loan attempt is essential: a method that always sets the flag and returns true would pass the first call but fail this check. Test state as well as return values with isLentOut(). Also try a second book to check that a loan on one book leaves the other available.
Test where behavior changes
Cover every constructor and public method. For range checks, try both endpoints and values just outside them. For a clock, check minute rollover and midnight rollover. For a rejecting or ignoring setter, check that invalid input has the promised effect on the old state. Write the expected result first so an unexpected output does not quietly become your new expectation.
Build in small increments: fields and constructor first, then a readable description, then one operation and its checks at a time. Save ordinary public classes in matching files, compile them together, and run the class containing main. Keeping model operations separate from screen output lets the same class serve different programs.
Key Takeaways
- Turn remembered data into private fields and allowed actions into methods.
- Write the state rules before implementing constructors and changes.
- Use final for fixed per-object values and avoid unnecessary setters.
- Test return values and resulting state, including repeated calls and separate objects.
- Check boundaries and invalid input as well as ordinary values.
- Build and test one useful part at a time.
- Keep model behavior separate from the main program that prints results.
Java Classes and Objects examples
1From one class to two pets
10 steps
- 1IntroductionA type for the things in your program
A pet program needs to remember a name, species, and age together. A class gives that group a type and offers methods that use it. Each object is one pet created from that definition.
Follow the difference between the definition and the pets it produces. Then trace two pet objects and see why an extra variable does not always mean an extra object.
- 2AnalogyA plan and its instances
Think of a class like a building plan and its objects like houses built from it. The plan describes what each house contains, but it is not a house itself.
One
Petdefinition can describe many pets. Each has fields for the same kinds of data, yet one can be a three-year-old cat and another a five-year-old dog. Defining the fields creates the plan; object creation supplies actual instances. - 3ExampleFind state and behavior
A pet's fields
name,species, andagestore its state. For Luna, their values are"Luna","cat", and3.The method
celebrateBirthday()provides behavior. Its body can executethis.age++;, changing the receiving pet's age. The method is part of the class definition; the value it changes belongs to a particular pet. - 4ChallengeDoes a definition create a pet?
A programmer writes a
Petclass with three fields and a birthday method. No object-creation expression has run. How many pet objects has that definition created?---reveal---
None. The class defines a type and its available state and behavior. Objects appear when the program creates them, for example with
new Pet(...). Three field declarations describe three pieces of data per pet, not three pets. - 5ExampleCreate the first object
Read
Pet luna = new Pet("Luna", "cat", 3);in parts.Pet lunadeclares a variable.new Pet(...)creates a pet and runs the constructor with the three supplied arguments.The constructor stores the starting values. The reference produced by
newis assigned toluna, giving later code a way to reach this object. DeclaringPet luna;alone would provide no object to call. - 6ExplanationCall a method on its receiver
In
luna.celebrateBirthday(), the expression before the dot identifies the receiver. The birthday method runs for Luna, increasing her age from 3 to 4.int age = luna.getAge();then retrieves the current age for use elsewhere.Pet.celebrateBirthday()cannot choose a pet: this is an instance method, and a class name supplies no particular object. - 7ExampleCreate a second pet
Now run
Pet max = new Pet("Max", "dog", 5);. A secondnewexpression creates a second object with its own fields.After another
luna.celebrateBirthday(), Luna is 5 and Max is still 5. Their equal ages do not make them the same object. A later birthday on Luna changes only Luna's age because Max's age lives in a different object's fields. - 8Key InsightAn assignment can share one object
Pet other = luna;copies Luna's reference. It does not call a constructor and does not copy her fields into another pet.The names
otherandlunanow reach the same object. Callingother.celebrateBirthday()changes that pet from age 5 to age 6, andluna.getAge()sees 6 too. Count object creations separately from variable declarations. - 9ChallengeTrace a shared reference and a separate pet
Two separate pets start with ages 1 for
aand 8 forb. The code runsPet c = a; c.celebrateBirthday(); b.celebrateBirthday();. What ages doaandbreport?---reveal---
They report 2 and 9.
csharesa's object, so its call increases that pet's age. The call throughbincreases the separate pet. The class supplies the same birthday behavior to both, but each call has its own receiver. - 10RecapRead creation and calls deliberately
Keep three roles separate: the class defines the type, each object holds its own instance state, and a reference variable reaches an object.
When reading code, mark each
new, match its arguments to the constructor, and identify the receiver before tracing a method call. A plain reference assignment adds a route to an existing object. A secondnewcreates a separate object with its own state.
2Build the first state correctly
14 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionGive every new object useful data
- 2ExplanationChoose lasting state
- 3ExplanationSeparate defaults from useful values
- 4ChallengePick a field or a local
- 5ExplanationRead the constructor header
- 6ExampleMove parameters into fields
- 7TipA legal assignment that stores nothing
- 8ChallengeFind the unchanged field
- 9ConnectionCreate internal objects too
- 10ExampleOffer a useful default route
- 11ExplanationFollow one object through the chain
- 12ChallengeDiagnose a misleading new expression
- 13ChallengeCombine a fixed field with an overload
- 14RecapCheck each route to a finished object
3Trace changing state and shared state
13 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionFollow what each call changes
- 2ExplanationReturn a value to the caller
- 3ExampleScale the stored dimensions
- 4ChallengeCheck the returned result after a change
- 5ExampleAdvance through midnight
- 6TipRepair a reset that changes no state
- 7Key InsightAccount for every normal return
- 8ExplanationSeparate two counts from one shared counter
- 9ExampleSupply an object in static code
- 10ConnectionRecognize a constant
- 11ChallengeTrace the two kinds of state
- 12ChallengeFind why separate objects change together
- 13RecapMatch each operation to its owner
4Protect every route into state
14 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionMake the class responsible for its rules
- 2ExplanationHide the field behind an operation
- 3TipChoose the smallest useful access
- 4ChallengeDecide where private access works
- 5ExampleReturn information with a getter
- 6ConnectionOffer actions that fit the object
- 7ChallengeRead without permitting replacement
- 8ExplanationChoose a policy for invalid input
- 9ExampleTrace clamping at the upper limit
- 10ExampleCheck the first state
- 11ChallengeTrace ignoring instead of clamping
- 12Key InsightA private list can still escape
- 13ChallengeClose both unchecked routes
- 14RecapAudit the public interface
5Build and test a useful class
12 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionTurn a requirement into visible behavior
- 2ExplanationUse the exact description header
- 3ExampleReturn the current state as text
- 4TipFormat a clock without changing it
- 5ChallengeRepair automatic printing
- 6ExampleChoose fields from the requirement
- 7ExampleEstablish the starting status
- 8ExampleImplement the rule before the change
- 9ChallengePredict a sequence before running it
- 10ConnectionTest the cases an easy run misses
- 11ChallengeDistinguish reporting from changing
- 12RecapBuild with a testable public promise
Java Classes and Objects practice questions
Set 1: Create objects and read their state10 Practice Questions
Question 1 of 10
Parcel class to create several parcels. What is one parcel created while the program runs called?Show answerHide answer
Parcel. The class definition describes the data and operations for all those objects; it is not another name for one particular parcel. A method is an operation the object can perform.Question 2 of 10
Bell object is stored in bell, and ring() is an instance method. How should the program ring that bell?Show answerHide answer
ring() on the object reached by bell. The variable before the dot supplies the receiver that an instance method needs. Bell.ring() names the class instead, so it cannot select this bell for an instance call.Question 3 of 10
private int attempts; with no initializer or constructor assignment. What value does a new object store in this field?Show answerHide answer
int instance field receives the default value 0 before explicit initialization. The rule requiring assignment before reading an uninitialized local variable does not apply to fields. null is the default for class-type fields, not an int field.Question 4 of 10
new Badge("Visitor"), getText() returns null. The field is private String text;, the getter returns it, and the constructor body is text = text;. How should the constructor store its text parameter?Show answerHide answer
this.text = text; writes the input into the current object. Reversing the assignment reads the still-null field into the parameter instead, and assigning the field to itself also leaves it unset.Question 5 of 10
Ticket() { this(4); } and Ticket(int zones) { this.zones = zones + 1; }. What value does new Ticket() store in zones?Show answerHide answer
Question 6 of 10
MinuteClock stores hours 0–23 and minutes 0–59. advance() adds one minute with hour and midnight rollover. isMidnight() checks for 00:00. Starting at 23:57, run advance(); advance(); advance(); if (isMidnight()) { advance(); } advance();. What is the final time?Show answerHide answer
Question 7 of 10
Lamp must remember its own on/off state. How should that state be declared?Show answerHide answer
Question 8 of 10
Bin field is written as int capacity; without an access modifier. What access does it have?Show answerHide answer
private.Question 9 of 10
Session has private boolean active;. Callers need to check it but may change it only through start() and stop(). What accessor fits this design?Show answerHide answer
Question 10 of 10
public String toString() { return "Ready"; }. What text is produced by System.out.println("State: " + object);?Show answerHide answer
"Ready" combine into "State: Ready". Defining a custom no-argument toString() replaces the built-in class-and-hash description; Java does not attach that built-in text as an extra prefix.Set 2: Check initialization and controlled changes10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
private int reading = 9;. Its method is public void reset() { int reading = 0; }. What does a getter returning this.reading report after reset()?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Locker has an occupied field and a release() method. What part of this class describes behavior?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
Panel stores width and height. Its width can change, and getArea() must always report the current area. How should area be represented?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
public Sensor(int channel). A caller uses new Sensor(). Why does this fail to compile?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
minutesSinceMidnight field, while its getters still return the same values. Why can callers keep their existing getter calls?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
setValue(25) and then setValue(8), what are the stored values after each call?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
Group must hold at most four names. addName enforces the limit, but Group(ArrayList<String> names) stores the supplied list directly and getNames() returns the internal list. What design preserves the limit against changes made by callers?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
toString() use?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
use() returns false if already used; otherwise it sets the flag and returns true. reset() clears the flag. toString() only reports it. What do the use calls return in use(); println(pass); use(); reset(); use(); use();?Show answerHide answer
Save this lesson to see this answer.
Set 3: Follow object state through longer sequences10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Marker has a name and setName. Run Marker a = new Marker("One"); Marker b = a; a = new Marker("Two"); b.setName("Three");. What do a.getName() and b.getName() return?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
private int level = 6;. Its constructor is public Beacon(int level) { this.level = level + 2; }. What does new Beacon(3) store?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
public Tag(String text). What additional constructor provides a distinct overload?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
scale(k) multiplies both dimensions by k; area() returns their product. Run scale(2); double saved = area(); scale(0.5);. What are saved and the final area()?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Dial class has instance field value and static field created, both initially 0. Each constructor increments created once; turn() increments only its receiver's value. Run Dial a = new Dial(); Dial b = a; b.turn(); b = new Dial(); b.turn(); b.turn();. What are a.value, b.value, and created?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
private String label;. What implementation supplies that value to its caller?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
setLevel. The constructor calls that setter, and raise() calls setLevel(this.level + 1). Starting with new Level(13), run raise(); setLevel(-2); raise(); raise();. What is the final level?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
String.format(java.util.Locale.US, "%02d:%02d", 4, 7) return?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Seat must refuse a second reservation until canceled. A test currently checks only the first successful reserve() call. What next call best checks the refusal rule?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
Show answerHide answer
Save this lesson to see this answer.
Set 4: Diagnose designs and combine the rules10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Pump class represent this?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Token has a numeric value and addOne() increases it. Run Token a = new Token(2); Token b = a; b.addOne(); Token c = new Token(7); a = c; a.addOne(); b.addOne();. What values do a, b, and c report?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
add(int amount) currently declares int total = amount; inside the method. What storage change makes accumulation possible?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
A Bucket declares private int capacity = 2; and an empty instance list items. Its constructor is Bucket(int capacity) { capacity = capacity; }. add returns false without adding when the list size is at least the stored capacity; otherwise it adds the item and returns true. snapshot() returns new ArrayList<>(this.items).
Run Bucket b = new Bucket(4); b.add("A"); ArrayList<String> view = b.snapshot(); view.add("B");. Then call b.add("C") and b.add("D"). What do these last two calls return, and how many items does b finally hold?
Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Route has final field code and static field created, initially 0. Its constructors are Route() { this("local"); created++; } and Route(String code) { this.code = code; created++; }. After one call to each constructor, created should count two objects. What correction gives the right count?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
advance() adds one minute with 24-hour rollover. getHour() reads the current hour. Run int h = getHour(); advance(); if (getHour() != h) { advance(); } advance();. What are h and the final time?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
scale. Its getter returns this.width * this.height, and there is no area field. Why is this a valid getter design?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Album has a limit of three captions. Its constructor rejects more than three captions and stores new ArrayList<>(captions). getCaptions() returns another copy; addCaption rejects additions at the limit. A caller supplies two captions, adds a third to the original list, adds a caption to a getter result, then calls addCaption once. How many captions does the Album hold?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
Door must refuse open() when locked. A fresh door starts closed and unlocked. lock() succeeds only while closed; unlock() removes the lock. What test sequence checks refusal while locked and then a successful open after unlocking?Show answerHide answer
Save this lesson to see this answer.
Stuck on your own question? Homework Help
Key Terms
A
Access modifier
private, protected, or public that controls access to a declaration.private access modifier keeps a helper available inside its class without exposing it to other classes.Action method
lend() action method checks current loan status, rejects a repeat loan, and reports whether lending succeeded.Argument
new Clock(9, 5), the arguments 9 and 5 supply the hour and minute for the new clock.B
Behavior
lend() and giveBack() so callers can manage its loan status.Boundary test
C
Clamping
Class
Pet class keeps a name, species, and age together with operations such as celebrateBirthday().Class design
Constant
static final field, often public and named in UPPER_SNAKE_CASE.MAX_CELSIUS constant supplies the same upper temperature limit to the class and to its callers.Constructor
Pet constructor copies the supplied name, species, and age into the new pet's fields.Constructor chaining
this(...) call.this(name, species, 0) to reuse setup with a default age.Constructor overloading
D
Default constructor
new Pet() needs an explicit overload.Default value
false; a local boolean must be assigned before it can be read.Defensive copy
new ArrayList<>(this.tracks) keeps outside list changes away from the internal list.Dot notation
luna.getAge() tells Java that the pet reached by luna should report its age.E
Encapsulation
Pet pairs a private age field with checking methods that refuse invalid changes.Expected result
lend() on a borrowed book is false with an unchanged loan flag.F
final field
G
Getter
get.getArea() getter can calculate width times height even when the class stores no separate area field.I
IllegalArgumentException
IllegalArgumentException is an exception a method or constructor can throw to reject an argument that breaks its input rules.IllegalArgumentException for a negative capacity prevents construction from returning an invalid object.Incremental development
Information hiding
getHours() consistent for existing callers.Initialization
new ArrayList<>() so entries can be added afterward.Instance
Pet when each is created separately.Instance method
scale is an instance method: a.scale(2) changes rectangle a while a separate rectangle stays unchanged.Instance variable
age instance variable keeps its own value even though the declaration appears only once in Pet.Invariant
L
Lifetime
Local variable
total inside a calculation method holds temporary work that the object need not remember.N
new
new begins an object-creation expression that runs a constructor and produces a reference to the object.new Pet("Luna", "cat", 3) creates a pet and supplies three arguments for its starting state.No-argument constructor
Clock() can delegate with this(0, 0) to start the clock at midnight.null
null means a reference has no object to reach; class-type fields receive it unless initialized differently.add on a list field still set to null fails because no list object was created.O
Object
new expressions can have different ages while following one class definition.P
Package access
int count; lets another class in the same unnamed package read or change the field.Parameter
age in a pet constructor receives 3 when the call supplies 3 in that position.private
private restricts member access to code inside its class, keeping separate top-level callers behind the public interface.pet.age = -1; fail in a separate Main class, requiring a controlled method call.protected
protected permits same-package access and restricted access from subclass code outside that package.public
public allows access to a member wherever the declaring type is accessible, so callers can use the exposed operation.lend() method lets Main request a loan while the book's private status field stays hidden.Public interface
lend(), giveBack(), and isLentOut() while its loan flag stays private.R
Read-only property
getTitle() but no operation to replace the title.Receiver
book.lend(), the receiver is the book reached by book, whose loan flag the method checks.Recursive constructor invocation
Box() and Box(int) delegate back to each other.Reference
Pet other = luna;, the two variables hold references to the same pet, so either can reach it.Return value
r.area() can be doubled in an expression; printing the area alone supplies no value.S
Scope
if block ends at that block, so later code cannot use its name.Setter
setAge(int age) setter can ignore negative inputs so the stored age stays in its allowed range.Shadowing
this.age = age; useful: the left side is the field, and the right side is the input.State
State trace
Static context
pet.getAge() instead supplies a particular object.Static field
created can rise each time the constructor sets up a new instance of the class.Static method
main can create Counter c and then call c.increment() through that reference.String.format
String.format builds text from a format string and values, supporting fixed widths and decimal places.String.format with java.util.Locale.US and "%.2f" formats 7.5 as "7.50" despite the default locale.T
this
this refers to the current object inside instance code, distinguishing its fields from same-named parameters.this.name = name; writes the new input into that particular pet's field.toString
toString() returns an object's text representation, allowing printing and string concatenation to show readable details.toString returns "09:05", so printing the clock shows a useful time instead of class-and-hash text.V
Validation
void
void declares that a method supplies no return value, even when the method changes state or prints output.void because its job is to increase the stored age of its receiver.#
@Override
@Override asks the compiler to verify that a method declaration replaces a method already provided by a supertype.@Override above tostring() reveals its capitalization error instead of leaving automatic printing unchanged.About this lesson
Make your own Study Materials
Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.