java—为什么lombok在重写泛型getter时会生成额外的getter?

wko9yo5t  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(445)

我有一个接口,它定义了一个id字段(和其他字段,但很简单),它使用java的泛型。
我使用lombok为实现这个的类生成getter和builder。
IdType getId() 在接口中,lombok同时生成 Object getId() ,和 UUID getId() . 这两个方法在通过反射调用时都可以工作,但这是非常奇怪的,并且弄乱了一些假设一个类不会有多个具有相同名称和不同返回类型的方法的代码。
(i<3反射)
下面是一个单元测试,它显示了这种行为。我的长跑错了吗?有没有其他的注解我需要申请?我只是耸耸肩写代码让所有getter检查并避免它吗?
Java8,Lombok1.18.16,当前最新。

public class LombokGeneratesDuplicateMethodsTest {
    interface WithId<IdType> {
        IdType getId();
    }

    @Getter
    @Builder
    static class Record implements WithId<UUID> {
        private UUID id;
        private String name;
    }

    @Test
    public void testStuff() throws Exception {
        Collection<Method> getIds = Arrays.stream(Record.class.getDeclaredMethods())
                .filter(m -> Modifier.isPublic(m.getModifiers()))
                .filter(m -> !Modifier.isStatic(m.getModifiers()))
                .filter(m -> !Void.TYPE.equals(m.getReturnType()))
                .filter(m -> m.getParameterTypes().length == 0)
                .filter(m -> m.getName().equals("getId"))
                .collect(Collectors.toList());

        assertThat(getIds.size()).isEqualTo(2);  // This seems wrong...

        UUID someId = UUID.randomUUID();
        Record record = Record.builder().id(someId).name("Gunter").build();
        for (Method getId : getIds) {
            assertThat(getId.invoke(record)).isEqualTo(someId);
        }

        WithId<UUID> withId = record;
        assertThat(withId.getId()).isEqualTo(someId);
        assertThat(record.getId()).isEqualTo(someId);
    }
}
kiz8lqtg

kiz8lqtg1#

与Lombok山无关。
试试看。编写以下代码:

interface Example<T> {
    T get();
}

class Foo implements Example<String> {
    public String get() {return null;}
}

然后:

>javac Foo.java
>javap Foo
Compiled from "Foo.java"
class Foo implements Example<java.lang.String> {
  Foo();
  public java.lang.String get();
  public java.lang.Object get();
}

这在jls中。返回对象的方法称为合成桥接器。它在那里,但不是特别显眼 javac (javac知道这一点,但其行为就好像它不存在一样)。在类文件级别(JVM,以及某种程度上的反射),它确实存在。
那么,如何修复呢?
检查合成标志。将为返回1的对象设置:

class Foo implements Example<String> {
        public String get() {return null;}

        public static void main(String[] args) throws Exception {
                for (Method m : Foo.class.getDeclaredMethods()) {
                        System.out.println(m.getReturnType() + " " + m.getName() + ": " + m.isSynthetic());
                }
        }
}

然后:

> javac Foo.java; java Foo
void main: false
class java.lang.String get: false
class java.lang.Object get: true

(i<3反射)
冒着下雨的危险,这是。。。在我看来,对于一个优秀的java程序员来说,这不是一个好的心态。java并不能使反射变得简单,而且工具也大多假设您也没有积极地使用它。例如,当您使用反射调用一组方法而不是实际调用它们时,重构脚本就不能很好地执行。

相关问题