Вопрос по java, inner-classes – Внутренние классы обычно используются в Java? Они «плохие»? [закрыто]

18

Внутренние классы обычно используются в Java? Это то же самое, что и вложенные классы? Или они были заменены в Java чем-то лучшим? У меня есть книга о версии 5, и в ней есть пример использования внутреннего класса, но мне показалось, что я читал, что внутренние классы были "плохими".

Я понятия не имею и надеялся на мысли об этом.

Спасибо.

Терминология. Вложенные классы делятся на две категории: статические и нестатические. Вложенные классы, которые объявлены статическими, просто называются статическими вложенными классами. Нестатические вложенные классы называются внутренними классами. & Quot; -- Отjava.sun.com/docs/books/tutorial/java/javaOO/nested.html Michael Myers♦
Возможный дубликатstackoverflow.com/questions/487126/… victor hugo
(a) Да (b) Нет (c) Нет, если вы не учитываете лямбды & amp; затворы. Если вы можете привести свой источник для теории, что они «плохие» пожалуйста, процитируйте это, чтобы мы могли избежать этого. user207421

Ваш Ответ

8   ответов
0

public class OuterClass {

private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() {
    @Override
    protected void printAboutme() {
        System.out.println("AnonymousInnerClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
};

public void displayAnonymousInnerClass() {
    anonymousInnerClass.printAboutme();
}

public void displayStaticInnerClass() {
    NestedStaticClass staticInnerClass = new NestedStaticClass();
    staticInnerClass.printAboutMe();
}

public void displayInnerClass() {
    InnerClass innerClass = new InnerClass();
    innerClass.printAboutMe();
}

public void displayMethodInnerClass(){

    class MethodInnerClass {

        private String sampleField = "Method Inner Class";
        public void printAboutMe() {
            System.out.println("MethodInnerClass.printAboutMe.........");
            Class clazz = this.getClass();

            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {

                String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
                message = message + " " + field.getType().getSimpleName();
                message = message + " " + field.getName();

                System.out.println(message);
            }
        }
    }

    MethodInnerClass methodInnerClass = new MethodInnerClass();
    methodInnerClass.printAboutMe();
}

class InnerClass {
    private String sampleField = "Inner Class";
    public void printAboutMe() {
        System.out.println("InnerClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
}


abstract class AnonymousInnerClass {
    protected String sampleField = "Anonymous Inner Class";
    protected abstract void printAboutme();
}

static class NestedStaticClass {
    private String sampleField = "NestedStaticClass";
    public void printAboutMe() {
        System.out.println("NestedStaticClass.printAboutMe.........");
        Class clazz = this.getClass();

        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {

            String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
            message = message + " " + field.getType().getSimpleName();
            message = message + " " + field.getName();

            System.out.println(message);
        }
    }
}

}

в этом примере сравнивается каждый тип нестатического вложенного класса со статическим вложенным классом. Теперь, если вы запустите метод отображения класса Outer для каждого вложенного класса, вы увидите выходные данные каждого метода вложенного класса printAboutMe (), который имеет некоторый код отражения распечатать все переменные-члены вложенных классов.

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

например, если мы выполним следующий код для InnerClass. : -

public class NestedClassesDemo {

public static void main(String[] args) {
    OuterClass outerClass = new OuterClass();
    outerClass.displayInnerClass();
}

}

вывод выглядит так:

InnerClass.printAboutMe.........
private String sampleField
protected OuterClass this$0

Обратите внимание, что эта переменная-член-загадка имеет $ 0 класса включения класса (Outer class).

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

Так что это делает использование внутренних классов плохим, если не используется prpperly.

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

«статическое внутреннее»; этоcontradiction in termsи «нестатический вложенный»; может быть заменен на «внутренний».
30

и что-то очень похожее - анонимные классы - практически незаменимы, так как они - самое близкое к закрытию Java. Поэтому, если вы не можете вспомнить, откуда вы слышали, что внутренние классы плохие, постарайтесь забыть об этом!

@DanielEarwicker Есть ли в Java анонимные классы сейчас? johnny
@skaffman - вот так! Просто посмотрел на них, не мог в это поверить. Вы думаете, что создали список & lt; int & gt ;? Угадай снова, мой друг, угадай снова!
замыкания в основном позволяют отправлять фрагмент кода куда-то еще, и все еще ссылаются на его исходное окружение. Это может быть очень, очень приятно.
просто не упоминайте инициализаторы с двойными скобками ...
@ Джонни Э-э, с 1997 года я думаю! :)
2

данного типа коллекции. Это класс, который реализует общедоступный интерфейс, но не имеет никакого бизнеса, кроме как в связи с другим классом. Это позволяет вам моделировать вещи, которые в C ++ вам придется делать с оператором друга.

2

ости. Они имеют доступ к полям-членам класса включения, но не напрямую, а через средства получения, которые создаются автоматически. Это будет медленнее, чем просто копирование членов включающего класса во внутренний класс.

Описаны некоторые другие проблемы с нестатическими внутренними классами.Вот

«статическое внутреннее»; этоcontradiction in termsи «нестатический вложенный»; может быть заменен на «внутренний».
0

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

1

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

19

Они могут быть предметом злоупотребления (например, внутренние классы внутренних классов). Как только мой внутренний класс занимает несколько строк, я предпочитаю извлекать его в свой собственный класс. Это способствует удобочитаемости и тестированию в некоторых случаях.

Есть одна ошибка, которая не сразу очевидна и заслуживает запоминания. Любой неstatic внутренний класс будет иметь неявную ссылку на окружающий внешний класс (неявная «эта» ссылка). Обычно это не проблема, но если вы хотите сериализовать внутренний класс (скажем, используяXStream), вы обнаружите, что это может вызвать у вас неожиданное горе.

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

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

Я бы сказал, что одна из проблем с внутренними классами заключается в том, что их синтаксис несколько «уродлив». Это то, что обескураживает некоторых людей. Здесь на работе их много.

Похожие вопросы