views:

59

answers:

2

I'm using the JDO Query class and I need to conditionally pass certain parameters to the execute method, as demonstrated in the code below.

I don't know how to do this in Java.

query.declareParameters("String alphaP");
query.declareParameters("String bravoP");
query.declareParameters("String charlieP");

if (condition == true)
{
    if (othercondition == true)
    {
        query.declareParameters("List<String> stringList");
    }
    else
    {
        query.declareParameters("String simpleString");
    }
}

if (someothercondition == true)
{
    query.declareParameters("int deltaP");
}

if (yetanothercondition == true)
{
    query.declareParameters("int echoP");
}

if (thelastcondition == true)
{
    query.declareParameters("int foxtrotP");
}

List<ResultClass> results = (List<ResultClass>) query.execute(
    alphaP, 
    bravoP, 
    charlieP,

    ... whatever other parameters are required based on which conditions are true above

    );
+2  A: 

I would suggest using the executeWithArray method: dynamically build up the array of parameters using an instance of java.util.ArrayList which you can then convert to an array using the toArray method. The code might look something like the following:

ArrayList<Object> args = new ArrayList<Object>();
args.add(alphaP);
args.add(bravoP);
args.add(charlieP);
// Add other arguments here...

List<ResultClass> results = (List<ResultClass>) query.executeWithArray(args.toArray());
Richard Cook
+1 if everybody checked API before asking questions, we'd have no reputation here. Also, executeWithMap might be a bit simpler.
Nikita Rybak
+1  A: 

How to conditionally pass parameters in Java to a method that takes a variable number of arguments?

@Richard has answered the specific question with regards to the JDO Query class. (Use one of the alternative queryWith... methods.)

The answer to the more general question is that "it depends". Specifically, it depends on the method signatures.

1) If the method is declared to take a variable number of parameters passed as an array, list, map or whatever, then the answer is obvious. Assemble the actual parameters in an array / list / map / whatever, and pass them.

2) If the method is declared with a "varargs" parameter, then you can pass an explicit array of actual parameters; e.g.

  public void test(String... args) { ... }

  test("Hi", "Mom");
  test(new String[]{"Hi", "Pa"});
  String[] args = new String[]{"Hi", "Bro"};
  test(args);

3) If there are actually multiple overloaded methods, then you have no choice but to programmaticaly select and call the appropriate overload based on the number of parameters you have to pass:

  public void test(String arg1) { ... }
  public void test(String arg1, String arg2) { ... }
  ...

  if (nosArgs == 1) {
      test(arg1);
  } else if (nosArgs == 2) {
      test(arg1, arg2);
  } else ...

You might think that reflection would help, because when you call a method reflectively you pass the actual arguments as an Object[]. But this doesn't help much because you also need to use the appropriate Method object, and each of the overloads of (say) the test method has a different Method object. So you end up with conditional / switch code that is equivalent to the non-reflective case.

Stephen C