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-newbies learn something new. Where possible, everything will be shown using 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 understand the first two types of classes, and local and anonymous are simply 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 that very thing. In other words, it is simply a description of what the created entities should be like: what properties and methods they should have. Properties are characteristics of an entity, methods are actions that it can perform. A good example of a class from real life, which gives an understanding of what a class is, can be considered drawings: drawings are used to describe structures (catapult, screwdriver), but a drawing is not a design. Just as engineers use blueprints to create designs, programming uses classes to create objects that have described properties and methods.
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 created a Java class that describes the “student” entity: each student has a name, group and specialty. Now, in other places in the program, we can create real examples of this class. In other words: if the class Studentis a portrait of what a student should be, then the created instance is the actual student itself. An example of creating a new student: new Student("Ivan", "KI-17-2", "Computer Engineering");The operator newsearches for the class Studentand then calls a special method (constructor) of this class. The constructor returns a ready-made class object Student- our dear, 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 inside an outer class.

  2. Nested static classes are static classes inside 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 an outer class

First, I want you to understand what this 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 the sake of example it will be enough to show a little; we will not break it down completely. To visualize this process, we will use an airplane diagram. Classes, types of nested classes with examples - 2 First, we need to create a class Airplanewhere we can add 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 designing airplanes, 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 inherit, but so they extend the parent class by 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. Essentially, this is a more detailed description of some details of our external class. In this example, we need to create wings for an airplane - 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 a class Airplane(airplane), and added two variables - left wing and right wing. And each wing has its own properties (color, model) that we can change. This way you can staff the structures as much as you need. And note: earlier on the diagram there were quite a lot of parts for the aircraft, and, in fact, we can divide all the parts 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 to solve the problem. Then there is no need to do them. It's like cutting a person into legs, arms, torso and head - it's possible, but why if this class is only used to store data about people? Features of non-static nested Java classes:
  1. They exist only in objects, so to create them you need an object. In other words: we designed our wing to be part of an airplane, so to create 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 move them to an outer class. This is due to the close 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 in two ways.
  4. You can get a reference to an instance of an external class. Example: Airplane.this is a link to an airplane, this is a link to a wing.

Static classes inside an outer class

This type of class is no different from a regular outer class, except for one thing: to create an instance of such a class, you need to list the entire path from the outer class to the desired one, separated by a dot. For example: Building.Plaftorm platform = new Building.Platform(); Static classes are used to put related classes side by side so that the logical structure is easier to work with. For example: we can create an external class Building, where there will be a specific list of classes that will represent 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 package a logical structure into a more convenient form. If they didn't exist, we would need to create 4 completely different classes. The advantages of this approach:
  1. The number of classes has decreased.
  2. All classes are inside 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 classes you need and show the whole picture more holistically.
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 AWT 2D 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 their instances can only be created in a method, and the method cannot be static (to create them you need an instance of an external class, a reference to an instance of the calling object is implicitly passed to non-static methods, and in a static method there is no method for 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 can be stored in the heap after the method completes, 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: since 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 can be found extremely rarely, since they make the code difficult to read and do not have any advantages, except one - access to method variables. I don’t know what 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(it will be assumed that this is a person) with properties street(street), house(house). We would like to return some object to access just the person's location. To do this, we created the AddressContainer interface, which implies a storage of data about a person’s location.
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 storage of a person’s location, created constant variables there (so that after exiting the method, the variables were stored in an object) and implemented a method for obtaining 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 getters in the class Person, however, the creation of this class and its possible use was shown, and then it’s up to you.

Anonymous classes

Under the hood, anonymous classes are just regular non-static nested classes. Their peculiarity is their ease of use. You can write your class directly when 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!");
        }
    }
}
Essentially, we are simply combining two things in one place: creating an instance of one class ( Animal) and creating an instance of its inheritor inner class ( 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 where it was created or immediately after it;
  • The class name is not important and does not make the code easier to understand.
Anonymous classes are often used in GUIs to create event handlers. For example, to create a button and react to its click:
JButton b2 = new JButton("Click");
b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата!");
    }
});
However, after Java 8 they began to use lambda expressions, but still a lot of code was written before version 8 and you may encounter (and will encounter during your training in JavaRush) 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 that you learned something new or understood something that you did not understand before. I would also like to clarify that this article belongs to the “attention to detail” category . This is my first work, so I hope that it was useful to someone. In the near future, when new ideas come, I will try to write something else, I just have one idea... Good luck to everyone and success in programming :)
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION