Производительность универсального интерфейса Java - PullRequest
6 голосов
/ 30 апреля 2010

Простой вопрос, но, наверное, хитрый ответ.

Влияет ли использование универсальных интерфейсов на производительность?

Пример:

public interface Stuff<T> {

    void hello(T var);
}

vs

public interface Stuff {

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

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

Это правильно?

Ответы [ 4 ]

10 голосов
/ 30 апреля 2010

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

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;
    }
}

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

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, то будут вызваны оба метода Integer вместо синтетических Object методов.

7 голосов
/ 30 апреля 2010

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

4 голосов
/ 30 апреля 2010

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

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

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

1 голос
/ 30 апреля 2010

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

- ИСПРАВЛЕНИЕ -

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...