JavaRush/Java Blog/Random EN/Nested inner classes or Inner Class in Java

Nested inner classes or Inner Class in Java

Published in the Random EN group
members
Hello! Today we'll start looking at an important topic - how nested classes work in Java. In English they are called nested classes. Java allows you to create some classes inside others:
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
It is these classes that are called nested. They are divided into 2 types:
  1. Non-static nested classes - non-static nested classes. They are also called inner classes in another way.
  2. Static nested classes - static nested classes.
In turn, inner classes have two special subtypes. Besides the fact that an inner class can be just an inner class, it can also be:
  • local class
  • anonymous class
A little difficult? :) It's okay, here's a diagram for clarity. Come back to it during the lecture if you suddenly feel confused! Nested inner classes - 2In today's lecture we will talk about Inner classes - internal classes (they are also non static nested classes, non-static nested classes). They are specially highlighted in the general diagram so that you don't get lost :) Let's start with the obvious question: why are these classes called “internal”? The answer is quite simple: because they are created inside other classes. Here's an example:
public class Bicycle {

   private String model;
   private int weight;

   public Bicycle(String model, int weight) {
       this.model = model;
       this.weight = weight;
   }

   public void start() {
       System.out.println("Go!");
   }

   public class HandleBar {

       public void right() {
           System.out.println("Steering wheel to the right!");
       }

       public void left() {

           System.out.println("Steering wheel to the left!");
       }
   }

   public class Seat {

       public void up() {

           System.out.println("The seat is up!");
       }

       public void down() {

           System.out.println("The seat is down!");
       }
   }
}
Here we have a class Bicycle- bicycle. It has 2 fields and 1 method - start(). Nested inner classes - 3Its difference from a regular class is that it has two classes, the code of which is written inside Bicycle- these are the classes HandleBar(steering wheel) and Seat(seat). These are full-fledged classes: as you can see, each of them has its own methods. At this point, you might have a question: why did we put one class inside another? Why make them internal? Okay, let’s say we need separate classes for the steering wheel and seat in the program. But you don’t have to nest them! You can make regular classes. For example, like this:
public class HandleBar {
   public void right() {
       System.out.println("Steering wheel to the right!");
   }

   public void left() {

       System.out.println("Steering wheel left");
   }
}

public class Seat {

   public void up() {

       System.out.println("The seat is up!");
   }

   public void down() {

       System.out.println("The seat is down!");
   }
}
Very good question! Of course, we have no technical limitations - we can do it this way. It's more about designing classes correctly from the point of view of a specific program and in the meaning of that program. Inner classes are classes for highlighting a certain entity in a program that is inextricably linked with another entity. Steering wheel, seat, pedals are the components of a bicycle. Separated from the bicycle, they do not make sense. If we made all these classes separate public classes, our program could have, for example, the following code:
public class Main {

   public static void main(String[] args) {
       HandleBar handleBar = new HandleBar();
       handleBar.right();
   }
}
Ummm... The meaning of this code is even difficult to explain. We have some kind of strange bicycle handlebar (why is it needed? No idea, to be honest). And this steering wheel turns to the right... on its own, without a bicycle... for some reason. By separating the essence of the steering wheel from the essence of the bicycle, we have lost the logic of our program. Using an inner class, the code looks completely different:
public class Main {

   public static void main(String[] args) {

       Bicycle peugeot = new Bicycle("Peugeot", 120);
       Bicycle.HandleBar handleBar = peugeot.new HandleBar();
       Bicycle.Seat seat = peugeot.new Seat();

       seat.up();
       peugeot.start();
       handleBar.left();
       handleBar.right();
   }
}
Console output:

