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

Последствия эффективности анонимного класса Java

Есть ли разница в эффективности (например, время выполнения, размер кода и т.д.) между этими двумя способами выполнения вещей?

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

Использование анонимных объектов:

void doSomething() {
    for (/* Assume some loop */) {
        final Object obj1, obj2; // some free variables

        IWorker anonymousWorker = new IWorker() {
            doWork() {
                // do things that refer to obj1 and obj2
            }
        };
    }
}

Определение класса сначала:

void doSomething() {
    for (/* Assume some loop */) {
        Object obj1, obj2;
        IWorker worker = new Worker(obj1, obj2);
    }
}

static class Worker implements IWorker {
    private Object obj1, obj2;
    public CustomObject(Object obj1, Object obj2) {/* blah blah */}

    @Override
    public void doWork() {}
};
4b9b3361

Ответ 1

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

Это не проявится в производительности, но будет влиять на вас, если вы когда-либо сериализуете эти классы.

Ответ 2

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

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

(Для записи, когда анонимный внутренний класс ссылается на final в охватывающей области, это реализуется на уровне байт-кода с помощью скрытых аргументов конструктора и атрибутов скрытого экземпляра. Байт-коды будут почти такими же, как байт-коды, которые вы получаете от своей другой реализации.)

Ответ 3

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

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

Ответ 4

Я действительно заметил, что эффективность производительности при создании экземпляров анонимного класса.

Мысль, если может быть из-за того, что локальный класс статичен, я удалил это, и это не имело никакого значения.

В моем случае я делал что-то 1000, выбираю 3 раза, что составляет 499 500. Версия с локальным классом (независимо от статики или нет) заняла 26 секунд, а версия с анонимным функционально идентичным классом заняла 2 минуты 20 секунд.

Ответ 5

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

Примером плохой практики может быть что-то вроде:

public List<String> someMethod() {
       return new ArrayList<String>() {{
                      add("Item one");
                      add("Item two");
              }};
}

В то время как это синтаксическое удобство выглядит на первый взгляд умным, это (часто незаметно) создает анонимный внутренний класс, объект которого ссылается на внешний экземпляр. Поскольку этот объект также присваивается внешнему в качестве значения результата someMethod, вы не можете быть уверены, что ваш вызывающий абонент делает с этим списком. Если он помещает полученный экземпляр ArrayList в некоторую статическую переменную, ваш текущий объект также будет сохранен навсегда!

Ответ 6

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

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