如何在运行时更改ATM类(Java反射)

时间:2016-04-29 06:19:09

标签: java reflection

有一个ATM GUI .class。

在ATM类中,如果用户单击滑动,它将使用Java反射动态调用我的Card.class。

在ATM类中有这个变量:

int userBalanceField = 100;

我正在尝试将其动态更改为Integer.MAX_VALUE。

以下是ATM中的滑动功能:

    Object object;
    Class class_ = null;
    ClassLoader classLoader;
    this.printToScreen("Loading Card");
    String string = "." + File.separator + "Card.class";
    File file = new File(string);
    ClassLoader classLoader2 = classLoader = ClassLoader.getSystemClassLoader();
    try {
        object = new URL("file:" + System.getProperty("user.dir") + File.separator + "Card.class");
        class_ = Card.class;

    }
    catch (MalformedURLException var6_7) {
        var6_7.printStackTrace();
    }
    object = "Card";

    this.printToScreen("Reading card data and verifying ATM");
    try {
        Method method = class_.getMethod("swipe", ATM.class);
        Data data = (Data)method.invoke(null, this);
        if (data == null) {
            this.printToScreen("Machine considered invalid");
        } else {
            this.user = data;
            this.tempEntry = "";
            this.screenState = 2;
            this.updateScreen();
        }
    }
    catch (SecurityException var8_11) {
        this.printToScreen("Security Exception when swiping card.");
    }
    catch (NoSuchMethodException var8_12) {
        this.printToScreen("No Such method exception when swiping card.");
    }
    catch (IllegalArgumentException var8_13) {
        this.printToScreen("Illegal Argument exception when swiping card.");
    }
    catch (IllegalAccessException var8_14) {
        this.printToScreen("Illegal Access exception when swiping card.");
    }
    catch (InvocationTargetException var8_15) {
        this.printToScreen("Invocation Target exception when swiping card.");
    }

这是我的尝试。

    public static ATM.Data swipe(ATM anATM){ 

    Class atmClass = anATM.getClass();
    try {
        Field moneyInMachineField = atmClass.getDeclaredField("moneyInMachine");
        System.out.println("Loading field..." + moneyInMachineField.getName());

        Field userBalanceField = atmClass.getDeclaredField("userBalance");
        userBalanceField.setAccessible(true);


        ATM.Data result = new ATM.Data(cardNumber, accountNumber, name, pinNumber);
        userBalanceField.set(result, Integer.MAX_VALUE);

        return result;
    } catch (IllegalAccessException 
            | NoSuchFieldException 
            | SecurityException e) {
        e.printStackTrace();
    }
    return null;
}

刷卡时我一直收到“调用目标异常。”

3 个答案:

答案 0 :(得分:3)

您使用的语法是创建新的非静态内部类。 DataATM的静态内部类,因此您需要执行以下操作:

ATM.Data result = new ATM.Data(cardNumber, accountNumber, name, pinNumber);

根据Java Docs

  

例如,要为静态嵌套类创建对象,请使用此方法   语法:

     

OuterClass.StaticNestedClass nestedObject =        new OuterClass.StaticNestedClass();

如果Data是非静态的,它将包含对ATM的特定引用(这将使其能够响应AMT.this.userBalance),但它仅用作POJO。

除上述内容外,您还错误地设置了字段。在调用field.set()时,您需要为其提供包含该字段的对象以及您要将其设置为的值。

在你的情况下,它将是:

userBalanceField.set(anATM, Integer.MAX_VALUE);

请参阅Java doc

答案 1 :(得分:0)

代码

Field userBalanceField = atmClass.getDeclaredField("userBalance");

建议userBalanceATM的字段,但

ATM.Data result = new ATM.Data(cardNumber, accountNumber, name, pinNumber);
userBalanceField.set(result, Integer.MAX_VALUE);

尝试设置userBalance对象的字段ATM.Data

如果字段userBalance位于ATM.Data,请尝试:

Field userBalanceField = ATM.Data.class.getDeclaredField("userBalance");

答案 2 :(得分:0)

InvocationTargetException 包装反射方法抛出的所有异常。这是因为Reflection API无视方法可以抛出的异常类型。

尝试捕捉:

Derived

然后使用:

InvocationTargetException

例如:

getCause();

这会告诉您 实际上 出错了什么。它还可以帮助我们调试代码。