title: Java reflection invoke method with varargs
body: <p>I am having an issue with reflection to calculate how many arguments the user passed and compare the length of arguments to the expected count. If this requirement is met then proceed to execute the method with an <code>Object[] { incommingArguments }</code> (varargs) argument to the method invoker.</p>
  
  <p>I have a method called <code>compute()</code> in my <code>LogicGates</code> class. The method takes 2 to 3 arguments. The first argument is the gate and the next 1 or 2 are the inputs depending on the inputs that the gate takes.</p>
  
  <p>Currently, the method with the signature:</p>
  
  <pre><code>compute(gate:GATE,a:boolean,b:boolean):boolean
  </code></pre>
  
  <p>executes correctly, but if I use the</p>
  
  <pre><code>compute(gate:GATE,&lt;VARARGS&gt;:boolean):boolean
  </code></pre>
  
  <p>signature then my code breaks. I am using the logic for varargs that I found here: <a href="https://stackoverflow.com/a/15951895/1762224">StackOverflow: Invoke method with an array parameter using reflection</a>.</p>
  
  <p>Both methods can be found at the bottom of LogicGates.java at the end of my question.</p>
  
  <p><strong>Output</strong></p>
  
  <pre><code> A | B | AND     A | B | OR     A | B | NAND     A | B | NOR     A | B | XOR     A | B | XNOR     A | B | XNOR_NAND     A | B | XNOR_NOR     A | B | IF_THEN     A | B | THEN_IF    
  ---+---+-----   ---+---+----   ---+---+------   ---+---+-----   ---+---+-----   ---+---+------   ---+---+-----------   ---+---+----------   ---+---+---------   ---+---+---------   
   T | T | T       T | T | T      T | T | F        T | T | F       T | T | F       T | T | T        T | T | T             T | T | T            T | T | T           T | T | T          
   T | F | F       T | F | T      T | F | T        T | F | F       T | F | T       T | F | F        T | F | F             T | F | F            T | F | F           T | F | T          
   F | T | F       F | T | T      F | T | T        F | T | F       F | T | T       F | T | F        F | T | F             F | T | F            F | T | T           F | T | F          
   F | F | F       F | F | F      F | F | T        F | F | T       F | F | F       F | F | T        F | F | T             F | F | T            F | F | T           F | F | T          
  </code></pre>
  
  <p><strong>GateTest.java</strong></p>
  
  <pre><code>public class GateTest {
      public static void main(String[] args) {
          StringBuffer[] rows = newStringBufferArray(6, "");
  
          for (LogicGates.GATE g : LogicGates.GATE.values()) {
              if (g.operands == 2)
                  rows = fillTable(g, rows, repeat(' ', 3));
          }
  
          for (StringBuffer row : rows) {
              System.out.println(row);
          }
      }
  
      private static final StringBuffer[] fillTable(final LogicGates.GATE gate,
              StringBuffer[] buffer, String delimiter) {
          int l = buffer.length - 1;
          String name = gate.name();
          String pad = repeat('-', name.length() + 1);
  
          buffer[0].append(String.format(" A | B | %s %s", name, delimiter));
          buffer[1].append(String.format("---+---+-%s%s", pad, delimiter));
  
          for (byte b = 3; b &gt;= 0; --b)
              buffer[l - b].append(fillRow(gate, intToBool(b &gt;&gt; 1),
                      intToBool(b &amp; 1), delimiter));
  
          return buffer;
      }
  
      private static final String fillRow(final LogicGates.GATE gate, boolean a,
              boolean b, String delimiter) {
          return String.format(" %c | %c | %c%s %s", boolToChar(a),
                  boolToChar(b),
                  boolToChar(LogicGates.compute(gate, a, b)),
                  repeat(' ', gate.name().length() - 1), delimiter);
      }
  
      public static final StringBuffer[] newStringBufferArray(int size,
              String initialValue) {
          if (initialValue == null)
              initialValue = "";
  
          StringBuffer[] bufferArr = new StringBuffer[size];
  
          for (int i = 0; i &lt; size; i++)
              bufferArr[i] = new StringBuffer(initialValue);
  
          return bufferArr;
      }
  
      private static final String repeat(char ch, int count) {
          StringBuilder sb = new StringBuilder();
  
          while (sb.length() &lt; count)
              sb.append(ch);
  
          return sb.toString();
      }
  
      private static final char boolToChar(final boolean bool) {
          return bool ? 'T' : 'F';
      }
  
      private static final boolean intToBool(final int input) {
          return intToBool((byte) input);
      }
  
      private static final boolean intToBool(final byte input) {
          if (input &lt; 0 || input &gt; 1)
              throw new IllegalArgumentException("Input must be 0 or 1");
  
          return input == 1;
      }
  }
  </code></pre>
  
  <p><strong>LogicGates.java</strong></p>
  
  <pre><code>import java.lang.reflect.Method;
  import java.util.Arrays;
  
  @SuppressWarnings("unused")
  public final class LogicGates {
      public static enum GATE {
          NOT("not", "Negation", 1), // .
          AND("and", "Logical conjunction", 2), // .
          OR("or", "Logical disjunction", 2), // .
          NAND("nand", "Logical NAND", 2), // .
          NOR("nor", "Logical NOR", 2), // .
          XOR("xor", "Exclusive disjunction", 2), // .
          XNOR("xnor", "Logical biconditional", 2), // .
          XNOR_NAND("xnorNand", "XNOR using only NAND gates.", 2), // .
          XNOR_NOR("xnorNor", "XNOR using only NOR gates.", 2), // .
          IF_THEN("ifThen", "Material implication.", 2), // .
          THEN_IF("thenIf", "Converse implication.", 2); // .
  
          private String methodName, description;
          int operands;
  
          private GATE(String methodName, String description, int operands) {
              this.methodName = methodName;
              this.description = description;
              this.operands = operands;
          }
  
          protected String methodName() {
              return methodName;
          }
  
          protected int operands() {
              return operands;
          }
      }
  
      private LogicGates() {
          throw new AssertionError();
      }
  
      private static final boolean not(boolean a) {
          return !a;
      }
  
      private static final boolean and(final boolean a, final boolean b) {
          return a &amp;&amp; b;
      }
  
      private static final boolean or(final boolean a, final boolean b) {
          return a || b;
      }
  
      private static final boolean nand(final boolean a, final boolean b) {
          return not(and(a, b));
      }
  
      private static final boolean nor(final boolean a, final boolean b) {
          return not(or(a, b));
      }
  
      private static final boolean xor(final boolean a, final boolean b) {
          return or(and(a, not(b)), and(not(a), b));
      }
  
      private static final boolean xnor(final boolean a, final boolean b) {
          return or(and(a, b), nor(a, b));
      }
  
      private static final boolean xnorNand(final boolean a, final boolean b) {
          return nand(nand(nand(a, nand(a, b)), nand(b, nand(a, b))),
                  nand(nand(a, nand(a, b)), nand(b, nand(a, b))));
      }
  
      private static final boolean xnorNor(final boolean a, final boolean b) {
          return nor(nor(a, nor(a, b)), nor(b, nor(a, b)));
      }
  
      private static final boolean ifThen(final boolean a, final boolean b) {
          return or(and(a, b), not(a));
      }
  
      private static final boolean thenIf(final boolean a, final boolean b) {
          return or(a, nor(a, b));
      }
  
      public static final boolean compute(GATE gate, boolean... values) {
          boolean result = false;
  
          if (values.length != gate.operands())
              throw new IllegalArgumentException(String.format(
                      "%s gate requires %d inputs.", gate.name(), gate.operands));
  
          try {
              Class&lt;?&gt; c = Class.forName(LogicGates.class.getName());
              Method method = null;
  
              if (gate.operands() == 2)
                  method = c.getDeclaredMethod(gate.methodName(), boolean.class,
                          boolean.class);
              else if (gate.operands() == 1) {
                  method = c.getDeclaredMethod(gate.methodName(), boolean.class);
              } else {
                  method = null;
              }
  
              boolean[] args = Arrays.copyOfRange(values, 0, values.length);
              result = (boolean) method.invoke(c, new Object[] { args });
          } catch (Exception e) {
              System.out.println(e.getMessage() + " " + e.getCause());
          }
  
          return result;
      }
  
      public static final boolean compute(GATE gate, boolean a, boolean b) {
          boolean result = false;
  
          try {
              Class&lt;?&gt; c = Class.forName(LogicGates.class.getName());
              Method method = null;
  
              if (gate.operands() == 2)
                  method = c.getDeclaredMethod(gate.methodName(), boolean.class,
                          boolean.class);
              else if (gate.operands() == 1) {
                  method = c.getDeclaredMethod(gate.methodName(), boolean.class);
              } else {
                  method = null;
              }
  
              result = (boolean) method.invoke(c, a, b);
          } catch (Exception e) {
              System.out.println(e.getMessage() + " " + e.getCause());
          }
  
          return result;
      }
  }
  </code></pre>