我遇到反射问题,要计算用户传递的参数数量,并将参数长度与预期计数进行比较。如果满足此要求,则继续使用方法调用者的Object[] { incommingArguments }
(varargs)参数执行该方法。
我的compute()
课程中有一个名为LogicGates
的方法。该方法需要2到3个参数。第一个参数是门,接下来的1或2是输入,具体取决于门的输入。
目前,该方法带有签名:
compute(gate:GATE,a:boolean,b:boolean):boolean
正确执行,但如果我使用
compute(gate:GATE,<VARARGS>:boolean):boolean
签名然后我的代码中断了。我正在使用我在这里找到的varargs逻辑:StackOverflow: Invoke method with an array parameter using reflection。
在我的问题的最后,两个方法都可以在LogicGates.java的底部找到。
输出
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
GateTest.java
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 >= 0; --b)
buffer[l - b].append(fillRow(gate, intToBool(b >> 1),
intToBool(b & 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 < 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() < 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 < 0 || input > 1)
throw new IllegalArgumentException("Input must be 0 or 1");
return input == 1;
}
}
LogicGates.java
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 && 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<?> 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<?> 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;
}
}
答案 0 :(得分:0)
在Java 7中,使用invokeWithArguments方法。
编辑:当然,这意味着使用Java 7 MethodHandle
类代替旧的Java 1.1 Method
类。
答案 1 :(得分:0)
好吧,在我坐下来思考一下之后,我想出了一个解决方案:
<强>输出强>
>> Invoking SimpleGate.not(false)
>> Invoking SimpleGate.and(true,true)
>> Invoking SimpleGate.or(true,false)
>> Invoking SimpleGate$AdvancedGate.xor(true,false)
PASS
<强> ReflectTest.java 强>
public class ReflectTest {
private enum Gate {
NOT(SimpleGate.class),
AND(SimpleGate.class),
OR(SimpleGate.class),
XOR(SimpleGate.AdvancedGate.class);
private Class<?> clazz;
private Gate(Class<?> clazz) { this.clazz = clazz; }
public Class<?> clazz() { return clazz; }
}
public static boolean compute(Gate gate, Boolean... input) {
return (Boolean) Reflect.call(gate.clazz(),
gate.name().toLowerCase(), (Object[]) input);
}
public static void main(String[] args) {
Boolean not = compute(Gate.NOT, false);
Boolean and = compute(Gate.AND, true, true);
Boolean or = compute(Gate.OR, true, false);
Boolean xor = compute(Gate.XOR, true, false);
if (not && and && or && xor)
System.out.println("PASS");
else
System.out.println("FAIL");
}
}
<强> Reflect.java 强>
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public abstract class Reflect {
public static final Object call(Class<?> clazz, String methodName, Object... varArgs) {
try {
Object invokee = null;
String className = clazz.getName();
int argc = varArgs.length;
Class<?>[] classList = new Class[argc];
StringBuffer varArgsStr = new StringBuffer();
for (int i = 0; i < argc; i++) {
Object argv = varArgs[i];
classList[i] = argv.getClass();
varArgsStr.append(argv.toString());
if (i < argc - 1) varArgsStr.append(',');
}
System.out.printf(">> Invoking %s.%s(%s)\n", className,methodName, varArgsStr);
Class<?> target = Class.forName(className);
Method method = target.getDeclaredMethod(methodName, classList);
int childIndex = className.indexOf('$');
if (childIndex > -1) {
String wrappingClassName = className.substring(0, childIndex);
Class<?> wrapper = Class.forName(wrappingClassName);
Object wrapperInstance = wrapper.newInstance();
Constructor<?> con = target.getDeclaredConstructor(wrapper);
invokee = con.newInstance(wrapperInstance);
} else {
boolean isStatic = Modifier.isStatic(method.getModifiers());
invokee = isStatic ? target : target.newInstance();
}
return method.invoke(invokee, varArgs);
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
}
SimpleGate.java&amp; SimpleGate $ AdvancedGate.java 强>
public class SimpleGate {
public Boolean not(Boolean a) { return !a; }
public static Boolean and(Boolean a, Boolean b) { return a && b; }
public static Boolean or(Boolean a, Boolean b) { return a || b; }
public class AdvancedGate {
public Boolean xor(Boolean a, Boolean b) {
return or(and(not(a),b),and(a,not(b)));
}
}
}