获取相关的字段的getter / setter(成员变量)

时间:2018-08-14 09:12:34

标签: java reflection field getter-setter member-variables

我有一个# Final names of binaries EXECUTABLE = Bin/zipsample SO_LIBRARY = Bin/libzip.so # C & C++ compiler #CC = gcc #CXX = g++-4.8 CC = clang CXX = clang++ CFLAGS = -fPIC -Wno-enum-conversion -O3 CXXFLAGS = -fPIC -std=c++11 -O3 # Linker flags LDFLAGS = -pthread # Sources of external libraries SRC_ZLIB = $(wildcard Source/ZipLib/extlibs/zlib/*.c) SRC_LZMA = $(wildcard Source/ZipLib/extlibs/lzma/unix/*.c) SRC_BZIP2 = $(wildcard Source/ZipLib/extlibs/bzip2/*.c) # ZipLib sources SRC = \ $(wildcard Source/ZipLib/*.cpp) \ $(wildcard Source/ZipLib/detail/*.cpp) # Object files OBJS = \ $(SRC:.cpp=.o) \ $(SRC_ZLIB:.c=.o) \ $(SRC_LZMA:.c=.o) \ $(SRC_BZIP2:.c=.o) # Rules all: $(EXECUTABLE) $(SO_LIBRARY) $(EXECUTABLE): $(OBJS) $(CXX) $(CXXFLAGS) $(LDFLAGS) Source/Sample/Main.cpp -o $@ $^ $(SO_LIBRARY): $(OBJS) $(CXX) $(LDFLAGS) -shared -o $@ $^ %.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ clean: rm -rf `find Source -name '*.o'` ziplib.tar.gz Bin/*.zip Bin/out* $(EXECUTABLE) $(SO_LIBRARY) tarball: tar -zcvf ziplib.tar.gz * 类的Field f,我想检索相关的getter / setter(如果存在)。我该怎么做?

  • 我检查了MyClass的方法,但什至没有一个返回Field的方法。
  • 我在玩Method检索到的BeanInfo。它有一个方法Introspector.getBeanInfo(Class<?> beanClass),它返回一个getPropertyDescriptors()的数组,并且每个PropertyDescriptor都可以通过PropertyDescriptorgetReadMethod()来检索吸气剂和设置剂。但是似乎与getWriteMethod()没有任何联系。另外,似乎无法获得某个Field(例如,通过将字段名作为参数来检索);因此,即使有一种方法可以从PropertyDescriptor获取Field,我也需要遍历所有PropertyDescriptor。这不是性能。

注意:我不想依靠命名约定,所以请不要给那些摆弄字段名称的答案。毕竟,字段PropertyDescriptors中没有名称myFieldgetMyField的吸气剂仍然是吸气剂。

2 个答案:

答案 0 :(得分:0)

这是我的想法,虽然并不完全正确。 检查方法名称中是否包含字段名称,以及返回类型和参数参数类型。我觉得如果没有关于setter / getter方法的规则。几乎是不可能的。

    @Test
    void test_fieldGetterSetter() throws NoSuchFieldException {
    Field f = MyClass.class.getDeclaredField("name");
    Class<?> declaringClass = f.getDeclaringClass();

    Method[] declaredMethods = declaringClass.getDeclaredMethods();

    for (Method declaredMethod : declaredMethods) {
        String name = declaredMethod.getName();

        // Can also check return type, argument type to increase the correctness
        if (isFieldNameWithMethodName(f.getName(), name)) {
            String format = String.format("Field name is %s and possible method name is %s", f.getName(), name);
            System.out.println(format);
        }
    }
}

private boolean isFieldNameWithMethodName(String fieldName, String methodName) {
    if (methodName.toLowerCase().contains(fieldName.toLowerCase())) {
        return true;
    }

    return false;
}

答案 1 :(得分:-1)

事实证明,在Java中,getter / setter不仅由它们的签名和行为(如我所认为的)定义,而且还通过遵循命名约定来定义。

因此,为了获取对象Field的{​​{1}} myField的getter / setter,我们需要创建其对应的getter / setter方法名称myObject(使用methodName,然后拨弄Field.getName() / get和camelCase),然后致电set。可以使用myObject.getClass().getMethod(methodName, ...)来检索参数(...),并且根据我想要的是getter还是setter,参数必须不同。

证明命名很重要: 对于这个班

Field.getType()

我运行了代码

public class ClassWithUnconventionalNaming {

    private int foo;
    public int myGetter() { return foo; }
    public void mySetter(int x) { this.foo = x; }
    public void setBaz(boolean x) { this.foo = 2; };

    private String bar;
    public String getBar() { return "hello world"; }
    public void setBar(String bar) { this.bar = bar; }

    private boolean baz;
    public boolean isBaz() { return baz; }
}

得到输出

ClassWithUnconventionalNaming myClass = new ClassWithUnconventionalNaming();
myClass.mySetter(5);

BeanInfo info = Introspector.getBeanInfo(ClassWithUnconventionalNaming.class);
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
    String propertyName = pd.getName();
    System.out.println("property name: " + propertyName);
    Method getter = pd.getReadMethod();
    System.out.println("    getter: " + ((getter == null) ? "" : getter.getName()));
    Method setter = pd.getWriteMethod();
    System.out.println("    setter: " + ((setter == null) ? "" : setter.getName()));
}