Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting value in constructor aliases collections #1642

Closed
jimshowalter opened this issue May 14, 2024 · 5 comments
Closed

Setting value in constructor aliases collections #1642

jimshowalter opened this issue May 14, 2024 · 5 comments

Comments

@jimshowalter
Copy link

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:

Screenshot 2024-05-13 at 8 07 26 PM

How can I create a new hash set each time?

@dogourd
Copy link

dogourd commented May 15, 2024

try to use

.intercept(MethodCall.invoke(getConstructor(entityClass))
    .onSuper()                   
    .andThen(MethodCall.construct(HashSet.class.getConstructor())
        .setsField(named(MODIFIED_FIELDS_TRACKER_FIELD_NAME))
    )
);

@jimshowalter
Copy link
Author

jimshowalter commented May 15, 2024

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.)

@raphw
Copy link
Owner

raphw commented May 16, 2024

You could not load the class if it did not call super, I assume it's simply not printed as this is implicit.

@jimshowalter
Copy link
Author

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.

@raphw
Copy link
Owner

raphw commented May 16, 2024

What does javap show?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants