从另一种方法动态初始化POJO

Initialize a POJO dynamically from another method

Let's say I have these set of POJO class that implement an interface but there are no common attributes here.

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;
    }
}

And in conjunction with these POJO classes I have a couple of methods which I can use to retrieve the type of POJO being returned based on another value and the actual POJO with values.

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;
        }
    }
}

Is there a way using which I can read the concrete POJO safely in my code and use the getters/setters? I have gone through quite a few questions which provide answers based on Reflection but that isn't working for me. The getters/setters aren't visible and when I call .getClass() on the returned Object I see it is the MainIfc interface.

The design problem I am trying to solve pertains to a REST API automation framework that I am trying to design. Basically I have a ClientResponse parser which will send back the POJO I am looking for. But I don't want the folks writing the test cases to worry about the type of POJO that is returned. So I was thinking I could return the type and the instantiated POJO so I get the values but I am troubled over how to achieve this dynamically.

It sounds to me like you're trying to do something rather illogical. Strategy Pattern or Abstract Factory might be a good fit for your requirement, but at the moment I don't quite understand what exactly it is you're trying to achieve. You should definitely not be conditionally casting and calling different methods on these classes. If you really want to continue on this path, I would suggest going with reflection, if not an option, and you need the flexibility, I'd probably go with a Map of some kind.

But I would definitely rethink your design if at all possible.

Try this piece of code, I don't know if I fully understand your requirement but based on my understanding I think below code would do the trick.

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);
    }

    }
}

}

A little explanation about above code : Get all the fileds of the object and check if is a private property, if yes then it must have a public getter and setter, guess their name based on java convention, call the getter, get the value, check if it is a instance of String class, if yes make it UPPERCASE then call setter to set new value.

Do consumers of MainIfc actually need the POJOs, or just the data inside of them?

It might be cleaner design if MainIfc declares a method or two that exposes the data that its consumers will need. Your POJOs can then implement the methods that the MainIfc interface declares. Or you can build a wrapper class for each POJO that conforms it to the interface, if you want to keep the concerns of implementing your interface separate from your POJOs.

Ideally an interface should expose a few methods that can be used to interact with any class which implements it and no one should need to know about the underlying POJOs/implementation.

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
  }
}

Try this code. Maybe this will return all the methods in class as well as methods inherited from Object class.

   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());
        }
    }
I updated my question for the exact requirement and design problem I am facing. Please advise.