【问题标题】:How to access an object's fields/methods by their name as a string如何通过名称作为字符串访问对象的字段/方法
【发布时间】:2016-06-15 17:01:39
【问题描述】:

假设我有一堂课

class A {
   string name;
   int age;
   string gender;
   //assuming all the constructors, getters and setters are present
}

为了简单起见,假设所有这些成员都是公共的,为了访问它们,我创建了一个该类的对象,如下所示

A a = new A();

有没有办法访问每个成员如下

String string = "age"

a.string

并获取对象的年龄等。 同样,假设我有一个 getter,我可以使用它访问它吗

String string = "getAge()";
a.string;

我是一名初学者 java 程序员,试图优化用 swift 编写的代码(不用说我是 swift 的新手),它有一个包含 50 多个成员的类,并在其他模块中设置/获取它们中的每一个很乏味。

只是想知道这是否可以在任何一种编程语言中实现。在 java 中,我假设使用类反射可能会发生这样的事情,但不是很确定。

【问题讨论】:

  • 是的,您必须使用反射,但一般来说,这也是一种明显的代码异味。
  • 一定要改变 java 约定,并期望将私有变量假定为公共变量。我建议在示例中声明 public。
  • 说到代码味道:“一个有 50 多个成员的类”。
  • Reflections 具有在运行时检查类的 API,包括访问类字段及其方法。此外,您可以根据需要调用这些方法或填充字段。
  • @AndyTurner 该类是具有 50 多个属性的数据库表之一的映射器类,我正在使用 swift 中的字典对其进行填充。

标签: java swift


【解决方案1】:

正如here 解释的(带有示例),您可以使用java 反射来检查类是否包含字段并获取该字段的值。

此外,将字段公开并不是一个好主意,它们应该是私有的并且只能通过 getter 和 setter 访问。

【讨论】:

  • ...除非您的成员是最终成员。特别是如果你有最终的静态成员。
  • @Huxley 使用访问器是个好主意,即使您的成员是最终成员。请参阅 Effective Java 第 2 版第 14 条“在公共类中,使用访问器方法,而不是公共字段”。它允许您在不更改接口的情况下更改实现;覆盖访问者;同步访问等
【解决方案2】:

好吧,你可以使用reflection,然后执行以下操作:

A a = new A();
Class cls = a.getClass();

//read a method value
String methodName = "getAge";
Method method = cls.getDeclaredMethod(methodName);
int methodReturnedResult = method.invoke(a, null);

//read a field value
String fieldName = "age";
Field field = cls.getDeclaredField(fieldName);
int fieldValue = field.get(a);

This is another example
Java Reflection tutorial

虽然重要的是要注意反射并不适用于这些情况,并且它不是被认为是在这些情况下使用反射的好设计。您需要做的是使用 IDE 的功能自动为您生成 setter 和 getter。
您使用哪个 IDE?大多数 Java IDE 都能够根据类字段自动生成 getter 和 setter。

这就是您在EclipseNetbeansIntellijAndroid Studio 中的操作方式。

【讨论】:

  • 我使用 Eclipse。我真正想问的是了解如何动态/以编程方式调用 getter/setter。类似于我示例的最后一部分。
  • @HardikShah 看我的例子,它完全证明了:)
【解决方案3】:

如果你必须使用通货再膨胀,下面应该可以工作。

A类

class A {
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

类中的实用方法

public Object get(String methodName, A a) throws Exception {
    Object ret = null;
    if(a != null){
        Class<A> cl = A.class;
        Method method = cl.getDeclaredMethod(methodName);
        ret = method.invoke(a);
    }
    return ret;
}

public void set(String methodName, Object value, A a) throws Exception{
    Class<A> cl = A.class;
    Method method = cl.getDeclaredMethod(methodName, value.getClass());
    method.invoke(a, value);

}

测试一下

public void testIt() throws Exception{
    A a = new A();
    set("setName", "xyz", a);
    String name = (String) get("getName",a);
    System.out.println(name);
}

注意:注意盒装类型,即 int 表示为 Integer。以及大量的空检查。

【讨论】:

    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    相关资源
    最近更新 更多