JavaRush /Java Blog /Random EN /Classes, types of nested classes with examples
Ярослав
Level 40
Днепр

Classes, types of nested classes with examples

Published in the Random EN group
Hi all. In this topic, I want to talk in detail about Java classes and their types in order to help beginners understand this topic, and, perhaps, non-beginners learn something new. Where possible, everything will be shown with real-life examples with accompanying code examples. Let's get started. Classes, types of nested classes with examples - 1And I would like to note that the main thing is to realize the first two types of classes, and local and anonymous are just subtypes of the inner class.

What is a class?

A class is a logical description of something, a template with which you can create real instances of this very something. In other words, this is just a description of what the created entities should be: what properties and methods they should have. Properties are the characteristics of an entity, methods are the actions that it can perform. A good example of a class from real life, giving an understanding of what a class is, can be considered blueprints: blueprints are used to describe structures (catapult, screwdriver), but a blueprint is not a structure. Engineers use blueprints to create designs, and in programming, classes are used to create objects that have the properties and methods described.
public class Student {
    private String name, group, specialty;

    public Student(String name, String group, String specialty) {
       this.name = name;
       this.group = group;
       this.specialty = specialty;
   }

   // getters/setters
}
In this example, we have created a Java class that describes the entity "student": each student has a name, a group, and a specialty. Now, in other places of the program, we can create real instances of this class. In other words: if the class Studentis a portrait of what a student should be, then the instance created is the real student itself. An example of creating a new student: new Student("Ivan", "KI-17-2", "Computer Engineering");The operator newsearches for a class Studentand then calls a special method (constructor) of this class. The constructor returns a ready-made class object Student- our own, hungry student without a scholarship :))

Types of classes in Java

In Java, there are 4 kinds of classes inside another class:
  1. Nested inner classes are non-static classes within an outer class.

  2. Nested static classes are static classes within an outer class.

  3. Java local classes are classes within methods.

  4. Anonymous Java classes are classes that are created on the fly.

We will talk about each of them separately.

Non-static classes inside outer class

First, I want you to understand what it is with a real example, because it makes it much easier to understand. So now we will break down a real big thing into smaller components, and we will disassemble - an airplane! However, for an example, it will be enough to show a little, we will not completely break it down. To visualize this process, we will use the scheme of the aircraft. Classes, types of nested classes with examples - 2 First, we need to create a class Airplanewhere we can enter a little description: aircraft name, identification code, flight.
public class Airplane {
    private String name, id, flight;

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    // getters/setters
}
Now we want to add wings. Create a separate class? Perhaps this is the logic if we have a complex program for constructing aircraft, and where we need to create a huge number of derived classes (classes that have the same logic as the parent class, that is, the class from which they are inherited, but so extend the parent class, adding logic or more detailed characteristics), but what if we just have a game where we have one plane? Then it will be more rational for us to complete the entire structure in one place (in one class). This is where non-static nested classes come into play. In fact, this is a more detailed description of some details of our outer class. In this example, we need to create wings for the plane - left and right. Let's create!
public class Airplane {
    private String name, id, flight;
    private Wing leftWing = new Wing("Red", "X3"), rightWing = new Wing("Blue", "X3");

    public Airplane(String name, String id, String flight) {
        this.name = name;
        this.id = id;
        this.flight = flight;
    }

    private class Wing {
        private String color, model;

        private Wing(String color, String model) {
            this.color = color;
            this.model = model;
        }

        // getters/setters
    }

    // getters/setters
}
So we created a non-static nested class Wing(wing) inside the class Airplane(airplane), and added two variables - the left wing and the right wing. And each wing has its own properties (color, model) that we can change. So you can complete the structures as much as you need. And note: earlier on the diagram there were quite a lot of details for the aircraft, and, in fact, we can divide all the details into internal classes, but such a process is not always advisable. Such moments need to be traced depending on the task. You may not need wings at all for the task at hand. Then there is no need to do them. It's like sawing a person into legs, arms, torso and head - you can, but why, if this class is used only to store data about people? Features of non-static nested Java classes:
  1. They exist only for objects, so you need an object to create them. In other words: we have framed our wing to be part of an airplane, because to make a wing we need an airplane, otherwise we don't need it.
  2. There cannot be static variables inside a Java class. If you need some constants or anything else static, you need to take them out to an external class. This is due to the tight coupling of the non-static nested class to the outer class.
  3. The class has full access to all private fields of the outer class. This feature works both ways.
  4. You can get a reference to an instance of the outer class. Example: Airplane.this is a reference to an aircraft, this is a reference to a wing.

Static classes inside outer class

This type of class is no different from a regular external class, except for one thing: to create an instance of such a class, you need to list the entire path from the external class to the desired one through a dot. For example: Building.Plaftorm platform = new Building.Platform(); Static classes are used to group related classes side by side to make the logical structure easier to work with. For example: we can create an external class Building, where there will be a specific list of classes that will be a specific building.
public abstract class Building {
    private String name, address, type;

