Setting value in constructor aliases collections
jimshowalter opened this issue · 5 comments
In #1638 I thought we had a solution to defining a constructor that initializes a field to a value:
.defineConstructor(Visibility.PUBLIC)
.intercept(
MethodCall.invoke(getConstructor(entityClass))
.onSuper()
.andThen(
FieldAccessor.ofField(MODIFIED_FIELDS_TRACKER_FIELD_NAME)
.setsValue(new HashSet<String>())))
But that turns out to put the same collection in all instances of the class, instead of creating a new hash set per instance:
How can I create a new hash set each time?
try to use
.intercept(MethodCall.invoke(getConstructor(entityClass))
.onSuper()
.andThen(MethodCall.construct(HashSet.class.getConstructor())
.setsField(named(MODIFIED_FIELDS_TRACKER_FIELD_NAME))
)
);
That seems to have worked!
The only thing now is the decompiled constructor isn't calling super. Is that okay?
import lombok.Data;
@Data
public class Foo {
private String bar;
private int ignoreMe;
}
public class Foo$Setter$Tracking$ByteBuddy$Subclass extends Foo {
private final Set<String> _modified$Fields$Tracker = new HashSet();
public Foo$Setter$Tracking$ByteBuddy$Subclass() {
}
static {
cachedValue$SAlkJfUp$ojd8qn2 = Foo.class.getMethod("setIgnoreMe", Integer.TYPE);
cachedValue$SAlkJfUp$jj42cs3 = Foo.class.getMethod("setBar", String.class);
}
}
(Same behavior if lombok is replaced with manually-declared methods.)
You could not load the class if it did not call super, I assume it's simply not printed as this is implicit.
That's my assumption too. It's just a bit disconcerting that the .class bytecode doesn't render showing it. Could also be an IntelliJ limitation. Was going to try some command-line decompiler but jad isn't maintained, fernflower requires cloning their mirror, etc. Javap doesn't appear to be able to reconstruct pretty-printed source.
What does javap show?