Подтвердить что ты не робот

Почему Android предпочитает статические классы

Я вижу много java-кода, где android предпочитает, чтобы разработчики использовали статические внутренние классы. В частности, для шаблонов, таких как Шаблон ViewHolder в пользовательских ListAdapters.

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

4b9b3361

Ответ 1

Это не только разработчики Android...

Нестатический внутренний класс всегда сохраняет неявную ссылку на окружающий объект. Если вам не нужна эта ссылка, все, что она делает, это память затрат. Рассмотрим это:

class Outer {
    class NonStaticInner {}
    static class StaticInner {}
    public List<Object> foo(){ 
        return Arrays.asList(
            new NonStaticInner(),
            new StaticInner()); 
    }
}

Когда вы скомпилируете его, то получится что-то вроде этого:

class Outer {
    Outer(){}
    public List<Object> foo(){ 
        return Arrays.asList(
            new Outer$NonStaticInner(this),
            new StaticInner()); 
    }
}
class Outer$NonStaticInner {
    private final Outer this$0;
    Outer$NonStaticInner(Outer enclosing) { this$0 = enclosing; }
}
class Outer$StaticInner {
    Outer$StaticInner(){}
}

Ответ 2

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

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

Как это влияет на память и/или производительность? Я действительно не знаю.:)

Ответ 3

Статические внутренние классы (т.е. классы, объявленные внутри другого класса с ключевым словом static), очень похожи на "нормальные" классы, за исключением того, что вы не загрязняете пространство имен вашего пакета. Это их (единственная) разница и польза, и я считаю, что причина, по которой вы ее видите в Android.

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

Ответ 4

Если вы декомпилируете внутренний класс (или смотрите его с помощью отладчика), вы можете увидеть, что создан код для доступа к экземпляру внешнего класса, который использовался для их создания. Накладные расходы для этого - больше памяти для дополнительного указателя, больше cpu для сбора мусора из-за дополнительного указателя на тест, и если вы хотите выбрать nit, больше времени компиляции. Создание экземпляров нестационарных внутренних классов немного сложнее, потому что для их создания требуется экземпляр внешнего класса.

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

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

В случае реализации классов UI, таких как swing или android, вы увидите статические внутренние классы, потому что они рассматриваются как частные функции. Эти классы не разработаны для повторного использования вне внешнего класса и сильно связаны с внутренней реализацией внешнего класса. Нет причин раскрывать их и убедиться, что они могут работать в большем количестве случаев, чем конкретный контекст требований внешнего класса.

Ответ 5

Нестационарный внутренний экземпляр класса содержит ссылку на экземпляр внешнего класса, а экземпляр статического внутреннего класса - нет.

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

class Outer{
    class Inner{//Only works with non static inner class
          public Outer getOuter(){return Outer.this;}
    }
}

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

Outer.Inner in = new Outer().new Inner();