    Building(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public static class Platform extends Building {
        public Platform(String name, String address) {
            super(name, address);
            setType("Platform");
        }

        // some additional logic
    }

    public static class House extends Building {
        public House(String name, String address) {
            super(name, address);
            setType("House");
        }

        // some additional logic
    }

    public static class Shop extends Building {
        public Shop(String name, String address) {
            super(name, address);
            setType("Shop");
        }

        // some additional logic
    }

    // getters/setters
}
This example demonstrates how static classes allow you to compose a logical structure in a more convenient way. Without them, we would need to create 4 completely different classes. The advantages of this approach:
  1. The number of classes has decreased.
  2. All classes within their parent class. We are able to trace the entire hierarchy without opening each class separately.
  3. We can refer to the Building class, and the IDE will already prompt the entire list of all subclasses of this class. This will make it easier to find the right classes and show the whole picture more whole.
An example of creating an instance of a nested static class:Building.Shop myShop = new Building.Shop(“Food & Fun!”, “Kalyaeva 8/53”); I would also like to note that this strategy is used in 2D AWT classes to describe shapes, such as Line2D, Arc2D, Ellipse2D and others.

Local classes

These classes are declared inside other methods. In fact, they have all the properties of a non-static nested class, only they can be instantiated only in a method, and the method cannot be static (to create them, you need an instance of the outer class, a reference to the instance of the calling object is implicitly passed to non-static methods, and in static there is no method of this link). But, they have their own characteristics:
  1. Local classes can only work with final method variables. The thing is that instances of local classes are able to be stored on the "heap" after the completion of the method, and the variable can be erased. If the variable is declared final, then the compiler can save a copy of the variable for later use by the object. And one more thing: from 8+ versions of Java, you can use non-final variables in local classes, but only on the condition that they will not change.
  2. Local classes cannot be declared with access modifiers.
  3. Local classes have access to method variables.
Local classes are extremely rare, as they make it difficult to read the code and do not have any advantages, except for one thing - access to method variables. I don't know what kind of example of a local class can be taken that would show their effective use, so I'll just show my example. Let's say that we have a class Person(will assume that this is a person) with the properties street(street), house(house). We would like to return some kind of object to access only the person's location. To do this, we created the AddressContainer interface, which is a store of data about the location of a person.
public class Person {
    private String name, street, house;

    public Person(String name, String street, String house) {
        this.name = name;
        this.street = street;
        this.house = house;
    }

    private interface AddressContainer {
        String getStreet();
        String getHouse();
    }

    public AddressContainer getAddressContainer() {
        class PersonAddressContainer implements AddressContainer {
            final String street = Person.this.street, house = Person.this.house;

            @Override
            public String getStreet() {
                return this.street;
            }

            @Override
            public String getHouse() {
                return this.house;
            }
        }

        return new PersonAddressContainer();
    }

    public static void main(String[] args) {
        Person person = new Person("Nikita", "Sholohova", "17");

        AddressContainer address = person.getAddressContainer();

        System.out.println("Address: street - " + address.getStreet() + ", house - " + address.getHouse());
    }

    // getters/setters
}
As you can see, inside the method we created a class that implements the person's location store, created constant variables there (so that after the method exits the variables are stored in the object) and implemented the method to get the address and house. Now we can use this object in other places in the program to get the location of a person. I understand that this example is not ideal and it would be more correct to do it simply by leaving the getters in the class Person, however, the creation of this class and its possible use was shown, and then you decide.

Anonymous classes

Under the hood, anonymous classes are just ordinary non-static nested classes. Their peculiarity lies in their ease of use. You can write your class directly while creating an instance of another class.
public class Animal {
    public void meow() {
        System.out.println("Meow!");
    }

    public static void main(String[] args) {
        Animal anonTiger = new Animal() {
            @Override
            public void meow() {
                System.out.println("Raaar!");
            }
        };

        Animal notAnonTiger = new Animal().new Tiger();

        anonTiger.meow(); // будет выведено Raaar!
        notAnonTiger.meow(); // будет выведено Raaar!
    }

    private class Tiger extends Animal {
        @Override
        public void meow() {
            System.out.println("Raaar!");
        }
    }
}
Basically, we're just combining two things in one place: instantiating one class ( Animal) and instantiating its inner-class child ( Tiger). Otherwise, we need to create the class separately and use longer constructs to achieve the same result. The use of anonymous classes is justified in many cases, in particular when:
  • the class body is very short;
  • only one instance of the class is needed;
  • the class is used at the place of its creation or immediately after it;
  • the class name is not important and does not make the code easier to understand.
Often anonymous classes are used in GUIs to create event handlers. For example, to create a button and react to its pressing:
JButton b2 = new JButton("Click");
b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата!");
    }
});
However, after Java 8, lambda expressions began to be used, but still a lot of code was written before version 8, and you may encounter (and will encounter in the course of learning on CodeGym) such inscriptions. \ Analogue with lambdas :
JButton b2 = new JButton("Click");
b2.addActionListener(e -> System.out.println("Кнопка нажата!"));
End of article Thank you all for your attention and I hope you learned something new or figured out something you didn't understand before. I also want to clarify that this article belongs to the nomination "attention to detail" . This is my first work, so I will hope that it was useful to someone. In the near future, when new ideas come, I will try to write something else, there is just one idea ... Good luck to everyone and success in programming :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION