views:

127

answers:

4

Simple question, but tricky answer I guess.

Does using Generic Interfaces hurts performance?

Example:

public interface Stuff<T> {

    void hello(T var);
}

vs

public interface Stuff {

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

My first thought is that it doesn't. Generics are just part of the language and the compiler will optimize it as though there were no generics (at least in this particular case of generic interfaces).

Is this correct?

+6  A: 

Yup - java generics are an entirely compile-time construct. The JVM sees it as a normal interface. So there's no runtime performance gain or loss using generics.

thecoop
+1  A: 

They are simply a helper at compile-time to get type safety.

Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler.

Taken from: http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html

Jarle Hansen
+1  A: 

Actually, I believe that in your example there IS a small performance difference. The compiled form of the first version assumes that hello() receives an Object, while in the second one it assumes an Integer. Therefore, when you instantiate StuffImpl<Integer>, the calls to hello() will be a little slower due to the implicit cast added by the compiler.

-- CORRECTION --

The implicit cast will not be added to hello(). However, if you add a getter method that returns T, the cast will be added to the returned value.

The bottom line is - usage of generics introduces negative performance impact in some cases, when compared with non-generic code restricted to specific types.

Eyal Schneider
For any concrete implementation of `Stuff<T>`, e.g. with T as `Integer`, there will be an implicit cast from `Object` to the concrete type, `Integer`. See my answer for details.
Christian Semrau
+3  A: 

There is potential for a minor performance loss, because the compiler sometimes adds synthetic bridge methods. Consider the following example:

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

If you look at the generated bytecode, you will see: In the main method, the erased interface methods

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

are invoked. That methods, implemented in IntStuff with the signatures

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

both with the modifiers public bridge synthetic, delegate to the "real" methods

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

The first synthetic method merely returns the Integer result, while the second performs a cast from Object to Integer before calling putData(Integer).

If you change the stuff variable to type IntStuff, then both Integer methods are called instead of the synthetic Object methods.

Christian Semrau
+1, beat me to it, the synthetic methods add overhead - although that is a micro-optimization that the JIT is likely to optimize away anyway, so no one should care about unless a problem actually presents itself. But it is useful to know in case.
Yishai
You are right. Usually, the overhead is *not* worth the effort of avoiding generics. But it seems the JIT can not fully optimize the bridge method away. I have just performed some tests with a loop containing only `final Integer data = intstuff.getData(); intstuff.putData(data);`. Running the loop with a `Stuff<Integer> stuff` variable needs 30% more time than with a `IntStuff stuff` variable, even with the `-server` JVM option.
Christian Semrau