Сиденье поднято выше!
Поехали!
Руль влево!
Руль вправо!
What was happening suddenly made sense! :) We have created a bicycle object. We created two of its “subobjects” - the steering wheel and the seat. We raised the seat higher for convenience - and off we went: we roll and steer where we need to go! :) The methods we need are called on the necessary objects. Everything is simple and convenient. In this example, highlighting the handlebars and seat enhances encapsulation (we are hiding data about the parts of the bicycle within the corresponding class), and allows us to create a more detailed abstraction. Now let's look at another situation. Let's say we want to create a program that models a bicycle and parts store. Nested inner classes - 4In this situation, our previous solution will fail. Within the confines of a parts store, each individual part of a bike has meaning even apart from the essence of the bike. For example, we will need methods like “sell pedals to a buyer”, “buy a new seat”, etc. It would be a mistake to use internal classes here - each individual part of the bicycle within our new program has its own meaning: it is separate from the essence of the bicycle, and is in no way tied to it. This is what you should pay attention to if you are wondering whether you need to use inner classes, or separate all entities into separate classes. Object-oriented programming is great because it makes it easy to model real-world entities. This is what you can use as a guide when deciding whether to use inner classes. In a real store, parts are separate from bikes - this is normal. This means that this will be correct when designing a program. Okay, we’ve sorted out the “philosophy” :) Now let’s get acquainted with the important “technical” features of inner classes. Here's what you definitely need to remember and understand:
  1. An object of an inner class cannot exist without an object of an “outer” class.

    This is logical: that’s why we made it Seatinternal HandleBarclasses, so that ownerless steering wheels and seats wouldn’t appear here and there in our program.

    This code won't compile:

    public static void main(String[] args) {
    
       HandleBar handleBar = new HandleBar();
    }

    The following important feature follows from this:

  2. An object of an inner class has access to the variables of the "outer" class.

    For example, let's add Bicyclea variable to our class int seatPostDiameter- the diameter of the seatpost.

    Then in the inner class Seatwe can create a method getSeatParam()that will tell us the seat parameter:

    public class Bicycle {
    
       private String model;
       private int weight;
    
       private int seatPostDiameter;
    
       public Bicycle(String model, int weight, int seatPostDiameter) {
           this.model = model;
           this.weight = weight;
           this.seatPostDiameter = seatPostDiameter;
    
       }
    
       public void start() {
           System.out.println("Go!");
       }
    
       public class Seat {
    
           public void up() {
    
               System.out.println("The seat is up!");
           }
    
           public void down() {
    
               System.out.println("The seat is down!");
           }
    
           public void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }

    And now we can get this information in our program:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
           Bicycle.Seat seat = bicycle.new Seat();
    
           seat.getSeatParam();
       }
    }

    Console output:

    
    Параметр сиденья: диаметр подседельного штыря = 40

    Pay attention:the new variable is declared with the strictest modifier - private. And still the inner class has access!

  3. An inner class object cannot be created in a static method of an "outer" class.

    This is explained by the design features of internal classes. An inner class can have constructors with parameters or just a default constructor. But regardless of this, when we create an object of the inner class, a reference to an object of the “outer” class is quietly passed into it. After all, the presence of such an object is a prerequisite. Otherwise we will not be able to create objects of the inner class.

    But if the outer class method is static, then the outer class object may not exist at all! This means that the logic of the inner class will be broken. In such a situation, the compiler will throw an error:

    public static Seat createSeat() {
    
       //Bicycle.this cannot be referenced from a static context
       return new Seat();
    }
  4. An inner class cannot contain static variables and methods.

    The logic here is the same: static methods and variables can exist and be called even if there is no object.

    But without an object of the “outer” class, we will not have access to the inner class.

    An obvious contradiction! Therefore, the presence of static variables and methods in inner classes is prohibited.

    The compiler will throw an error when trying to create them:

    public class Bicycle {
    
       private int weight;
    
    
       public class Seat {
    
           //inner class cannot have static declarations
           public static void getSeatParam() {
    
               System.out.println("Seat parameter: seatpost diameter = " + Bicycle.this.seatPostDiameter);
           }
       }
    }
  5. When creating an inner class object, its access modifier plays an important role.

    An inner class can be denoted by the standard access modifiers - public, private, protectedand package private.

    Why is it important?

    This affects where in our program we can instantiate the inner class.

    If our class Seatis declared as public, we can create its objects in any other class. The only requirement is that the object of the “external” class must also exist.

    By the way, we have already done this here:

    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle peugeot = new Bicycle("Peugeot", 120);
           Bicycle.HandleBar handleBar = peugeot.new HandleBar();
           Bicycle.Seat seat = peugeot.new Seat();
    
           seat.up();
           peugeot.start();
           handleBar.left();
           handleBar.right();
       }
    }

    We easily accessed the inner class HandleBarfrom the Main.

    If we declare the inner class as private, we will only have access to creating objects within the “outer” class.

    SeatWe will no longer be able to create an object from the outside:

    private class Seat {
    
       //methods
    }
    
    public class Main {
    
       public static void main(String[] args) {
    
           Bicycle bicycle = new Bicycle("Peugeot", 120, 40);
    
           //Bicycle.Seat has a private access in 'Bicycle'
           Bicycle.Seat seat = bicycle.new Seat();
       }
    }

    You probably already understand the logic :)

  6. Access modifiers for inner classes work the same as for regular variables.

    The modifier protectedprovides access to a class variable in its descendant classes and in classes that are in the same package.

    The same protectedworks for inner classes. protectedInner class objects can be created:

    • inside the "outer" class;
    • in its descendant classes;
    • in those classes that are in the same package.

    If the inner class does not have an access modifier ( package private), objects of the inner class can be created

    • inside the "outer" class;
    • in classes that are in the same package.

    You've been familiar with modifiers for a long time, so there won't be any problems here.

That's all for now :) But don't relax! Internal nested classes are a fairly broad topic that we will continue to explore in future lessons. Now you can brush up on the lecture on internal classes from our course. And next time we'll talk about static nested classes.
Comments
  • Popular
  • New
  • Old
You must be signed in to leave a comment
This page doesn't have any comments yet