Keywords: Java | Abstract Class | Anonymous Subclass | Instantiation | Object-Oriented Programming
Abstract: This article explains through concrete code examples and Java Language Specification why it appears possible to instantiate abstract classes when actually creating anonymous subclass objects. It analyzes the compilation mechanism of anonymous classes, object creation process, and validates this phenomenon through class file generation, helping readers deeply understand core concepts of Java object-oriented programming.
Introduction
In Java programming interviews, the question of whether abstract classes can be instantiated often sparks controversy. Many developers firmly believe abstract classes cannot be instantiated, but certain code examples seem to challenge this understanding. This article will reveal the truth behind this phenomenon through in-depth analysis of Java Language Specification and actual compilation processes.
Problem Context
Consider the following code example:
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
This code compiles and runs successfully, outputting "Abstract". Superficially, it appears that abstract class my is being instantiated, but this is actually a misunderstanding.
The Nature of Anonymous Subclasses
In the expression new my() {}, we are not directly instantiating the abstract class my, but rather creating an instance of an anonymous subclass. According to Java Language Specification (JLS) Section 15.9.1:
- If the class instance creation expression ends in a class body, then the class being instantiated is an anonymous class
- If T denotes a class, then an anonymous direct subclass of the class named by T is declared
- The class being instantiated is the anonymous subclass
This means new my() {} actually creates an object of an anonymous subclass that inherits from my, and the abstract class reference m points to this subclass object.
Compilation Process Verification
To verify this phenomenon, we can compile the code in separate files:
My.java:
abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}
Poly.java:
class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}
After compiling with javac My.java Poly.java, the following class files are generated in the directory:
My.classPoly$1.class(corresponding to the anonymous subclass)Poly.class
The existence of Poly$1.class file clearly proves that the compiler indeed creates a new anonymous subclass. The number "1" indicates this is the first anonymous class appearing in the enclosing class.
Object Creation Process
According to JLS Section 12.5 describing the object creation process:
- Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass
- Just before a reference to the newly created object is returned, the indicated constructor is processed to initialize the new object
During this process, the anonymous subclass inherits all non-private members of the abstract class and can override or implement abstract methods.
Further Example Analysis
Consider a more comprehensive example:
public abstract class ClassOne {
public ClassOne() {
System.out.println("Anonymous(Unnamed) Subclass object Created");
}
public void printSomething() {
System.out.println("Hello,in abstract class:printSomething method");
}
public abstract void implementMethod();
}
class AnonymousClassExample {
public static void main(String[] args) {
ClassOne obj = new ClassOne() {
@Override
public void implementMethod() {
System.out.println("Implemented abstract method in anonymous class");
}
};
obj.printSomething();
obj.implementMethod();
}
}
Output:
Anonymous(Unnamed) Subclass object Created
Hello,in abstract class:printSomething method
Implemented abstract method in anonymous class
This example clearly demonstrates:
- The abstract class constructor is called when the anonymous subclass is instantiated
- Concrete methods in the abstract class can be used directly
- Abstract methods must be implemented in the anonymous subclass
Comparison with Interface Implementation
The concept of anonymous classes also applies to interface implementation:
interface NewClass {
public void show();
}
class AnonymousClassExample {
public static void main(String[] args) {
NewClass nc = new NewClass() {
public void show() {
System.out.println("This is an anonymous class implementing interface");
}
};
nc.show();
}
}
In this case, an anonymous class implementing the interface is created, rather than instantiating the interface itself.
Conclusion
Returning to the original interview question: "Can we instantiate an abstract class?" Strictly speaking, the answer remains "no." The code new My() {} that appears to instantiate an abstract class actually creates an instance of an anonymous subclass of the abstract class. This syntactic sugar makes code more concise, but understanding the underlying mechanism is crucial for mastering Java object-oriented programming.
In practical development, anonymous classes are commonly used in scenarios requiring temporary interface implementation or class extension, such as event handling, thread creation, etc. Understanding this concept helps in writing more flexible and efficient Java code.