In Java, is there any way to alias an object field so that it has two names?

Viewed 364

I'm getting back into Java programming, and I have a situation where I'd like to do something like this:

public class FieldAliasTest {
    
    static public class Something {
        @Alias("somethingId")
        public Long id;
        @Alias("id")
        public Long somethingId;
    }
    
    static public void main(String[]args) {
        Something mySomething = new Something();
        mySomething.id = 1L;
        assert(mySomething.somethingId == 1L);
        mySomething.somethingId = 2L;
        assert(mySomething.id == 2L);
    }
}

Is there anything in the Java standard, Spring Boot, and/or Lombok libraries that would make that possible?

Is it possible at all?

I'm trying to avoid adding any functions like setSomethingId() and setId().

1 Answers

In short, no. Java does not support this.

You can build something like this, noting that you define aliases per instance, not on the class itself. Modify as needed:

public class AliasThingy {
    private final Map<String, Object> storage = new HashMap<>();
    private final Map<String, String> aliases = new HashMap<>();

    public AliasThingy (Map<String, List<String>> aliases) {
        aliases.forEach((key, value) -> value.forEach(alias -> this.aliases.put(alias, key)));
    }

    public void set(String key, Object value) {
        storage.put(aliases.getOrDefault(key, key), value);
    }

    public <T> T get(String key) {
        return (T)storage.get(aliases.getOrDefault(key, key));
    }

    public static void main(String[] args) {
        var something = new AliasThingy(Map.of(
            "id", List.of("somethingId")
        ));
        something.set("id", 1L);
        assert((long)something.get("somethingId") == 1L);

        something.set("somethingId", 2L);
        assert((long)something.get("id") == 2L);
    }
}

You could also use it as a base class, which lets you define the aliases in the class definition, plus an opportunity to avoid raw strings:

public class Something extends AliasThingy {
    public interface KEYS {
        String ID = "id";
        String SOMETHING_ID = "somethingId";
        String NAME = "name";
        String DESCRIPTION = "description";
        String TITLE = "title";
    }
    public Something() {
        super(Map.of(
            KEYS.ID, List.of(KEYS.SOMETHING_ID),
            KEYS.NAME, List.of(KEYS.DESCRIPTION, KEYS.TITLE)
        ));
    }

    public static void main(String[] args) {
        Something something = new Something();
        something.set(KEYS.ID, 1L);
        assert((long)something.get(KEYS.SOMETHING_ID) == 1L);

        something.set(KEYS.SOMETHING_ID, 2L);
        assert((long)something.get(KEYS.ID) == 2L);

        something.set(KEYS.TITLE, "Dr. Strangelove");
        assert(something.get(KEYS.NAME).equals("Dr. Strangelove"));
        assert(something.get(KEYS.DESCRIPTION).equals("Dr. Strangelove"));
    }
}
Related