In Java, an anonymous inner class is a local inner class that is defined and instantiated in a single expression. Anonymous inner classes are often used when we need to define a class that will be used only once and don’t want to create a separate file for it.
Anonymous inner classes are declared using the syntax:
new SuperType(constructor parameters) { // class body }
Here, SuperType
is the class or interface being extended or implemented by the anonymous inner class. The body of the anonymous inner class follows the same syntax as a regular class or interface definition.
For example, consider the following code that defines an anonymous inner class that implements the Runnable
interface:
Thread t = new Thread(new Runnable() { public void run() { System.out.println("Hello, world!"); } }); t.start();
Here, we are creating a new Thread
object and passing an anonymous inner class that implements the Runnable
interface as an argument to its constructor. The run()
method of the Runnable
interface is defined within the anonymous inner class, and when the thread is started, it will execute the run()
method and print “Hello, world!” to the console.
Anonymous inner classes can also access variables in their enclosing scope, but these variables must be declared final or effectively final to be used within the anonymous inner class. This is because the variables are passed by value to the anonymous inner class and must be immutable to ensure their values don’t change between the time the inner class is created and the time it is executed.
Java anonymous inner class example using class:
Sure, here is an example of using an anonymous inner class in Java to define a new class that extends an existing class:
public class AnonymousInnerClassExample { public static void main(String[] args) { // create an instance of the anonymous class that extends the Person class Person p = new Person("John") { @Override public void sayHello() { System.out.println("Hello, my name is " + getName()); } }; // call the sayHello method of the anonymous class p.sayHello(); } } class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void sayHello() { System.out.println("Hello, my name is " + name); } }
In this example, we define an anonymous inner class that extends the Person
class and overrides its sayHello
method to print a customized greeting that includes the person’s name. We create an instance of the anonymous inner class and call its sayHello
method to print the greeting.
Note that the anonymous inner class is declared and instantiated in a single expression using the following syntax:
new Person("John") { @Override public void sayHello() { System.out.println("Hello, my name is " + getName()); } }
Here, we are creating a new instance of the Person
class with a name of “John”, but we are also defining a new class that extends the Person
class and overrides its sayHello
method. This new class is defined within the curly braces after the new Person("John")
expression, and we use the @Override
annotation to indicate that we are overriding a method from the superclass.
When we call the sayHello
method on the instance of the anonymous inner class, it will print the customized greeting that we defined within the anonymous class.
Internal working of given code:
Sure, let me explain how the given code works:
Thread t = new Thread(new Runnable() { public void run() { System.out.println("Hello, world!"); } }); t.start();
This code creates a new Thread
object and passes an anonymous inner class that implements the Runnable
interface as a parameter to its constructor.
The anonymous inner class is defined as:
new Runnable() { public void run() { System.out.println("Hello, world!"); } }
Here, we are creating a new instance of the Runnable
interface and defining its run
method within the anonymous inner class. When the thread is started, it will execute the run
method defined within the anonymous inner class, which simply prints “Hello, world!” to the console.
The t.start()
method call starts the thread, which causes the run
method of the anonymous inner class to be executed in a separate thread of control.
The reason for using an anonymous inner class in this case is to define the run
method of the Runnable
interface without having to create a separate named class for it. Since the run
method is the only method defined by the Runnable
interface, it is often more concise to use an anonymous inner class instead of creating a separate named class that implements the interface.
I hope this explanation helps!
Internal class generated by the compiler:
When we define an anonymous inner class in Java, the compiler generates a new class file for the anonymous class with a generated name that is typically composed of the outer class name, a dollar sign, and a sequential number.
For example, consider the following code:
public class Outer { public void foo() { Bar bar = new Bar() { public void baz() { System.out.println("Hello, world!"); } }; bar.baz(); } } interface Bar { void baz(); }
In this code, we define an anonymous inner class that implements the Bar
interface and overrides its baz
method. When the foo
method of the Outer
class is called, it creates an instance of the anonymous inner class and calls its baz
method.
The compiler will generate a new class file for the anonymous inner class with a name like Outer$1.class
. This class file will contain the implementation of the anonymous inner class and will be loaded by the JVM at runtime when the class is used.
The generated class file will have access to the members of the outer class, including private members, because it is an inner class of the outer class. However, the generated class file will not have a reference to the this
object of the outer class. Instead, it will have a reference to a synthetic field in the outer class that holds a reference to the outer class instance.
It is important to note that the generated class file for an anonymous inner class is not named or declared explicitly in the source code and is not accessible from other classes, making it effectively “invisible” to the rest of the program.
Java anonymous inner class example using interface:
Sure, here is an example of using an anonymous inner class in Java to implement an interface:
public class AnonymousInnerClassExample { public static void main(String[] args) { // create an instance of the anonymous class that implements the MyInterface interface MyInterface obj = new MyInterface() { @Override public void doSomething() { System.out.println("Doing something..."); } }; // call the doSomething method of the anonymous class obj.doSomething(); } } interface MyInterface { void doSomething(); }
In this example, we define an anonymous inner class that implements the MyInterface
interface and overrides its doSomething
method to print a message to the console. We create an instance of the anonymous inner class and call its doSomething
method to perform the action.
Note that the anonymous inner class is declared and instantiated in a single expression using the following syntax:
new MyInterface() { @Override public void doSomething() { System.out.println("Doing something..."); } }
Here, we are creating a new instance of the MyInterface
interface, but we are also defining a new class that implements the MyInterface
interface and overrides its doSomething
method. This new class is defined within the curly braces after the new MyInterface()
expression, and we use the @Override
annotation to indicate that we are overriding a method from the interface.
When we call the doSomething
method on the instance of the anonymous inner class, it will print the message that we defined within the anonymous class.