【问题标题】:Initialize a POJO dynamically from another method从另一个方法动态初始化 POJO
【发布时间】:2017-01-02 23:23:25
【问题描述】:

假设我有这些实现接口的 POJO 类,但这里没有公共属性。

public interface MainIfc {}

class Ifc1 implements MainIfc {
    private String a1;
    public String getA1() {
        return a1;
    }
    public void setA1(String a1) {
        this.a1 = a1;
    }
}

class Ifc2 implements MainIfc {
    private String x1;
    private String x2;
    public String getX1() {
        return x1;
    }
    public void setX1(String x1) {
        this.x1 = x1;
    }
    public String getX2() {
        return x2;
    }
    public void setX2(String x2) {
        this.x2 = x2;
    }
}

结合这些 POJO 类,我有几个方法可以用来检索基于另一个值返回的 POJO 的类型以及带有值的实际 POJO。

public class GetIfc {
    public Class getIfcType(int code) {
        if (code==1)
            return Ifc1.class;
        else
            return Ifc2.class;
    }
    public MainIfc getIfc(int code) {
        if (code==1) {
            Ifc1 thisIfc = new Ifc1();
            thisIfc.setA1("Ifc1");
            return thisIfc;
        } else {
            Ifc2 thisIfc = new Ifc2();
            thisIfc.setX1("Ifc2");
            thisIfc.setX2("Ifc2");
            return thisIfc;
        }
    }
}

有没有一种方法可以让我在我的代码中安全地读取具体的 POJO 并使用 getter/setter?我已经经历了很多问题,这些问题提供了基于反射的答案,但这对我不起作用。 getter/setter 不可见,当我在返回的对象上调用 .getClass() 时,我看到它是 MainIfc 接口。

我尝试解决的设计问题与我尝试设计的 REST API 自动化框架有关。基本上我有一个ClientResponse 解析器,它将发回我正在寻找的 POJO。但我不希望编写测试用例的人担心返回的 POJO 类型。所以我想我可以返回类型和实例化的 POJO,这样我就可以得到这些值,但我对如何动态实现这一点感到困扰。

【问题讨论】:

  • 我不清楚您要做什么。我感觉到了对某些类似 Bean 的行为的渴望,但我可能弄错了。
  • "当我在返回的对象上调用 .getClass() 时,我看到它是 MainIfc 接口。"我觉得很难相信。请添加一些显示此行为的代码。另请澄清:您是否正在寻找使其工作的任何方法,或者您对解决此问题的正确 OO 方法感兴趣?
  • 您可以向您的类添加一个方法,该方法将所有(公共)字段作为Field 对象的列表返回。可能是 MainIfc 的成员。但是,我觉得这是一个 X-Y-问题。您要解决的问题是什么?
  • 我尝试了这里提到的答案 - stackoverflow.com/questions/8479943/…。我已经用我要解决的确切设计问题更新了我的问题。
  • 您能举例说明您希望如何使用它吗?

标签: java design-patterns reflection type-conversion dynamictype


【解决方案1】:

试试这个代码。也许这将返回类中的所有方法以及从Object 类继承的方法。

   public static void main(String[] args) throws ClassNotFoundException {
        GetIfc getIfc=new GetIfc();
        MainIfc clas1s=getIfc.getIfc(1);
        Class class1= clas1s.getClass();
        System.out.println(class1);
        Method[] mem= class1.getMethods();
        for(Method mmm : mem) {
            System.out.println(mmm.getName());
        }
    }

【讨论】:

  • 我针对我面临的确切要求和设计问题更新了我的问题。请指教。
【解决方案2】:

MainIfc 的消费者真的需要 POJO,还是只需要其中的数据?

如果 MainIfc 声明一个或两个方法来公开其使用者需要的数据,则可能是更简洁的设计。然后,您的 POJO 可以实现 MainIfc 接口声明的方法。或者,您可以为每个符合接口的 POJO 构建一个包装类,如果您希望将实现接口的关注点与 POJO 分开。

理想情况下,接口应该公开一些可用于与任何实现它的类进行交互的方法,并且没有人需要了解底层 POJO/实现。

public interface MainIfc {
  public Hash getAttributes();
  public setAttributes(Hash attributes);
}

class Ifc1 implements MainIfc {
  private String a1;
  public String getA1() {
    return a1;
  }
  public void setA1(String a1) {
    this.a1 = a1;
  }
  public Hash getAttributes() {
    // return a hash with data that MainIfc consumer will need from this POJO
  }
  public setAttributes(Hash attributes) {
    // copy hash attributes to corresponding POJO fields
  }
}

class Ifc2 implements MainIfc {
  private String x1;
  private String x2;
  public String getX1() {
    return x1;
  }
  public void setX1(String x1) {
    this.x1 = x1;
  }
  public String getX2() {
    return x2;
  }
  public void setX2(String x2) {
    this.x2 = x2;
  }
  public Hash getAttributes() {
    // return a hash with data that MainIfc consumer will need from this POJO
  }
  public setAttributes(Hash attributes) {
    // copy hash attributes to corresponding POJO fields
  }
}

【讨论】:

    【解决方案3】:

    在我看来,您正在尝试做一些不合逻辑的事情。策略模式或抽象工厂可能非常适合您的要求,但目前我不太明白您想要实现的究竟是什么。您绝对不应该在这些类上有条件地强制转换和调用不同的方法。如果您真的想继续走这条路,我建议您进行反思,如果不是一种选择,并且您需要灵活性,我可能会选择某种地图。

    但如果可能的话,我肯定会重新考虑你的设计。

    【讨论】:

      【解决方案4】:

      试试这段代码,我不知道我是否完全理解您的要求,但根据我的理解,我认为下面的代码可以解决问题。

      public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
          IllegalArgumentException, InvocationTargetException {
      GetIfc getIfc = new GetIfc();
      MainIfc clas1s = getIfc.getIfc(1);
      Field[] fields = clas1s.getClass().getDeclaredFields();
      for (int i = 0; i < fields.length; i++) {
          Field field = fields[i];
          Class fieldClasslasse = field.getType();
      
          if (field.getModifiers() == Modifier.PRIVATE) {
      
          // you need to check fieldClass, if it is boolean then initials of the getter could be 'is' instead of 'get'
          String methodNameGet = "get" + Character.toUpperCase(field.getName().charAt(0))
              + field.getName().substring(1);
          String methodNameSet = "set" + Character.toUpperCase(field.getName().charAt(0))
              + field.getName().substring(1);
      
          Method methodGet = clas1s.getClass().getDeclaredMethod(methodNameGet, null);
          Object value =  methodGet.invoke(clas1s, null);
          if (value != null && value instanceof String) {
              String valueUpper = ((String)value).toUpperCase();
      
              Class[] cArg = new Class[1];
              cArg[0] = String.class;
              Method methodSet = clas1s.getClass().getDeclaredMethod(methodNameSet, cArg);
              Object[] var = new Object[1];
              var[0] = valueUpper;
              methodSet.invoke((Object) clas1s, var);
          }
      
          }
      }
      
      }
      

      关于上面代码的一点解释:获取对象的所有文件并检查是否是私有属性,如果是则它必须有一个公共的getter和setter,根据java约定猜测它们的名字,调用getter,得到该值,检查它是否是 String 类的实例,如果是,则将其设为大写,然后调用 setter 设置新值。

      【讨论】:

        猜你喜欢
        • 2013-12-28
        • 2012-04-10
        • 1970-01-01
        • 1970-01-01
        • 2021-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多