Java Anonymous Classes

A normal class in java is created with class keyword followed by its name.
An anonymous class in java, is a class that is created without a name.
Anonymous, literally means, Without a name.

Anonymous classes are often used when its object is required only once, such as an event handler or a comparator. In this case, it does not make any sense to define a separate class for it.

Following two points must be remembered about Anonymous classes:
1. They always extend another class or implement an interface.
2. Anonymous classes are always implemented inside another class. So, they are also called Anonymous inner classes.
The term Anonymous class is only applicable to Inner classes since outer classes should have a name.

Syntax
Anonymous classes are created by using new keyword and the class or interface type that the anonymous class extends or implements, followed by a set of parentheses that contain the class definition.
Parenthesis contain the definition of methods contained in the class or interface, that the anonymous class is based on.

Example, below is a definition of an anonymous class that extends MyClass, where MyClass has a single method named myMethod().

new MyClass() {
  void myMethod() {
  
  }

};

Note that anonymous class definition ends with a semi-colon, since it is a normal java statement.
Anonymous class extends
An anonymous class can extend a class and implement its methods. Below is an example.

// Already existing class
class Website {
  public void printName() {
    System.out.println("No website till now");
  }
}
class SearchEngine {   // Notice the syntax
   Website w = new WebSite() {
      public void printName() {
         System.out.println("Website is codippa.com");
      }
   };
}

In the above example, there is a class named Website which is already created.
Another class SearchEngine redefines this class, implements its method and assigns it to a reference variable which is of the same type as the actual class.
It is also possible to call the newly implemented method using this reference variable.

Remember that the newly implemented Anonymous class is a sub-class of the actual class.

It follows Polymorphism and its object can be passed anywhere the object of Website class is expected.

class Website {
   public void printName() {
      System.out.println("No website till now");
   }
}
class SearchEngine {
   // Notice the syntax
   Website w = new WebSite() {
      public void printName() {
         System.out.println("Website is codippa.com");
      }
   };
   // Expects an instance of Website class
   public void getWebsite(Website web) {
      // call the method of Website class
      web.printName();
   }
   // Main method
   public static void main(String[] args) {
      // create an object of this class
      SearchEngine obj = new SearchEngine();
      // call its method and pass instance of Website class
      obj.getWebsite(obj.w);
   }
}

Instead of pre-defining the implementation of Website class, it can be defined where required, that is while calling the getWebsite() method.
Thus main method can be modified as

public static void main(String[] args) {
   SearchEngine obj = new SearchEngine();
   // Notice the implementation of Website class as argument
   obj.getWebsite(new Website() {
         public void print() {
           System.out.println("Dynamic implementation");
         }
    });
}

The above implementation is not assigned to any reference variable, it has no name and hence the name Anonymous.

Another example of anonymous class that extends a class is while creating a new thread

Thread t = new Thread() {
    public void run() {
        // code here
    }
};

Remember that if the class which is extended by an anonymous class has a parameterized constructor, then the anonymous class also needs to provide that argument. Example,

public MyClass("test") {

};

In this example, MyTest class would have a constructor that takes a String argument.

Anonymous class implements
An anonymous class can also be defined as the implementer of an interface.
In this case, it will define the implementation of methods declared in the interface and can be passed anywhere the object of interface is expected.
Refer below example to make it clear.

interface WebInterface {
   // interface method declaration
   public void print();
}
class SearchEngine {
   // Notice the syntax
   WebInterface w = new WebInterface() {
      // Interface method implementation
      public void printName() {
         System.out.println("Website is codippa.com");
      }
   };
   // Expects an instance of WebInterface interface
   public void getWebsite(WebInterface web) {
      // call the method of WebInterface
      web.printName();
   }
   // Main method
   public static void main(String[] args) {
      // create an object of this class
      SearchEngine obj = new SearchEngine();
      // call its method and pass instance of WebInterface
      obj.getWebsite(obj.w);
   }
}

As before, implementation of interface as anonymous class can be created where required as shown below.

public static void main(String[] args) {
   SearchEngine obj = new SearchEngine();
   // Notice the implementation of WebInterface as argument
   obj.getWebsite(new WebInterface() {
          public void print() {
            System.out.println("Dynamic implementation");
          }
   });
}

Notice the use of new keyword before the interface name. Anonymous class is the ONLY place where it is possible.

Another example of anonymous class that implements an interface is while creating a new thread

Runnable r = new Runnable() {
    public void run() {
        // code here
    }
};

Anonymous class to sort list
If you want to sort a list of objects in a certain order. You can use anonymous classes to provide the sorting logic as below

Collections.sort(myList, new Comparator<MyObject>() {
    public int compare(MyObject o1, MyObject o2) {
        return o1.getName().compareTo(o2.getName());
    }
});

Above example creates an anonymous class that implements Comparator interface and its compare() method.
ActionListener Anonymous class
Suppose you want to create a button that prints a text, when clicked.
We can create a separate class that implements the ActionListener interface and override its actionPerformed() method as below

class MyButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Java");
    }
}

But you can also do this with an anonymous class as follows

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Hello World!");
    }
});

Anonymous class constructor
An anonymous class cannot have a constructor.

When you create an instance of an anonymous class, Java automatically calls the constructor of the superclass or the class that the anonymous class is based on.
Therefore, you don’t need to define a constructor for an anonymous class, and you also cannot define one.

However, Anonymous classes can access the constructors of the superclass or the class that the anonymous class is based on.
Variable scope
An anonymous class has access to the variables of the enclosing scope, but the scope of the variables within the anonymous class is limited.

A variable that is defined within the enclosing scope and is used within the anonymous class must be either final or effectively final.
A variable is effectively final if it’s not modified after it’s initialized. If a variable is not final or effectively final, the anonymous class will not be able to access it.

For example, in the following code, the variable num is final and can be accessed within the anonymous class

final int num = 5;
Runnable r = new Runnable() {
    public void run() {
        System.out.println(num);
    }
};

However, if num is not final, the anonymous class will not be able to access it and it will result in a compiler errror.

int x = 5;
Runnable r = new Runnable() {
    public void run() {
        System.out.println(x); //Compile-time error
    }
};

Also, the anonymous class can not modify the final variable. Obviously because it’s final.
Anonymous class scope
The scope of anonymous class is limited to the block in which it is defined.
Once the block ends, the anonymous class and its instances are no longer accessible. Example,

boolean createThread = true; 
if(createThread) { 
  Runnable r = new Runnable() { 
    public void run() { 
      System.out.println(x); 
    } 
  }; 
} 
// r is not accessible here

In above example, an anonymous class that implements an interface is defined in an if block. So, its reference is available only in that block.

Hope the article was useful.