mardi 17 novembre 2015

Performance of "reflection-based" static initializer with a generic-based Class parameter

It is well-known that reflection is slow, but my question deals with if the below is affected by reflection or not. This question is not, whether the method is correct or not, but the performance aspect.

Now I was testing out some idea with generics, and I liked the way it looked to the users of the code; however, I wanted to make a generic static initializer method. I can do that all with generics and it works; however, the syntax looks horrible and I could not get the syntax to look good.

  1. Bar foo = new Foo.Builder<Bar>().now(); // Good generic Constructor

  2. Bar foo = Foo.<Bar>build().now(); // Good generic static initializer. Doesn't read well

  3. Bar foo = Foo.build<Bar>().now(); // Compiler Error on generic static initializer

  4. Bar foo = Foo.<Bar>build().now(); // Good generics static initializer.

  5. Bar foo = Foo.build(Bar.class).now(); // Good reflection-based static initializer with a generic-based parameter

Now, let’s look at #4 more. Let’s assume the code looks like this…

public static class Foo<T extends Barz> {

    // Usage: Foo<Bar> foo = Foo.<Bar>build().now(); 
    public static <Z extends Barz> Foo<Z> build() {

        // …
        return new Foo<Z>();

    }
}

Again, this is what I originally had; however, it looks bad when reading the code that uses this. As far as I can tell, most people that use this code will always have a warning, because they don’t know to prepend the generic to the method name - usually generics are appended to the end of stuff. In fact, I had to look up how to get rid of the warning because I didn’t know why it persisted with generics.

Anyway, #5 is the code I thought up of that was clear in reading, and nobody would have a persisting warning.

public static class Foo<T extends Barz> {

    // Usage: Foo<Bar> foo = Foo.build(Bar.class).now();
    public static <Z extends Barz> Foo<Z> build(Class<Z> ignore) {

        // The variable “ignore” allows me to do reflection, but I am not using it. 

        // But does having this “Class<Z>” in the parameter 
        // cause negative performance compared to #4?

        // …
        return new Foo<Z>();

    }
}

I know I am not using reflection in #5, but I am creating the class that allows me to do reflection. So is #5 just as performant as the others? What makes reflection expensive? The creation of the class that I can reflect or just the operations I perform on the reflection class?





Aucun commentaire:

Enregistrer un commentaire