Liang Chapters 9 & 10: Encapsulation, Immutable Objects, Scope, Static Members, Passing Objects, Arrays of Objects, Aggregation, Garbage Collection, Strings, Wrappers, and BigDecimal
Encapsulation means making data fields private and providing public getter and setter methods to access and modify them. This protects data from invalid states and hides internal implementation. (Liang, Section 9.9)
For a field xyz: getter is getXyz(), setter is setXyz(value). For boolean fields: getter is isXyz(). (Liang, Section 9.9)
boolean field called active?getActive()isActive()active()hasActive()is instead of get. (Liang, Section 9.9)An immutable object is an object whose state cannot be changed after it is created. An immutable class is a class whose objects are immutable. The String class is a well-known example. (Liang, Section 9.10)
1. All data fields must be private.
2. No setter (mutator) methods.
3. No methods that can modify the object's state.
4. The class itself can be declared final to prevent subclasses from adding mutability.
Once an ImmutableCircle is created, its radius can never be changed. To get a circle with a different radius, you must create a new object.
finalThe scope of a variable determines where in the program it can be accessed. Java has three types of variable scope: local variables, instance variables, and class (static) variables. (Liang, Section 9.8)
| Type | Declared In | Scope | Lifetime |
|---|---|---|---|
| Local | Inside a method or block | From declaration to end of block | Method execution |
| Instance | Inside a class (no static) | Entire class | Object's lifetime |
| Class (static) | Inside a class with static | Entire class | Program's lifetime |
If a local variable has the same name as an instance variable, the local variable shadows (hides) the instance variable within that scope. Use this.variableName to refer to the instance variable. (Liang, Section 9.8)
What are the two lines of output?
A static member belongs to the class, not to any particular object. Static variables are shared by all instances. Static constants are declared with static final. (Liang, Section 9.7)
| Instance | Static | |
|---|---|---|
| Belongs to | Each object | The class |
| Access | obj.member | ClassName.member |
| Memory | One copy per object | One copy shared by all |
• A static method cannot access instance variables or use this.
• An instance method can access both static and instance members.
• Static constants (static final) should use UPPER_CASE naming. (Liang, Section 9.7)
thisthis reference and cannot access instance members directly. It can only access static members. (Liang, Section 9.7)What is the output?
When you pass an object to a method, you are passing the reference (memory address), not a copy of the object. This means the method can modify the original object's data fields. This is different from passing primitive types, which passes a copy of the value. (Liang, Section 9.6)
| Passing Primitives | Passing Objects |
|---|---|
| A copy of the value is passed | A copy of the reference is passed |
| Changes inside the method do NOT affect the original | Changes to the object's fields DO affect the original |
int x = 5; change(x); | Circle c = new Circle(5); change(c); |
What is the output? (Hint: swapping references inside a method does NOT affect the caller)
You can create an array that holds references to objects. Each element of the array is a reference variable that must be initialized with new before use. (Liang, Section 9.11)
Circle[] circles = new Circle[3]; creates the array, but each element is null. You must create each object individually with new Circle(). Accessing circles[0].getArea() before initialization causes NullPointerException!
Circle[] c = new Circle[5];, what is c[0]?nullnull until you assign an object with new. (Liang, Section 9.11)What is the output?
Aggregation and composition model "has-a" relationships between objects. A class can have a data field that references another object. The difference is about ownership and lifecycle. (Liang, Section 9.11)
In aggregation, the contained object is created outside and passed to the container. It can exist independently.
In composition, the contained object is created inside the container. Its lifecycle depends on the container.
| Aggregation | Composition | |
|---|---|---|
| Relationship | Weak "has-a" | Strong "has-a" |
| Object creation | Created outside, passed in | Created inside the container |
| Lifecycle | Independent | Dependent on container |
| UML | Hollow diamond ◊ | Filled diamond ♦ |
new inside; composition does notnew (strong ownership). Aggregation: object passed in from outside (weak ownership, independent lifecycle). (Liang, Section 9.11)Java automatically reclaims memory occupied by objects that are no longer referenced. This process is called garbage collection. You don't need to manually free memory like in C/C++. (Liang, Section 9.10)
• An object becomes eligible for garbage collection when no references point to it.
• The JVM runs the garbage collector automatically — you cannot force it.
• System.gc() only suggests that the JVM run GC — it is not guaranteed.
• Setting a reference to null does not immediately destroy the object.
delete on itnullnull doesn't make it garbage if another reference still points to it. (Liang, Section 9.10)How many objects are eligible for garbage collection? (Hint: Object A is still referenced by c, Object B is still referenced by a)
Strings are immutable objects in Java. Any operation that appears to modify a String creates a new String object. (Liang, Section 10.10)
| Method | Description | Example |
|---|---|---|
length() | Number of characters | "Hello".length() → 5 |
charAt(i) | Character at index i | "Hello".charAt(1) → 'e' |
substring(i, j) | Substring from i to j-1 | "Hello".substring(1, 4) → "ell" |
equals(s) | Compare content | "Hi".equals("hi") → false |
equalsIgnoreCase(s) | Compare ignoring case | "Hi".equalsIgnoreCase("hi") → true |
indexOf(s) | First index of s | "Hello".indexOf("ll") → 2 |
toUpperCase() | To uppercase | "hello".toUpperCase() → "HELLO" |
trim() | Remove whitespace | " Hi ".trim() → "Hi" |
== compares references. .equals() compares content. Always use .equals() to compare string values!
toUpperCase() return a new String — the original is unchanged. (Liang, Section 10.10)What are the three lines of output?
Wrapper classes let you use primitives as objects. Java automatically converts between them: autoboxing (primitive → wrapper) and unboxing (wrapper → primitive). (Liang, Section 10.7)
| Primitive | Wrapper | Primitive | Wrapper |
|---|---|---|---|
int | Integer | float | Float |
double | Double | char | Character |
long | Long | boolean | Boolean |
BigInteger handles arbitrarily large integers. BigDecimal provides exact decimal arithmetic, avoiding floating-point errors. Use methods (add, subtract, multiply, divide) instead of operators. (Liang, Section 10.9)
Always create BigDecimal from a String, not a double. new BigDecimal(0.1) captures the imprecise double value. Use new BigDecimal("0.1") instead. (Liang, Section 10.9)
a and b?a + ba.add(b)BigInteger.add(a, b)add(a, b)+ don't work. (Liang, Section 10.9)