JavaRush /Java Blog /Random EN /Anonymous classes in Java

Anonymous classes in Java

Published in the Random EN group
Hello! In today's lesson we will continue to look at the topic of nested classes. It's the turn of the last group - anonymous inner classes in Java. Let's return to our diagram: Anonymous classes - 2Like the local classes we talked about in the last lecture, anonymous classes are a subset of inner classes. They also have several similarities and differences between them. But first, let’s figure it out: why are they actually called “anonymous”? To do this, let's look at a simple example. Imagine that we have a main program that is constantly running and doing something. We want to create a monitoring system for this program consisting of several modules. One module will monitor general performance indicators and keep a log, the second will record and log errors in the error log, the third will monitor suspicious activity: for example, unauthorized access attempts and other security-related things. Since all three modules should essentially just start at the beginning of the program and run in the background, it's a good idea to create a common interface for them:
public interface MonitoringSystem {

   public void startMonitoring();
}
It will be implemented by 3 specific classes:
public class GeneralIndicatorsMonitoringModule implements MonitoringSystem {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Security monitoring started!");
   }
}
It would seem that everything is in order. We have a fairly clear system of several modules. Each of them has its own behavior. If we need new modules, we can add them, because we have an interface that is quite easy to implement. But let's think about how our monitoring system will work. Anonymous classes - 3Essentially, we should just create 3 objects - GeneralIndicatorsMonitoringModule, ErrorMonitoringModule, SecurityModule- and call a method startMonitoring()on each of them. That is, all you need to do is create 3 objects and call 1 method on them.
public class Main {

   public static void main(String[] args) {

       GeneralIndicatorsMonitoringModule generalModule = new GeneralIndicatorsMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Console output:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
And for such a small job, we wrote a whole system: 3 classes and one interface! And all this for the sake of 6 lines of code. On the other hand, what are our options? Yes, it’s not very cool that we wrote such “disposable” classes. But how can we fix this? This is where anonymous inner classes come to our aid ! Here's what they look like in our case:
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Monitoring of general indicators has started!");
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Security monitoring started!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Let's figure out what's going on here! It looks like we are creating an interface object:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
};
But we have known for a long time that it is impossible to create interface objects! That's right, it's impossible. In fact, we don't do that. The moment we write:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Inside the Java machine the following happens:
  1. An unnamed Java class is created that implements the MonitoringSystem.
  2. The compiler, seeing such a class, requires you to implement all the interface methods MonitoringSystem(we did this 3 times).
  3. One object of this class is created. Pay attention to the code:
MonitoringSystem generalModule = new MonitoringSystem() {

};
There is a semicolon at the end! She's standing there for a reason. We simultaneously declare a class (via curly braces) and create its object using (); Each of our three objects has overridden a method startMonitoring()in its own way. At the end we simply call this method on each of them:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Console output:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
That's all! We've completed our task: we've created three objects MonitoringSystem, redefined it in three different ways, and called it three times. All three modules are successfully launched and working. At the same time, the structure of our program has become much simpler! GeneralIndicatorsMonitoringModuleAfter all , classes can ErrorMonitoringModulenow SecurityModulebe removed from the program altogether! We simply don’t need them - we managed just fine without them. If each of our anonymous module classes needs some different behavior, its own specific methods that the others do not have, we can easily add them:
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }

   public void someSpecificMethod() {

       System.out.println("Specific method for first module only");
   }
};
The Oracle documentation has a good recommendation : "Use anonymous classes if you need a local class for one-time use." An anonymous class is a full-fledged inner class. Therefore, it has access to outer class variables, including static and private ones:
public class Main {

   private static int currentErrorsCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {

           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
They have something in common with local classes: they are visible only inside the method in which they are defined. In the example above, any attempts to access the object errorModuleoutside the method main()will fail. And one more important limitation that anonymous classes inherited from their “ancestors” - inner classes: an anonymous class cannot contain static variables and methods . If we try to make the method getCurrentErrorsCount()from the example above static, the compiler will throw an error:
//error! Inner classes cannot have static declarations
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
We get the same result if we try to declare a static variable:
MonitoringSystem errorModule = new MonitoringSystem() {

   //error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }

};
Finally, I can recommend you an excellent video on the topic of anonymous classes, where this topic is explained as simply and clearly as possible :)
And our lesson today has come to an end! And although we've covered the last group of nested classes, we're not done with this topic yet. What will we study next about nested classes? You'll definitely find out soon! :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION