I had a hard time understanding anonymous classes while preparing for the OCJP-Gold exam. Anonymous classes are also important for understanding lambda expressions and stream APIs. Therefore, here I will read various books and organize the ideas that helped me understand anonymous classes.
First, implement the interface normally without using an anonymous class, and check the code that calls the method.
Sample1.java
1 interface Foo {//interface
2 void methodA();//Abstract method
3 }
4
5 class FooImple implements Foo {//Implementation class
6 @Override
7 public void methodA() {//Abstract method override
8 System.out.println("methodA");
9 }
10 }
11
12 public class Sample1 {//Execution class
13 public static void main(String[] args) {
14
15 Foo f = new FooImple();//Generate an implementation class and assign it to a variable
16 f.methodA();//Calling a method on a variable to which the implementation class is assigned
17
18 new FooImple().methodA();//No need to assign to variables if only method calls
19 }
20 }
Execution result
methodA
methodA
In Sample1.java
, the interface Foo
, its implementation class FooImple
, and the execution classSampole1
will appear.
There is nothing particularly difficult, but let's assume that the methodA ()
method that we are implementing and calling here is ** a method that we do not plan to reuse elsewhere and is needed on an ad hoc basis **. ..
In such a case, it feels like it is troublesome to bother to define the implementation class of the Foo
interface and use it in two steps. ** **
Also, since the process itself is not a big process, the code itself can be shortened, but if you want to call many methods that implement similar implementations, you need to define as many implementation classes as there are methods you want to implement. there is. ** **
If this is in the same class file, the problem seems small, but if it is divided into different class files, it can be troublesome to manage.
An implementation using anonymous classes can be used to solve such troubles. There are two ways to write an implementation that uses anonymous classes. Check each with a code.
Sample2.java
1 interface Foo {//interface
2 void methodA();//Abstract method
3 }
4
5 public class Sample2 {//Execution class
6 public static void main(String[] args) {
7 Foo f = new Foo() {//Assign the result implemented by the anonymous class to the variable f
8 @Override
9 public void methodA() {//Abstract method override
10 System.out.println("methodA");
11 }
12 };
13 f.methodA();//Method call to implementation class
14 }
15 }
Execution result
methodA
In Sample2.java
, the interface Foo
and the execution class Sampole2
will appear.
FooImple
, which is an implementation class of the Foo interface that appeared in Sample1.java
, will not appear by implementing it with an anonymous class.
** By using an anonymous class, you can "declare a class" and "create an instance" at the same time. ** **
If you can't get an image just by looking at this sample, please compare it with Sample1.java
mentioned above.
The 15th line of Sample1.java
has been replaced with the 7th to 12th lines of Sample2.java
.
You can see that the right side of Foo f = new FooImple ();
is new Foo ()
.
Also, you can see that the contents (method definition) of the FooImple
class are moved to the followingFoo f = new Foo ()
(lines 8 to 10) as they are.
By doing this, you can define and use the implementation class in the execution class without having to define the implementation class that you do not plan to reuse.
Note that the 18th line of Sample1.java
cannot be used unless the FooImple
class is defined, so it is deleted from Sample2.java
.
This pattern is described below.
Also, if you just want to execute the ** method and you don't plan to reuse the implemented class, you don't even need to assign it to a variable. ** **
This is related to line 18 of Sample1.java
mentioned earlier.
Sample3.java
1 interface Foo {//interface
2 void methodA();//Abstract method
3 }
4
5 public class Sample3 {//Execution class
6 public static void main(String[] args) {
7 new Foo() {//Implementation in anonymous class without variable declaration
8 @Override
9 public void methodA() {//Abstract method override
10 System.out.println("methodA");
11 }
12 }.methodA();//Method call to implementation class
13 }
14 }
If you can't get an image just by looking at this sample, please compare it with the above Sample2.java
.
It is almost the same as Sample2.java
, but the 7th and 12th lines are different.
You can see that the left side of Foo f = new Foo ()
(7th line) is missing and that f
off.methodA ();
(13th line) is missing. ..
This is because the created instance is assigned to the variable f, and the implementation that called methodA () for that variable f is temporarily used without assigning it to the variable to call methodA ().
In Samples 1, 2 and 3, we organized the implementation of the interface that does not have arguments and return values, but we also created the sample code for ** the implementation of the interface that has arguments and return values **, so I will add it. If you understand the idea in Samples 1, 2 and 3, there is nothing particularly difficult, so I will omit the explanation.
Sample4.java
1 interface Foo {//interface
2 String methodA(String str);//An abstract method that takes a String type as an argument and returns a String type
3 }
4
5 class FooImple implements Foo {//Implementation class
6 @Override
7 public String methodA(String str) {//Abstract method override
8 return "Hello " + str;
9 }
10 }
11
12 public class Sample4 {//Execution class
13 public static void main(String[] args) {
14 Foo f = new FooImple();//Generate an implementation class and assign it to the variable f
15 String str = f.methodA("methodA");//Assign the return value of the method to the variable str
16 System.out.println(str);
17 }
18 }
Execution result
Hello methodA
Sample5.java
1 interface Foo {//interface
2 String methodA(String str);//An abstract method that takes a String type as an argument and returns a String type
3 }
4
5 public class Sample5 {//Execution class
6 public static void main(String[] args) {
7 Foo f = new Foo() {//Generate an implementation class and assign it to the variable f
8 @Override
9 public String methodA(String str) {//Abstract method override
10 return "Hello " + str;
11 }
12 };
13 String str = f.methodA("methodA");//Assign the return value of the method to the variable str
14 System.out.println(str);
15 }
16 }
Sample6.java
1 interface Foo {//interface
2 String methodA(String str);//An abstract method that takes a String type as an argument and returns a String type
3 }
4
5 public class Sample6 {//Execution class
6 public static void main(String[] args) {
7 String str = new Foo() {//Generate an implementation class but do not assign it to a variable, but assign the method execution result to the variable str
8 @Override
9 public String methodA(String str) {//Abstract method override
10 return "Hello " + str;
11 }
12 }.methodA("methodA");//Method call to the created instance
13 System.out.println(str);
14 }
15 }
I have organized the idea of anonymous classes. ** It's important to understand what the difference is if you don't use anonymous classes. ** ** By doing so, you can understand the merits of anonymous classes, and it is also useful as a preparation for exams. Please compare Samples 1, 2 and 3 carefully to understand the difference between them.
Also, the sample code is uploaded below, so please refer to it if you like.
** Addendum (2019/1/31) ** Samples 4, 5 and 6 have also been added to the above sample code.
Recommended Posts