Hello dear students! I am so glad you are here. Today we are going to learn one of the most important chapters in your Object Oriented Programming course: Classes and Objects in Java. This chapter is the foundation of everything else in OOP. If you understand this chapter well, the rest of the course becomes much easier. So please read each section carefully, try every example, and answer all the questions I give you. Let us start!
What is a Class in Java?
In our previous lesson about the introduction to OOP, we learned that a class is like a blueprint. Now let me explain this in much more detail with Java code.
A class in Java is a user-defined blueprint or template from which objects are created. It is a logical structure that defines what kind of data an object will hold and what kind of actions that object can perform. Think of it as a design plan. Just like an architect draws a plan of a house on paper before building it, a programmer writes a class before creating objects from it.
A class in Java is declared using the class keyword. Inside the class body (which is enclosed in curly braces), we write two main things:
- Fields (Instance Variables): These represent the data or state of the object. They tell us what information the object will store.
- Methods: These represent the behavior or actions of the object. They tell us what the object can do.
Let me show you the general syntax of a class declaration in Java:
Now let me write a real class that represents a Student. This is the kind of class you will often see in your exam.
Look at this code carefully. The class name is Student. It has four fields: name, age, department, and GPA. These fields will hold data for each student. It has two methods: study() and displayInfo(). These methods define what a student can do. Right now, this is just a blueprint. No actual student exists yet. We have only defined what a student WILL look like when we create one.
1. A class is declared using the
class keyword in Java.2. A class contains fields (data) and methods (behavior).
3. A class is a logical entity (it does not occupy memory for data, only for the class definition).
4. A class does NOT have any actual values in its fields. The fields are just declared, not initialized with specific values.
5. A class can have any number of fields and methods.
6. In Java, every class must be in a file. For a public class, the file name must match the class name (e.g., Student.java for public class Student).
Question 1: Which of the following correctly defines a class in Java?
A) A physical entity that occupies memory B) A blueprint from which objects are created C) A method that creates variables D) A keyword used to declare variables
Answer: B) A blueprint from which objects are created
A class is simply a blueprint or template. It defines the structure (fields and methods) but is not a physical entity itself. Option A describes an object, not a class. Option C is wrong because a class is not a method. Option D is wrong because class is not used to declare variables. The word “blueprint” is the key word to look for in the correct answer.
Question 2: The ________ keyword is used to declare a class in Java.
Answer: class
In Java, the class keyword is used to declare a new class. For example, class Student { } declares a class named Student. This is a reserved keyword in Java, meaning you cannot use it as a variable name or method name. Always write it in lowercase.
Question 3: A class in Java occupies memory for the data of its fields as soon as it is declared.
Answer: False
A class definition does NOT occupy memory for field data. Memory for data is allocated only when an object is created from the class using the new keyword. The class definition itself is loaded into memory (in the method area), but that is just the code/instructions, not the actual data values. Think of it this way: the blueprint of a house does not need land space, but the actual house built from it does.
What is an Object in Java?
An object is a real, physical instance of a class. If the class is the blueprint of a house, the object is the actual house built from that blueprint, sitting on a piece of land, taking up space. When you create an object, Java allocates memory for all the fields defined in the class, and that object now has its own copy of each field with its own values.
You can create many objects from the same class, and each object will be independent. Changing one object’s data does not affect another object’s data. This is a very important point to understand well.
In Java, an object is created using the new keyword. The general syntax is:
Let me break this down because every part is important for your exam:
- ClassName: The name of the class whose object you are creating.
- referenceVariable: A name you give to refer to this object. It is like a remote control for the object.
- new: This keyword tells Java to allocate memory for a new object.
- ClassName(): This calls the constructor of the class to initialize the object.
Now let me create objects from the Student class we wrote earlier:
Output:
See how s1 and s2 are two completely separate objects? Each one has its own name, age, department, and GPA. When I set s1.name to “Abebe”, it does not change s2.name. They are independent of each other. The reference variables s1 and s2 live in the stack, and the actual objects live in the heap.
1. An object is created using the
new keyword. Example: Student s1 = new Student();2. The
new keyword allocates memory in the heap for the object.3. The reference variable (like s1) is stored in the stack and holds the memory address of the object.
4. Each object has its own copy of instance variables. Changing one object does not affect others.
5. You can create any number of objects from one class.
6. The process of creating an object is called instantiation.
7. You access an object’s fields and methods using the dot operator (
.). Example: s1.name, s1.study().
Question 4: What does the new keyword do when creating an object in Java?
A) Declares a new variable B) Allocates memory for the object in the heap C) Deletes an old object D) Creates a new class
Answer: B) Allocates memory for the object in the heap
The new keyword tells the JVM to allocate memory space in the heap for the new object. It also calls the constructor to initialize the object’s fields. It does not just declare a variable (option A), it does not delete anything (option C), and it does not create a class (option D). Memory allocation in the heap is the key function of the new keyword.
Question 5: If you create three Student objects from the same Student class, how many copies of the instance variables exist in memory?
A) One B) Three C) Zero D) It depends on the number of fields
Answer: B) Three
Each object gets its own separate copy of all the instance variables. If the Student class has 4 fields (name, age, department, GPA) and you create 3 objects, then there are 3 separate copies of name, 3 separate copies of age, 3 separate copies of department, and 3 separate copies of GPA in memory. That is 12 variable slots total (3 objects times 4 fields each). Each object is independent with its own data.
Question 6: The reference variable and the object it points to are stored in the same memory area.
Answer: False
The reference variable (like s1) is stored in the stack memory, while the actual object it points to is stored in the heap memory. The reference variable holds only the memory address (a pointer) of the object, not the object itself. This separation is important to understand for memory-related exam questions.
Declaring and Initializing Fields
Fields (also called instance variables) are the data containers inside a class. Let me now explain how they work in more detail because there are some subtle points that examiners love to test.
When you declare a field without assigning a value, Java gives it a default value automatically. This is important because it is different from local variables (variables inside methods), which do NOT get default values.
| Data Type | Default Value |
|---|---|
| byte, short, int, long | 0 |
| float, double | 0.0 |
| boolean | false |
| char | ‘\u0000’ (null character) |
| Any object reference (String, etc.) | null |
Notice that name prints as null (not “null” with quotes, just null). This means the String reference is not pointing to any object. And ch prints as nothing because the null character has no visible symbol. These default values are assigned by Java when the object is created, before any constructor code runs.
1. Instance variables get default values automatically (0 for numbers, false for boolean, null for references).
2. Local variables (inside methods) do NOT get default values. You MUST initialize them before use, or you get a compile error.
3. The default value for any object reference type (including String) is
null.4. This difference between instance variables and local variables regarding default values is a very common exam question.
Question 7: What is the default value of an int instance variable in Java if you do not initialize it?
A) null B) 1 C) 0 D) Compile error
Answer: C) 0
For instance variables (fields declared inside a class but outside any method), Java automatically assigns default values. For integer types (byte, short, int, long), the default value is 0. The value null is only for reference types like String or objects. The value 1 is not a default. A compile error would only happen if this were a local variable, not an instance variable.
Question 8: A local variable declared inside a method gets a default value of 0 if it is not initialized.
Answer: False
Local variables (variables declared inside a method, constructor, or block) do NOT receive any default value in Java. If you try to use a local variable before assigning a value to it, the compiler will give an error. This is a strict rule in Java. Only instance variables (class-level fields) get default values. This is a very important distinction that examiners test frequently.
Access Modifiers for Fields
When you declare fields, you can use access modifiers to control who can access them. There are four access modifiers in Java, and you need to know all of them for your exam.
| Access Modifier | Same Class | Same Package | Subclass (different package) | Everyone |
|---|---|---|---|---|
| private | Yes | No | No | No |
| default (no keyword) | Yes | Yes | No | No |
| protected | Yes | Yes | Yes | No |
| public | Yes | Yes | Yes | Yes |
For now, the most important ones to understand are private and public. When we want to achieve encapsulation, we make fields private and provide public methods to access them. When we directly access fields from outside (like s1.name = "Abebe"), those fields need to be public or have no modifier (default). In good OOP practice, fields should be private, but in simple exam examples, you might see them as public or default.
Methods in a Class
Methods define the behavior of an object. A method is a block of code that performs a specific task. In Java, every method must be inside a class. You cannot have a method floating on its own outside a class.
The general syntax of a method is:
Let me explain each part:
- access_modifier: Like public, private, protected, or default. Determines who can call this method.
- static: Optional keyword. If present, the method belongs to the class, not to objects.
- returnType: The type of value the method sends back. Use
voidif the method does not return anything. - methodName: A valid Java identifier. Follows naming conventions (camelCase).
- parameterList: Optional. Values passed to the method when it is called. Can be empty.
- return statement: Sends a value back. Required if returnType is not void.
See how each method is different? greet() just prints something and returns nothing (void). add() takes two numbers, adds them, and returns the result (int). displayResult() takes a value and prints it but returns nothing (void). getPi() takes nothing but returns a value (double). You need to be comfortable with all these combinations for your exam.
1. A method with
void return type does NOT need a return statement.2. A method with any other return type (int, double, String, etc.) MUST have a
return statement that returns a value of that type.3. The
return statement immediately ends the method execution.4. Parameters are the variables listed in the method declaration. Arguments are the actual values passed when calling the method.
5. A method can have any number of parameters, including zero.
6. Java supports method overloading (same name, different parameters) which we will discuss later in this lesson.
Question 9: What will happen if a method declares a return type of int but does not have a return statement?
A) Returns 0 by default B) Returns null C) Compile-time error D) Runtime error
Answer: C) Compile-time error
If a method declares a non-void return type (like int, double, String, etc.), the Java compiler checks that every possible path through the method ends with a return statement that returns the correct type. If the compiler finds a path that does not return a value, it gives a “missing return statement” compile error. Unlike instance variables, methods do not get default return values. Only void methods can skip the return statement.
Question 10: The values passed to a method when it is called are called ________, while the variables in the method declaration are called ________.
Answer: arguments, parameters
This distinction is important. Parameters are the variable declarations in the method signature, like int a, int b in int add(int a, int b). Arguments are the actual values you pass when calling the method, like 10, 25 in calc.add(10, 25). Parameters receive the values of arguments. Some people use these terms loosely, but in exam contexts, knowing the difference can earn you points.
Constructors in Java
Now we come to one of the most important topics in this chapter. A constructor is a special method inside a class that is used to initialize objects. When you create an object using new, the constructor is automatically called to set up the initial state of the object.
Think of a constructor as the “setup team” for a new object. When a new student joins a university, there is a registration process that sets up their initial information (name, ID, department). A constructor does exactly this for objects in Java.
Rules for Writing Constructors
There are strict rules for constructors that you must memorize:
- The constructor name must be exactly the same as the class name.
- A constructor has no return type, not even void.
- A constructor is called automatically when you use the
newkeyword. You never call a constructor directly like a regular method. - A constructor can have parameters (just like a method).
- You can have multiple constructors in the same class with different parameters (constructor overloading).
Types of Constructors
1. Default Constructor (No-Argument Constructor)
A default constructor is a constructor that takes no parameters. If you do not write ANY constructor in your class, Java automatically provides a default constructor that has an empty body. But if you write even one constructor yourself, Java will NOT provide the default one.
When we write new Student(), Java calls the Student() constructor automatically. Inside the constructor, we set default values for name and age. This way, even before the user sets specific values, the object has valid initial values instead of null and 0.
2. Parameterized Constructor
A parameterized constructor takes parameters. It allows you to pass values when creating the object, so the object is initialized with the values you provide right from the start.
Output:
Now compare this with how we created objects earlier (without a constructor). Earlier, we had to write three separate lines to set data: s1.name = "Abebe"; s1.age = 21; s1.department = "Computer Science";. With a parameterized constructor, we do it all in one line: new Student("Abebe", 21, "Computer Science"). Much cleaner and more convenient!
1. A constructor has the same name as the class and no return type (not even void).
2. If you write
void Student(), it is NOT a constructor. It is a regular method that happens to have the class name.3. Java provides a default constructor automatically only if you write no constructor at all.
4. If you write a parameterized constructor but no default constructor, then
new ClassName() will cause a compile error.5. A constructor is called only once per object, at the time of creation.
6. You can call one constructor from another using
this() keyword (constructor chaining).
Question 11: What will happen if you write void Student() { } inside the Student class and then try Student s = new Student();?
A) The constructor works fine B) Compile error because Java looks for a constructor without void C) Runtime error D) Java automatically removes the void
Answer: B) Compile error because Java looks for a constructor without void
When you write void Student() { }, Java does NOT treat it as a constructor. It treats it as a regular method named “Student” that returns void. Since it is not a constructor, Java will provide the actual default constructor automatically. So new Student() would actually call the auto-generated default constructor, not your method. The real problem comes if you have ONLY void Student() { } and a parameterized constructor like Student(String n). Then the default constructor is NOT auto-generated, and new Student() fails because there is no matching constructor. But in the simplest case with only void Student() { }, new Student() actually compiles because Java provides the real default constructor. The key point is: a constructor must NOT have any return type.
Question 12: A class has only one constructor: Book(String title, double price). Which of the following is valid?
A) Book b = new Book(); B) Book b = new Book("Java", 500); C) Book b = new Book("Java"); D) Both A and B
Answer: B) Book b = new Book("Java", 500);
Since the class has only one constructor that takes two parameters (String and double), you MUST pass exactly two arguments that match those types when creating an object. Option A passes no arguments, so there is no matching constructor (and Java does not provide a default constructor because you already have a constructor). Option C passes only one argument, which also does not match. Only option B passes exactly two arguments of the correct types, so it matches the constructor.
Question 13: A constructor can be called multiple times on the same object after it is created.
Answer: False
A constructor is called only once, at the exact moment an object is created using the new keyword. You cannot call a constructor on an existing object like s1.Student(). That would be a syntax error. After an object is created, you can call regular methods on it as many times as you want, but the constructor runs only once during creation.
Constructor Overloading
Just like methods, you can have multiple constructors in the same class with different parameter lists. This is called constructor overloading. Each constructor provides a different way to initialize an object.
Java decides which constructor to call based on the number and types of arguments you pass. This is similar to method overloading, and the decision is made at compile time.
Constructor Chaining Using this()
You can call one constructor from another constructor in the same class using this(). This is called constructor chaining. It helps avoid repeating code in multiple constructors.
Output:
Notice the order! Even though we called new Book() (no-parameter constructor), the execution goes from Constructor 3 to Constructor 2 to Constructor 1. This is because Constructor 1 calls Constructor 2 using this(), and Constructor 2 calls Constructor 3 using this(). The most detailed constructor runs first, then the less detailed ones. The this() call must always be the first statement in the constructor.
1.
this() is used to call another constructor in the same class.2.
super() is used to call the parent class constructor (we will learn this in inheritance).3.
this() must be the first statement in the constructor. You cannot write anything before it.4. You cannot have a circular chain (Constructor A calls B, B calls C, C calls A). This causes a compile error.
5. Constructor chaining reduces code duplication by reusing initialization logic.
Question 14: What will be the output of the following code?
A) A B B) B A C) A D) B
Answer: A) A B
When new Demo(5) is called, the parameterized constructor Demo(int x) runs. Its first statement is this(), which calls the no-parameter constructor Demo(). That constructor prints “A ” and finishes. Then control returns to the parameterized constructor, which prints “B “. So the output is “A B”. The key is that this() always runs the called constructor FIRST before continuing with the rest of the calling constructor.
Question 15: The this() call can be placed anywhere inside a constructor.
Answer: False
The this() call must ALWAYS be the very first statement in the constructor. If you try to put any code before it, even a simple System.out.println(), the Java compiler will give an error. This rule exists because the object must be fully initialized by the called constructor before the current constructor can do any additional work on it.
The “this” Keyword in Detail
We have been using the this keyword in several examples. Now let me explain it completely because it appears in many exam questions.
The this keyword is a reference variable that refers to the current object. It always points to the object on which the method or constructor is being called. Inside a constructor, this refers to the object being created. Inside a method, this refers to the object that called the method.
There are six main uses of this in Java:
Use 1: To distinguish between instance variables and local variables (most common)
When the parameter name is the same as the instance variable name, Java gets confused. this.name clearly says “the name field of the current object” and the plain name means “the parameter.” Without this, both would refer to the parameter, and the instance variable would never be set!
Use 2: To call another constructor in the same class
Use 3: To pass the current object as a parameter to a method
Use 4: To return the current object from a method
Use 5: To call an instance method of the current object
Use 6: To access an instance variable (even without naming conflict)
1.
this refers to the current object. Inside a constructor, it is the object being created. Inside a method, it is the object that called the method.2. The most common use is resolving naming conflicts between instance variables and parameters.
3.
this() calls a constructor. this (without parentheses) refers to the current object. They are different.4.
this cannot be used inside a static method or static block because static members do not belong to any object.5.
this can be used to return the current object (method chaining pattern).
Question 16: What is the output of the following code?
A) 10, 10 B) 25, 25 C) 25, 10 D) 10, 25
Answer: C) 25, 10
The parameter x in the method hides the instance variable x. When we print just x, Java uses the local variable (parameter), which is 25. When we print this.x, Java explicitly uses the instance variable of the current object, which is 10. This is a classic exam question that tests whether you understand the difference between x and this.x when there is a naming conflict.
Question 17: The this keyword can be used inside a static method to refer to the current object.
Answer: False
Static methods belong to the class, not to any specific object. Since there is no “current object” in a static context, this cannot be used inside a static method. If you try, the compiler will give an error saying “cannot use this in a static context.” This is a very common exam trick question.
Method Overloading in a Class
Method overloading means having two or more methods in the same class with the same name but different parameter lists. The parameters must differ in number, type, or order. The return type alone is NOT enough to overload a method.
Why do we need method overloading? Because it makes your code cleaner and more readable. Instead of having addInt(int, int), addDouble(double, double), and addThree(int, int, int), you can just have add() with different parameters. The compiler figures out which one to call based on the arguments you pass.
The compiler looks at the number and types of arguments you pass and matches them to the correct method. This matching happens at compile time, which is why method overloading is also called compile-time polymorphism.
1. Overloaded methods must have the same name but different parameters (number, type, or order).
2. Changing only the return type does NOT overload a method. It causes a compile error.
3. The compiler decides which method to call at compile time based on argument types.
4. Constructors can also be overloaded (as we saw earlier).
5. The method signature = method name + parameter list. Return type is NOT part of the signature.
6. Changing only the access modifier does NOT overload a method.
Question 18: Which of the following is a valid method overloading?
A) int calc(int a) {} and double calc(int a) {} B) int calc(int a) {} and int calc(int b) {} C) int calc(int a) {} and int calc(int a, int b) {} D) int calc(int a) {} and private int calc(int a) {}
Answer: C) int calc(int a) {} and int calc(int a, int b) {}
Option A is wrong because only the return type is different (int vs double), but the parameters are the same. Return type alone cannot overload. Option B is wrong because the parameter names are different but the types are the same. Parameter names do not matter, only types matter. Option C is correct because the number of parameters is different (one int vs two ints). Option D is wrong because only the access modifier is different. Access modifier alone cannot overload a method.
Question 19: What will be the output?
Output:
Explanation: d.show(5) passes an integer literal, so the show(int) version is called. d.show(5.0) passes a double literal, so the show(double) version is called. d.show('A') passes a character. There is no show(char) version, so Java promotes the char to int (char is automatically promoted to int in Java). The ASCII value of ‘A’ is 65, so it prints “int: 65”. This type promotion during overloading resolution is a very common exam topic!
Static Members: Variables, Methods, and Blocks
We briefly touched on static members in the introduction lesson. Now let me go deep into this topic because it carries many marks in exams.
The word “static” means something that belongs to the class itself, not to any specific object. Let me explain the three types of static members.
Static Variables (Class Variables)
A static variable is declared using the static keyword. Unlike instance variables (where each object gets its own copy), there is only one copy of a static variable, and it is shared by all objects of the class.
Output:
Look at the studentCount variable. It is shared by all three objects. Each time a new Student is created, the same studentCount is increased. After three objects, it shows 3. If you check the count through s1, s2, or s3, or through the class name, you always get the same value because there is only ONE copy.
Similarly, when we change university to “Addis Ababa University”, ALL objects see the new value because they all share the same static variable.
Static Methods (Class Methods)
A static method also belongs to the class, not to any object. You can call a static method using the class name without creating any object. Static methods can only access static variables and other static methods directly. They cannot access instance variables or instance methods directly.
Static Initialization Block
A static block is a block of code inside a class that is marked with the static keyword. It is used to initialize static variables. The static block runs only once, when the class is first loaded into memory, before any object is created and before any static method is called.
Output:
Notice the order carefully. The static block runs FIRST, before anything else, when the class is loaded. The constructor runs each time an object is created. Even though we create two objects, the static block runs only once. This is because static initialization happens at the class level, not the object level.
1. Static variables are shared by all objects. Only one copy exists.
2. Static methods can only directly access static variables and static methods.
3. Static methods CANNOT directly access instance variables or call instance methods.
4. Access static members using the class name:
ClassName.staticMember.5. The
static block runs once when the class is first loaded into memory.6. You can have multiple static blocks in a class, and they run in the order they appear.
7.
main() is static because it must be callable without creating any object.8. Static members are loaded before instance members.
Question 20: What will be the output of the following code?
A) 1 1, 2 1, 3 1 B) 3 1, 3 1, 3 1 C) 1 1, 1 1, 1 1 D) 3 3, 3 3, 3 3
Answer: B) 3 1, 3 1, 3 1
The count variable is static, so it is shared by all objects. After creating three objects, count becomes 3. All three objects (c1, c2, c3) see the same count value of 3. The num variable is an instance variable, so each object has its own copy. Each object increments its own num by 1. So c1.num = 1, c2.num = 1, c3.num = 1. The output is “3 1” for all three objects because the static part is shared (3) but the instance part is separate (1 each).
Question 21: When does a static initialization block run?
A) Every time an object is created B) Only once when the class is first loaded into memory C) When a static method is called D) At the end of the program
Answer: B) Only once when the class is first loaded into memory
The static block executes exactly once, at the moment the JVM loads the class into memory. This happens before any object is created, before any static method is called, and before any static variable is accessed. Even if you create 100 objects, the static block runs only one time. This makes it ideal for one-time setup tasks like loading configuration or establishing database connections.
Question 22: Find the error in the following code and explain why it occurs:
Error: Compile-time error. A static method cannot access a non-static (instance) variable directly.
Explanation: The method show() is static, which means it belongs to the class and can be called without any object. The variable x is an instance variable, which means it belongs to individual objects. Since the static method is not associated with any particular object, it cannot know which object’s x to access. That is why Java prevents this at compile time. To fix it, either make x static (static int x = 10;) or access x through an object reference (System.out.println(new Demo().x);).
Object as Method Parameter and Return Type
In Java, you can pass an object as an argument to a method, and you can also return an object from a method. These are very important concepts that often appear in practical exam questions.
Passing an Object as a Parameter
When you pass s1 and s2 to the method, you are actually passing references (memory addresses), not copies of the objects. The method parameters s1 and s2 point to the same objects in the heap. This means if the method modifies the object’s fields through the reference, the original object is also changed.
Returning an Object from a Method
The return type of the method is Student, which means the method must return a Student object (or null). Inside the method, we create a new Student object and return it. The caller receives this object reference and can use it normally.
1. When you pass an object to a method, you pass a reference (address), not a copy of the object.
2. Because references are passed, changes made to the object inside the method affect the original object.
3. A method can return an object. The return type must be the class type (or a parent class type).
4. For primitive types (int, double, etc.), values are passed by value (a copy is passed).
5. For objects, references are passed by value (a copy of the reference is passed, but it points to the same object).
Question 23: What will be the output?
Output:
Explanation: When we pass box to changeValue(), we are passing the reference (memory address) of the Box object. Inside the method, b points to the same object as box. When b.value = 100 is executed, it changes the actual object’s value. So after the method call, box.value is 100, not 50. This demonstrates that object references are passed, not copies of the objects themselves.
The toString() Method
The toString() method is a special method defined in the Object class (which is the parent of all classes in Java). It returns a string representation of the object. When you print an object using System.out.println(obj), Java automatically calls the toString() method of that object.
If you do not override toString() in your class, the default version returns something like ClassName@hashcode, which is not very useful.
Output:
Without the overridden toString(), the output would be something like Student@15db9742, which tells you nothing about the object. By overriding toString(), you control what gets printed when someone prints your object. This is a very good practice and often asked in exams.
Question 24: What does System.out.println(obj) automatically call on the object?
A) equals() B) hashCode() C) toString() D) getClass()
Answer: C) toString()
When you pass an object to System.out.println() or System.out.print(), Java automatically calls the object’s toString() method and prints whatever string it returns. If the class does not override toString(), the default version from the Object class is used, which returns the class name followed by @ and the hash code in hexadecimal.
Garbage Collection
In languages like C and C++, the programmer must manually free memory by writing code to delete objects. In Java, this is done automatically by a process called garbage collection.
When an object is no longer reachable (no reference variable points to it), it becomes eligible for garbage collection. The Java Garbage Collector (GC) runs in the background and automatically frees the memory used by such objects. You do not need to do anything.
There are two ways to make an object eligible for garbage collection:
- Set the reference variable to
null:s1 = null; - Make the reference variable point to a different object:
s1 = new Student(...);
Java also provides a method called System.gc() that you can call to suggest to the JVM that garbage collection should run. But note: it is only a suggestion, not a guarantee. The JVM decides when to actually run the garbage collector.
Before an object is destroyed by the garbage collector, Java calls the finalize() method of that object. You can override finalize() to perform any cleanup operations (like closing files or database connections). However, finalize() is deprecated in newer Java versions and is not reliable for cleanup.
1. Garbage collection in Java is automatic. The programmer does not need to manually free memory.
2. An object becomes eligible for GC when it has no references pointing to it.
3.
System.gc() only suggests garbage collection; it does not force it.4. The
finalize() method is called by the GC before destroying an object (but it is deprecated since Java 9).5. Setting a reference to
null or reassigning it makes the old object eligible for GC.6. Java has four types of GC: Serial GC, Parallel GC, CMS GC, and G1 GC (you may need to know their names).
Question 25: When does an object become eligible for garbage collection in Java?
A) When the program ends B) When the object’s finalize() method is called C) When no reference variable points to the object D) When the object is declared as static
Answer: C) When no reference variable points to the object
An object becomes eligible for garbage collection when it is no longer reachable, meaning no active reference variable in the program points to that object. This can happen by setting the reference to null, by reassigning the reference to a different object, or when the reference goes out of scope. The program ending (option A) does clean up, but the question asks about eligibility for GC during program execution. finalize() (option B) is called BEFORE the object is destroyed, not to make it eligible. Static objects (option D) are not eligible because they are always reachable through the class.
Question 26: Calling System.gc() guarantees that garbage collection will happen immediately.
Answer: False
System.gc() is only a suggestion or request to the JVM. It does NOT guarantee that garbage collection will run immediately or at all. The JVM has its own logic to decide when garbage collection should run based on memory needs and other factors. This is an important point because some students think System.gc() forces GC, but it does not.
Complete Worked Example
Let me now give you one big example that puts together everything we have learned in this lesson. This type of comprehensive question often appears in exams.
Output:
Let me walk you through what happened step by step:
- The static block ran first when the BankAccount class was loaded, printing the bank name header.
- We called
showBankInfo()before creating any objects. Total accounts was 0. - We created 3 accounts. a1 and a2 use the parameterized constructor, a3 uses the default constructor which chains to the parameterized one using
this(). Each creation increments totalAccounts. - We used both overloaded versions of
deposit()– one with double, one with int. - We printed the objects using
System.out.println(a1), which automatically called our overriddentoString()method. - Finally, we called
showBankInfo()again, and now total accounts shows 3.
Question 27: What will be the output of the following code?
Output:
Explanation: The static block runs first and changes x from 10 to 50. Since x is static, all objects share this value. When we print Test.x, it shows 50. When we print t2.x, it also shows 50 because t2 accesses the same static variable. The instance variable y is set to 100 by the constructor. Each object has its own y, and for t1 it is 100. Even though y was initially 20, the constructor changes it to 100 for each object.
Exercises with Answers
Rectangle with private fields length and width (both double). Include: (a) a default constructor that sets both to 1.0, (b) a parameterized constructor, (c) getter and setter methods for both fields with validation (values must be positive), (d) methods calculateArea() and calculatePerimeter(), (e) a toString() method. Write a main method to test everything.
Area of rectangle:
Perimeter of rectangle:
Output:
Errors found:
Error 1: Missing opening brace { after class Product.
Error 2: void Product(String name, double p) has a return type void. This makes it a regular method, NOT a constructor. Since there is no actual constructor, Java provides a default one (no parameters). But in main, we call new Product() which uses the default constructor, so productName and price stay at their default values (null and 0.0).
Error 3: The static method display() tries to access instance variables productName and price. Static methods cannot access instance variables directly.
Error 4: toString() should have @Override annotation and should be public (the original in Object class is public). Without public, it may not work correctly when printing with println().
Corrected code:
Employee with a static variable companyName, instance variables name, id, and salary. Include a static block to initialize the company name. Include a parameterized constructor. Include a static method to change the company name and show that the change affects all existing objects. Demonstrate in main.
Output:
Notice how changing the static companyName through the static method affected both existing objects. Both employees now show “Ethiopian Airlines” instead of “Ethio Telecom.” This proves that the static variable is shared.
More Practice Questions for Exam
Question 28: What is the difference between instance variables and static variables?
A) Instance variables are shared, static are not B) Static variables are shared by all objects, instance variables are separate for each object C) There is no difference D) Static variables cannot be accessed from methods
Answer: B) Static variables are shared by all objects, instance variables are separate for each object
This is the fundamental difference. If a class has 3 objects, each object has its own copy of instance variables (separate values). But there is only one copy of each static variable, and all 3 objects see and share that same value. Option A has it backwards. Option C is wrong because there is a clear difference. Option D is wrong because static variables CAN be accessed from methods (instance methods can access both static and instance variables).
Question 29: What will be the output?
Output:
Explanation: Each object gets its own a value (5, 10, 15) because a is an instance variable. But b is static, so all three objects share the same b. After creating 3 objects, each constructor increments b by 1, so b becomes 3. Whether you access it through t1, t2, or t3, you get the same value: 3.
Question 30: What will be the output?
Output:
Explanation: First, b1 points to a Box of size 10 and b2 points to a Box of size 20. Then b2 = b1 makes b2 point to the SAME object as b1. Now both b1 and b2 reference the same Box(size=10) object. The Box(size=20) object has no references and becomes eligible for garbage collection. When we change b1.size = 50, since b2 points to the same object, b2.size is also 50. Both print “Size=50” because they point to the same object.
Question 31: Explain the difference between a constructor and a method. List at least four differences.
Answer:
1. Name: A constructor must have the same name as the class. A method can have any valid name following naming conventions.
2. Return type: A constructor has NO return type (not even void). A method must have a return type (void or a specific type).
3. Invocation: A constructor is called automatically when you use new. A method must be called explicitly by the programmer.
4. Purpose: A constructor initializes the object’s state (sets up initial values). A method performs an action or computation on the object.
5. Timing: A constructor runs only once per object, at creation time. A method can be called many times on the same object after creation.
Question 32: How many times does a static block run if you create 5 objects of a class?
A) 5 times B) 0 times C) 1 time D) Depends on the number of static variables
Answer: C) 1 time
A static block runs only once, when the class is first loaded into memory. This happens before any object is created. Even if you create 5, 10, or 1000 objects, the static block executes only that one time. The constructors run for each object (5 times), but the static block runs only once. This is because the static block belongs to the class, not to individual objects.
1. A constructor has the same name as the class and NO return type. If you see
void ClassName(), it is a method, not a constructor.2. If you write any constructor, Java will NOT provide the default constructor.
new ClassName() will fail if you only wrote a parameterized constructor.3.
this() calls another constructor in the same class and MUST be the first statement.4.
this.variable resolves naming conflicts between instance variables and parameters.5. Static methods cannot access instance members directly. This WILL be on your exam.
6. Static variables are shared (one copy). Instance variables are separate (each object has its own).
7. Static block runs ONCE when the class is loaded, before any constructor.
8. When passing objects to methods, references are passed, so changes inside the method affect the original object.
9. Overriding
toString() is important for meaningful object printing.10. An object becomes eligible for garbage collection when no reference points to it.
11.
System.gc() only suggests garbage collection; it does NOT force it.12. Practice writing complete classes with constructors, getters, setters, methods, and toString(). This is the most common practical exam question.