raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.23k stars 804 forks source link

What is the best way to create setters and getters by field name? #1570

Closed PavelTurk closed 9 months ago

PavelTurk commented 9 months ago

I am working on project that needs to set and get values to/from instances of different classes by field name automatically. For example:

Let's suppose we have class Person:

public class Person {

   private String name;

   private String surname;
   + setters and getters
}

And we have row with data:

name     | surname
---------|---------
John     | Black

And it is necessary to load these data to instance var person = new Person() automatically.

This is just a small example. Real situation - about 50 classes with 8 - 15 fields in every class.

The only solution I found (using byte-buddy of course) is to create dynamically classes for every field. I mean, for Person.name the following class is created:

public class PersonName implements SetterGetter<Person, String> {

    public void set(Person p, String value) {
             p.setName(value);
    }

    public String get(Person p) {
          return p.getName();
    }
}

So, when we have name in data we take instance of PersonName and pass data and instance of Person to it. This solution works and it is very fast. However, such solution needs to create too many classes and it confuses me. I feel, that I am doing something wrong.

Could anyone say what is the best strategy to solve such problems?

raphw commented 9 months ago

I would use MethodHandles for this and not code generation. Handles are as fast as regular code, more or less, as long as you keep the handles cached. I assume you are on Java 8+.

PavelTurk commented 9 months ago

@raphw Thank you very much for your answer. I've considered MethodHandle but then found this article https://www.optaplanner.org/blog/2018/01/09/JavaReflectionButMuchFaster.html#_methodhandles

UPDATE - Or the reason of such bad performance in the tests is that obtaining getterMethodHandle is done for every test? By other words in these tests MethodHandles instances are not cached as you suggest.

PavelTurk commented 9 months ago

@raphw I moved to MethodHandle. Thank you very much for your help.