Java универсальная Интерфейсная производительность

Простой вопрос, но хитрый ответ я предполагаю.

Использующая Универсальная производительность вреда Интерфейсов?

Пример:

public interface Stuff<T> {

    void hello(T var);
}

vs

public interface Stuff {

    void hello(Integer var);  <---- Integer used just as an example
}

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

Это корректно?

6
задан halfwarp 30 April 2010 в 16:08
поделиться

4 ответа

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

public class GenericPerformance {
    public static void main(final String[] args) {
        final Stuff<Integer> stuff = new IntStuff();
        final Integer data = stuff.getData();
        stuff.putData(data);
    }
}

interface Stuff<T> {
    T getData();
    void putData(T stuff);
}

class IntStuff implements Stuff<Integer> {
    private Integer stuff;
    public Integer getData() {
        return stuff;
    }
    public void putData(final Integer stuff) {
        this.stuff = stuff;
    }
}

Если вы посмотрите на сгенерированный байткод, то увидите: В методе main вызываются методы стертого интерфейса

java.lang.Object Stuff.getData()
void Stuff.putData(java.lang.Object)

-. Эти методы, реализованные в IntStuff с сигнатурами

java.lang.Object getData()
void putData(java.lang.Object)

обе с модификаторами public bridge synthetic, делегируют "настоящим" методам

java.lang.Integer IntStuff.getData()
void putData(java.lang.Integer)

Первый синтетический метод просто возвращает результат Integer, а второй выполняет приведение из Object в Integer перед вызовом putData(Integer).

Если изменить переменную stuff на тип IntStuff, то вместо синтетических Object методов будут вызваны оба Integer.

10
ответ дан 8 December 2019 в 05:53
поделиться

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

7
ответ дан 8 December 2019 в 05:53
поделиться

Они просто помогают во время компиляции обеспечить безопасность типов.

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

Взято из: http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html

4
ответ дан 8 December 2019 в 05:53
поделиться

На самом деле, я считаю, что в вашем примере ЕСТЬ небольшая разница в производительности. Скомпилированная форма первой версии предполагает, что hello() получает Object, а во второй - Integer. Поэтому, когда вы инстанцируете StuffImpl, вызовы hello() будут немного медленнее из-за неявного приведения, добавленного компилятором.

-- СПРАВКА --

Неявное приведение не будет добавлено к hello(). Однако, если вы добавите метод getter, возвращающий T, приведение будет добавлено к возвращаемому значению.

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

1
ответ дан 8 December 2019 в 05:53
поделиться
Другие вопросы по тегам:

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