Theory:Anonymous classes
Sometimes developers need to use a small class that overrides some methods of another class or interface only once. In this case, declaring a new class may be superfluous. Fortunately, Java provides a mechanism for creating a class in a single statement without having to declare a new named class. Such classes are called anonymous because they don't have name identifiers like String
or MyClass
(but they do have an internal name).
# What is an anonymous class?
Anonymous classes enable you to declare and instantiate a class at the same time.
An anonymous class always implements an interface or extends another class (concrete or abstract). Here is the common syntax of creating an anonymous class:
new SuperClassOrInterfaceName() {
// fields
// overridden methods
};
2
3
4
5
6
The syntax of an anonymous class is an expression. And it's similar to a constructor call except that there is a class definition contained in a block of code.
注意
An anonymous class must override all abstract methods of the superclass. That is, all interface methods must be overridden except default methods. If an anonymous class extends a class that has no abstract methods, it doesn't have to override anything.
# Writing anonymous classes
Let's assume we have the following interface with two methods:
interface SpeakingEntity {
void sayHello();
void sayBye();
}
2
3
4
5
6
Here is an anonymous class that represents an English-speaking person:
SpeakingEntity englishSpeakingPerson = new SpeakingEntity() {
@Override
public void sayHello() {
System.out.println("Hello!");
}
@Override
public void sayBye() {
System.out.println("Bye!");
}
};
2
3
4
5
6
7
8
9
10
11
12
The anonymous class is declared and instantiated at the same time — as an expression. It overrides both methods of the interface.
We assign an instance of the anonymous class to the variable of the interface type. Now, we can invoke overridden methods:
englishSpeakingPerson.sayHello();
englishSpeakingPerson.sayBye();
2
Of course, the result is
Hello!
Bye!
2
Let's declare and instantiate another anonymous class:
SpeakingEntity cat = new SpeakingEntity() {
@Override
public void sayHello() {
System.out.println("Meow!");
}
@Override
public void sayBye() {
System.out.println("Meow!");
}
};
2
3
4
5
6
7
8
9
10
11
12
When we invoke the same methods, we obtain the following result:
Meow!
Meow!
2
So, englishSpeakingPerson
and cat
are instances of different anonymous classes that implement the same interface.
# Accessing context variables
In the body of an anonymous class, it is possible to capture variables from a context where it is defined:
- an anonymous class can capture members of its enclosing class (the outer class);
- an anonymous class can capture local variables that are declared as
final
or are effectively final (i.e. the variable is not changed but it doesn't have thefinal
keyword).
Here is another anonymous class that implements the SpeakingEntity
interface:
public class AnonymousClassExample {
private static String BYE_STRING = "Auf Wiedersehen!"; // static constant
public static void main(String[] args) {
final String hello = "Guten Tag!"; // final local variable
SpeakingEntity germanSpeakingPerson = new SpeakingEntity() {
@Override
public void sayHello() {
System.out.println(hello); // it captures the local variable
}
@Override
public void sayBye() {
System.out.println(BYE_STRING); // it captures the constant field
}
};
germanSpeakingPerson.sayHello();
germanSpeakingPerson.sayBye();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
The anonymous class captures the constant field BYE_STRING
and the local final variable hello
. This code is successfully compiled and prints what we expect:
Guten Tag!
Auf Wiedersehen!
2
A declaration of a variable or a method in an anonymous class shadows any other declaration in the enclosing scope that has the same name. You cannot access any shadowed declarations by their names.
# When to use anonymous classes
Generally, you should consider using an anonymous class when:
- only one instance of the class is needed
- the class has a very short body
- the class is used right after it's defined
In this topic, we've considered rather simple anonymous classes to understand the basic syntax, but in real-life applications, they provide a powerful mechanism for creating classes that encapsulate behaviors and pass them to suitable methods. This is a convenient way to interact with parts of our application or with some third-party libraries.
And in the next topic about anonymous classes you will become acquainted with more difficult examples and will dive into the intricacies of anonymous classes. See you soon!