📜 ⬆️ ⬇️

Internal and nested java classes. Part 1

Hello dear readers Habra

Java internal and nested classes

03/02/2017 - 2019

Part 1. Start

Purpose of the article: To tell about internal, nested, local, anonymous classes. Show examples of their use. Write and test classes in java code. Tell about the properties of these classes.

A little introduction. I suggest you heed a cycle of three articles.
In them, I talk about internal, nested, local, anonymous classes. It's about terminology and application. For these articles, I wrote quite a lot of code.
This is a training code, not a guide to action. That is, I wrote the code for better understanding. I also tried to explain the work of the training code. It took quite a long time to write the publication. Please treat with understanding.

To begin with, what is the inner and nested classes. Let's look at the terminology found in the documentation >>> :

In Java, there are 4 types of nested (nested) classes:
  1. Static nested classes
  2. Inner classes
  3. Local Classes
  4. Anonymous (unnamed) classes

Joshua Bloch:
“There are four categories of nested classes:

  • static member class
  • nonstatic member class,
  • anonymous class (anonymous class)
  • and local class.
"
Let's try to figure out what it is.

Let's start a bit remotely, since all this is directly related to our questions. Recall object-oriented programming. Relationship composition and inheritance.

In his book “Java 2 Developer Guide,” Michael Morgan very well and describes in detail the relationships between classes and objects. We will look at some of them. The “this is - that” relationship is expressed by inheritance, and the “has a part” relationship is described by composition.

In our examples, we mainly consider composition. Since nested classes are part of something. That is, we have a wrapper class and a nested class defined within the wrapper class. Composition example: the car has an engine, a door, 4 wheels, a housing. And we can describe the car using internal (Inner) classes.

An example of this use can be found in Bruce Ekkel’s book, The Java Philosophy.

/* Пример №1 */ //: c06:Car.java // композиция с использованием открытых объектов // двигатель class Engine{ public void start(){} public void rev(){} public void stop(){} } class Wheel{ public void inflare(int psi){}// накачать } // окно class Window{ public void rollup(){}// приоткрыть public void rolldown(){}// опустить } // дверь class Door{ public Window window=new Window(); public void open(){}//открыть public void close(){}// закрыть } // машина public class Car{ public Engine engine = new Engine(); public Wheel[] wheel = new Wheel[4]; public Door left = new Door(), right = new Door();//две двери public Car(){ for(int i = 0; i<4; i++) wheel[i]= new Wheel(); } public static void main(String[] args){ Car car= new Car(); car.left.window.rollup(); car.wheel[0].inflare(72); } } 

There is some author warning about using the code in this form:
"Since the composition of the object is part of the analysis of the task (and not
just part of the class implementation), declaring class members open, helps the client programmer understand how to use the class, and makes it easier for the creator to write code. However, it must be remembered that the described case is special, and basically the fields of the class must be declared private. "
Static nested classes

Defining nested classes:
A class is called nested if it is defined inside another class. That is, a class is simply defined inside another, not even important statically defined or not statically. A nested class is created to serve the class around it. If the nested class is useful in some other context, it should become a top-level class.
Application

Nested classes are used in cases when you need to write a small auxiliary code for another class. A nested class is also created to hide its variables and methods from the outside world. Thus, the nested class is another elegant way to limit the scope. It also makes sense to use inner classes if it is assumed that they will use parent elements in order not to pass on too much in constructors.

You can see an example of a nested class in the Orakle documentation:

 /* Пример №2 */ // class OuterClass { ... class NestedClass { ... } } 

We do not have, so far, any context for the use of this construct. With the same success, we can name the nested class instead of: “Nested class” (NestedClass) - “Inner class” InnerClass. Further we will understand what the differences are and in what contexts the classes are used. Bruce Ekkel writes in his book The Java Philosophy:
A class is called nested if it is defined inside another class "
Oracle documentation can be viewed at this link: >>>

Terminology:

There are four categories of nested classes:

  1. Static nested classes and non-static nested classes. Nested classes declared statically are called nested static classes.
  2. Inner classes - when an object of the inner class is associated with an object of the framing class. Non-static nested classes are called inner classes if they are associated with an outer class.
  3. Local classes are declared inside a block of code and are not a member of the framing class. In this case, you can consider the class as a local variable of type class.
  4. Anonymous classes are inheritable from any class in which the class name is not specified when declaring.

