Towards
Towards

Reputation: 21

Java reflection to invoke private methods and fields, because the call order is different, lead to the result is different

I want to use the Java reflection calls private method and fields.Below is my code:

package javaReflect.test;

public class PrivateCar {

    private String color;

    protected void drive() {
        System.out.println("this is private car! the color is:" + color);
    }
}

package javaReflect.test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PrivateCarReflect {

    public static void main(String[] args) throws Throwable {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        Class clazz = loader.loadClass("javaReflect.test.PrivateCar");

        PrivateCar pcar = (PrivateCar) clazz.newInstance();

        Field colorFld = clazz.getDeclaredField("color");
        colorFld.setAccessible(true);
        colorFld.set(pcar, "red");

        Method driveMtd = clazz.getDeclaredMethod("drive");
        driveMtd.setAccessible(true);
        driveMtd.invoke(pcar, (Object[]) null);

    }
}

I perform the main method, the result is this is private car! the color is:red. But when I change the calling sequence method and fields. Like this:

    Method driveMtd = clazz.getDeclaredMethod("drive");
    driveMtd.setAccessible(true);
    driveMtd.invoke(pcar, (Object[]) null);

    Field colorFld = clazz.getDeclaredField("color");
    colorFld.setAccessible(true);
    colorFld.set(pcar, "red");

Use reflection to invoke method first. The result is:

this is private car! the color is:null.

I don't know why it happens. What does exactly happen?

Upvotes: 1

Views: 596

Answers (2)

AxelH
AxelH

Reputation: 14572

You are accessing a variable before setting a value. Without Reflection, that would look like :

PrivateCar car = new PrivateCar();
car.drive(); //color is still null
car.color = "red";

Using the reflection won't change this order.

And without a surprise, your working example is like

PrivateCar car = new PrivateCar();
car.color = "red";
car.drive(); //color is 'red'

Upvotes: 6

SamCle88
SamCle88

Reputation: 275

You should set the color before testing it. That's why the second code snippet doesn't do what you expect. You can't use a value for a field before having set it correctly, so you shouldn't invoke a method using it before you have chosen it.

Upvotes: 0

Related Questions