Вложенные и внутренние классы

В Java определены вложенные классы. Вложенным называется такой класс, который объявляется в другом классе.

Вложенный класс не может существовать независимо от класса, в который он вложен. Следовательно, область действия вложенного класса ограничена его внешним классом. Если вложенный класс объявлен в пределах области действия внешнего класса, то он становится членом последнего. Имеется также возможность объявить вложенный класс, который станет локальным в пределах блока

Существуют два типа вложенных классов. Одни вложенные классы объявляются с помощью модификатора доступа static, а другие - без него. Нестатический вариант вложенных классов называются внутренними.

Внутренние классы позволяют вам группировать классы, логически принадлежащие друг другу, и управлять доступом к ним. Однако важно понимать, что внутренние классы заметно отличаются от композиции.

Внутренний класс может взаимодействовать со своим внешним классом, а код, написанный с использованием внутренних классов, получается более элегантным и понятным.

Создание внутренних классов

Создать внутренний класс несложно - достаточно разместить определение класса внутри окружающего класса.

public class Main {

    public static void main(String[] args) {
        Parcel parcel = new Parcel();
        parcel.ship("Лимпопо");
    }
}

class Parcel {

    class Contents {
        private int i = 11;
        public int value() {return i;}
    }
    
    class Destination {
        private String label;

        public Destination(String label) {
            this.label = label;
        }

        public String getLabel() {
            return label;
        }
    }
    
    public void ship(String destination) {
        Contents c = new Contents();
        Destination d = new Destination(destination);
        System.out.println(d.getLabel());
    }
}

Внутренний класс имеет доступ ко всем переменным и методам внешнего класса, в который он вложен, и может обращаться к ним непосредственно, как и все остальные нестатические члены внешнего класса.

Иногда внутренний класс используется для предоставления ряда услуг внешнему классу, в котором он содержится.

public class Outer {

    private List<Integer> numbers = new ArrayList<>();

    public void printAnalyticalData() {
        Inner inner = new Inner();

        System.out.println("Min: " + inner.min());
        System.out.println("Max: " + inner.max());
        System.out.println("Sum: " + inner.sum());
    }

    private class Inner {
        private int min() {
            return numbers.stream().min(Integer::compareTo).orElse(0);
        }

        private int max() {
            return numbers.stream().max(Integer::compareTo).orElse(0);
        }

        private int sum() {
            return numbers.stream().reduce(Integer::sum).orElse(0);
        }
    }
}

Класс можно вложить в область действия блока. В итоге получается локальный класс, недоступный за пределами блока.

public class Main {
    public static void main(String[] args) {
        
        class Local {
            private int value;

            private Local(int value) {
                this.value = value;
            }
        }
        
        Local local = new Local(10);
    }
}

Также внутренний класс можно быть анонимным классом (анонимные классы уже были рассмотрены ранее).

Last updated