Reasons for using nested classes (Nesred Classes)
Why use nested classes?

The reasons for using nested classes are as follows. If a class is only useful for one other class, then it is logical to embed it in this class and store them together. Using nested classes increases encapsulation. Consider two top-level classes, A and B, where B needs access to members that would otherwise be declared closed.

 /* Пример №3 */ // class A{ ... class B { ... } } 


By hiding class “B” within class “A”, members of class “A” can be declared closed, and “B” can access them. In addition, the "B" itself can be hidden from the outside world.

Let's demonstrate it in the code:

 /* Учебный пример №4 */ package innernested; /** * * @author Ar20L80 */ public class A { private static int iPrivVar; class B { void setPrivateOfA(int var) { A.iPrivVar = var; } } } 

Using nested classes results in more readable and supported code:
Placing the class closer to where it will be used makes the code more readable.

Static Nested Classes
Static Nested Classes

The reasons for using static nested classes are as follows.

For the case when the relationship between the object of the nested class and the object of the external class is not needed, you can make the nested class static.

Since the inner class is associated with an instance, it cannot define any static members in itself.

Static nested classes have no restrictions on declaring their data and fields as static.

From the nested static class, we do not have access to the external non-static variable of the external class.

The code below demonstrates this:

 /* Учебный пример №5 Статические вложенные классы Попытка доступа к нестатической переменной внешнего класса Outer2 через обращение из вложенного статического класса Nested2 */ package nested; /** * * @author Ar20L80 * 20.03.2016 */ public class Outer2 { public int pubOutVar; // переменная не статическая и мы не имеем к ней доступа // из внутреннего статического класса private int prOutVar; public Outer2(){} static class Nested2{ public static int pub_innVar; // тут все в порядке public Nested2() {} int getOuterPublicVariable() { return Outer2.this.pubOutVar; // ошибка return Outer2.pubOutVar; // ошибка } int getOuterPrivateVariable() { return Outer2.this.prOutVar; // ошибка return Outer2.prOutVar; // ошибка } } } /* вывод программы: программа не компилируется */ 

Conclusion: We do not have access to the non-static field of the outer class through the static context of the nested class.

But we have access to the private static fields of the outer class from the nested static class.

The following code snippet demonstrates this:

 /* Учебный пример №6 Статические вложенные классы Демонстрация доступа к «приватной» статической переменной внешнего класса из внутреннего статического класса 20.03.2016 */ package nested; /** * * @author Ar20L80 */ public class Outer3 { private static int prStOuterVar; public Outer3(){} static class Nested3 // Nested { int getStaticOuterVar() { return Outer3.prStOuterVar; // ok } void setStaticOuterVariable(int var) { Outer3.prStOuterVar = var; // ok } } public static void main(String[] args) { Outer3.Nested3 nestedObj = new Outer3.Nested3(); // экземпляр класса внутренний Outer3.prStOuterVar = 19; System.out.println("nestedObj.getStaticOuterVar() = "+nestedObj.getStaticOuterVar());//статическая переменная внешнего класса из экземпляра внутреннего // устанавливаем через экземпляр внутреннего класса nestedObj.setStaticOuterVariable(77); System.out.println("Outer3.prStOuterVar = "+ Outer3.prStOuterVar); } } /* Вывод программы: nestedObj.getStaticOuterVar() = 19 Outer3.prStOuterVar = 77 */ 

In this sample code, we created an instance of the inner class with the name "nestedObj".
That is, we get access to a private static variable of the outer class, through an instance of the inner class. In the context of the instance associated with the outer class, we have an inner class.

Literature

Michael Morgan. "Java 2. Developer Guide" ISBN 5-8459-0046-8
Bruce Ekkel. "The Philosophy of Java." ISBN 5-272-00250-4
Herbert Shieldt “Java. Complete guide. 8th edition. "ISBN: 978-5-8459-1759-1

References:

ru.wikipedia.org
src-code.net/lokalnye-vnutrennie-klassy-java

Oracle documentation

All questions, comments, additions, criticism are welcome.

To be continued…
Part 2 >>

Source: https://habr.com/ru/post/439648/