从 Method.invoke 传递的变量不会显示在 System.out.println 中

Variable passed from Method.invoke doesn't show up in anything but System.out.println

我想做的是在我正在制作的游戏的输入框中创建一个显示在屏幕上的消息,例如

"Name: (input would appear here)"

我所做的是传入消息,我希望我的输入转到哪个对象,以及哪个函数将使用该变量(例如将输入设置为玩家姓名的函数)。现在,我可以只从 InputBox 对象访问输入变量,但是,在长 运行 中,这会更有效。我正在使用 Method.invoke 将函数传递到我想要的对象中,并将输入字符串作为参数。这是我的代码:

public class InputBox extends Textbox {

    public String input = "";
    private String out;
    private Object obj;

    private int lastLastKey = 0;

    /** 
     * 
     * @param message
     * @param cl The object/class where the output variable is.
     * @param out The method to run. Only takes the input variable, so use this format: void toRun(String input)
     */
    public InputBox(String message, Object obj, String out) {
        super(message);
        this.out = out;
        this.obj = obj;
    }

    public void tick(Game game){                
        if (game.input.lastKey != 0 && !game.input.keys[KeyEvent.VK_ENTER]
                && !game.input.keys[KeyEvent.VK_SPACE] && !game.input.keys[KeyEvent.VK_SHIFT] && !game.input.keys[KeyEvent.VK_BACK_SLASH]){
            if(game.input.lastKey != lastLastKey) input+=Character.toUpperCase((char) game.input.lastKey);
        }else if(game.input.keys[KeyEvent.VK_ENTER] && !input.isEmpty() && !cleared){
            Method method = null;
            try {
                method = obj.getClass().getMethod(out, new Class[]{ String.class, Object.class });
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }

            try {
                method.invoke(obj, new Object[]{ input, obj });
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            cleared = true;
        }

        lastLastKey = game.input.lastKey;
    }

    public void render(Graphics g){
        if(!cleared){
            g.setColor(Color.white);
            g.fillRect(10, Display.height-110, Display.width-20, 100);

            g.setColor(Color.black);
            g.drawRect(10, Display.height-110, Display.width-20, 100);

            g.setFont(Game.smallFont);
            FontMetrics fm = g.getFontMetrics();
            g.drawString(message+" "+input, Display.width/2-fm.stringWidth(message+" "+input)/2, Display.height-50);
        }
    }

}

您对构造函数的描述表明预期方法的签名为

void toRun(String input) {}

但是您的反射代码寻找具有签名的方法

void toRun(String input, Object o) {}

如果您使用的是 Java 8,您可以使用 Consumer 并删除所有反射代码:

public class InputBox extends Textbox {

    private Consumer<String> out;

    public InputBox(String message, Consumer<String> out) {
        this.out = out;
        ...
    }

    public void tick(Game game){
        ...
        out.apply(input);
        ...
    }
}

假设您的 Player class 有这样的方法 setName(String)

public class Player {
    public void setName(String name) {
    }
}

您可以使用方法参考创建一个InputBox

public InputBox createNameInputBox(Player p) {
    return new InputBox("Name: ", p::setName);
}

或使用 lambda 表达式

public InputBox createAlternateNameInputBox(Player p) {
    return new InputBox("Name: ", name -> p.setName(name));
}

要阅读有关 lambda 表达式和方法参考的更多信息,请参阅 Java 教程系列(https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html). For a discussion of whether you should use method references or lambda expressions see