Какие бывают внутренние классы? Как правильно создавать объект вложенного класса? Как правильно создавать объект внутреннего класса? Зачем использовать ключевое слово final при создании анонимных классов? Во что компилируется анонимный внутренний класс?​

Внутренние классы бывают следующих типов:
-вложенные (статические) внутренние классы;
-внутренние классы члены;
-локальные классы;
-анонимные классы.

Вложенные статические классы.​

Имеют доступ только к статическим полям и методам содержащего их класса. Для создания экземпляра не требуется объект внешнего класса.

class OuterClass {
    private static String secret = "secret string";
//Объявление вложенного класса
    public static class InnerStaticClass {
        static void printString(String str) {
            System.out.println(str);
        }

        void printReverseString(String str) {
            StringBuilder sb = new StringBuilder(str);
            System.out.println(sb.reverse());
        }
        static void printSecret(){
            System.out.println(secret);
        }
    }
}

public class TestClass{
    public static void main(String[] args) {
        String string = "Мама мыла раму";
//Вызов методов вложенного класса
        OuterClass.InnerStaticClass.printString(string);
//Создание экземпляра вложенного класса
        OuterClass.InnerStaticClass inClass = new OuterClass.InnerStaticClass();
        inClass.printReverseString(string);
//Обращение к приватным полям внешнего класса через метод внутреннего класса
        OuterClass.InnerStaticClass.printSecret();
    }
}

Вложенные статические классы в основном используются для группировки. Пример из кода компилируется в два класса OuterClass$InnerStaticClass.class и OuterClass.class.

Внутренние классы члены.​

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

class OuterClass {
    int k = 10;
    static int i = 20;
    public class InnerMemberClass{
        public <T extends Number> void  printArray(T[] arr){
            for(T t:arr){
                System.out.print(t.toString() + " ");
            }
            System.out.println();
            staticMethod();
            System.out.println("Outer fields: "+k+" "+i);
        }
    }
    public Integer[] genArray(){
         Integer[] arrInt = new Integer[] {10,20,30,40,90,80,70};
         return arrInt;
    }
    public static void staticMethod(){
        System.out.println("i'm static");
    }
}

public class TestClass{
    public static void main(String[] args) {
        OuterClass.InnerMemberClass innClass = new OuterClass().new InnerMemberClass();
        innClass.printArray(new OuterClass().genArray());

    }
}

Во внутренних классах-членах нельзя объявлять статические поля, статические методы и перечисления.

Локальные классы.​

Локальные классы создаются в блоках инициализации и в статических блоках java кода. Но чаще всего они используются внутри методов. Они могут обращаться только к финальным полям обрамляющего класса и аргументам метода. Его нельзя создать за пределами блока кода, в котором он описан. Локальный класс не может быть private, public, protected или static.

class OuterClass {
    final int k = 222;
    public void someMethod(final int k,int i){
        class LocalClass{
            public void printArg(){
                System.out.println("LocalClass.printArg(field--> "+OuterClass.this.k+" | "+k+" <--arg)");
            }
        }
        new LocalClass().printArg();
    }
}

public class TestClass{
    public static void main(String[] args) {
        new OuterClass().someMethod(321,123);
    }
}
Анонимные классы.​

Анонимные классы используются в месте их создания. Они не имеют имени. Являясь частным случаем локального класса они приемствуют все ограничения локальных классов. Также могут обращаться к финальным локальным переменным внешнего класса и ко всем полям обрамляющего класса. Локальные переменные должны быть финальными для того, что бы пользователь класса был уверен в том, что пока он работает с данными они не изменятся во внешнем коде, что их состояние остаётся актуальным на всём протяжении жизни анонимного класса.

public class TestAnonimClass{
    static final int k = 0;
    public static void main(String[] args) {
        new Thread(new Runnable() {
            int k = TestAnonimClass.k;
            public void run() {
                for(;;){
                    k++;
                    if(k%33==0){
                        System.out.println(k);
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
}

После компиляции анонимный класс из примера выше выглядит как TestAnonimClass$1.class, но в программе мы не можем обратиться к нему по такому имени.

Понравилась статья? Поделиться с друзьями:

Комментарии:

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: