Почему Android предпочитает статические классы
Я вижу много кода java, где android предпочитает, чтобы разработчики использовали статические внутренние классы. Особенно для таких моделей, как Паттерн ViewHolder в пользовательских ListAdapters.
Я не уверен, каковы различия между статическими и нестатическими классами. Я читал об этом, но, похоже, это не имеет смысла, когда речь идет о производительности или памяти.
5 ответов
это не только разработчики 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;
Outer$NonStaticInner(Outer enclosing) { this = enclosing; }
}
class Outer$StaticInner {
Outer$StaticInner(){}
}
главное отличие статических и нестатических внутренних классов заключается в том, что нестатический внутренний класс имеет доступ к членам внешнего класса, даже если они частные. Нестатические внутренние классы являются "частью" внешнего класса. Вы не можете создавать и не можете существовать без экземпляра внешнего класса. Следствием этого является то, что экземпляр нестатических внутренних классов уничтожается при уничтожении экземпляра внешнего класса.
статические внутренние классы, на с другой стороны, они похожи на обычные внешние классы. Они живут и умирают сами по себе. Вам не нужен экземпляр внешнего класса для существования внутреннего класса. Это означает, что у них тоже есть свой жизненный цикл. Они уничтожаются, когда мусорщик решает уничтожить их.
Как это влияет на память и/или производительность? Я действительно не знаю. :)
статические внутренние классы (т. е. классы, объявленные внутри другого класса с помощью ключевого слова static
) очень похожи на" нормальные " классы, за исключением того, что вы не загрязняете пространство имен вашего пакета. Это их (единственная) разница и польза, и я считаю, что именно по этой причине вы видите это в Android.
используйте статические внутренние классы, когда цель класса-затянуть к основному классу, но не зависит от его экземпляров. В целом это считается хорошей практикой.
Если вы декомпилируете внутренний класс (или смотрите его с помощью отладчика), вы можете увидеть, что существует сгенерированный код для доступа к экземпляру внешнего класса, который использовался для их создания. Накладные расходы для этого больше памяти для дополнительного указателя, больше cpu для сборки мусора из-за дополнительного указателя для тестирования, и если вы хотите nit pick, больше времени компиляции. Создание экземпляров нестатических внутренних классов немного сложнее, потому что вам нужен экземпляр внешнего класса для создать их.
видимость и статических и нестатических внутренних классов можно контролировать. Обычно они являются частными, если их реализация сильно связана с внутренними деталями внешнего класса, и разработчик не думает, что код можно использовать повторно. В этом смысле они не лучше частных функций. Внутренние классы могут быть общедоступными в таких случаях, как Map.Запись, где внутренний класс сильно связан с интерфейсом, предоставляемым классом, а разработчик не подумай о карте.Запись может быть использована без какой-либо карты. Оба типа имеют доступ к закрытым членам внешнего класса, а внешний класс имеет доступ к закрытым членам внутреннего класса.
экземпляры статических и нестатических внутренних классов-это мусор, собранный, как и любой другой класс. Нет никакой особой связи между коллекцией grabage внешнего класса и сборкой мусора внутреннего класса.
в случае реализации классов UI, таких как swing или android вы увидите статические внутренние классы, потому что они рассматриваются как частная функция. Эти классы не разработаны для повторного использования вне внешнего класса и сильно связаны с внутренней реализацией внешнего класса. Нет причин выставлять их и убеждаться, что они могут работать в большем количестве случаев, чем конкретный контекст требований внешнего класса.
нестатический экземпляр внутреннего класса содержит ссылку на экземпляр внешнего класса, а статический экземпляр внутреннего класса-нет.
это относится к области памяти приложений, так как скрытая ссылка может привести к утечке памяти - сборщик мусора не может собрать экземпляр внешнего класса, пока не будет больше ссылок. Также дополнительная ссылка сама нуждается в памяти, это может быть актуально, если используется большое количество экземпляров.
class Outer{
class Inner{//Only works with non static inner class
public Outer getOuter(){return Outer.this;}
}
}
это также актуально для его использования, ссылка на внешний класс является аргументом ctor внутреннего класса, чтобы создать новый нестатический объект внутреннего класса, который вы должны вызвать ctor как memberfunction на экземпляре внешнего класса или изнутри memberfunction внешнего класса. Это означает, что вы не можете иметь экземпляр внутреннего класса без экземпляра внешнего класса.
Outer.Inner in = new Outer().new Inner();